1 /* System-dependent calls for tar.
3 Copyright 2003-2023 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3, or (at your option) any later
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include <system-ioctl.h>
25 #include <wordsplit.h>
27 #include <parse-datetime.h>
30 xexec (const char *cmd
)
34 argv
[0] = (char *) "/bin/sh";
35 argv
[1] = (char *) "-c";
36 argv
[2] = (char *) cmd
;
39 execv ("/bin/sh", argv
);
43 /* True if the archive is seekable via ioctl and MTIOCTOP,
44 or if it is not known whether it is seekable.
45 False if it is known to be not seekable. */
46 static bool mtioseekable_archive
;
49 mtioseek (bool count_files
, off_t count
)
51 if (mtioseekable_archive
)
54 struct mtop operation
;
55 operation
.mt_op
= (count_files
56 ? (count
< 0 ? MTBSF
: MTFSF
)
57 : (count
< 0 ? MTBSR
: MTFSR
));
59 ? INT_SUBTRACT_WRAPV (0, count
, &operation
.mt_count
)
60 : INT_ADD_WRAPV (count
, 0, &operation
.mt_count
))
61 && (0 <= rmtioctl (archive
, MTIOCTOP
, &operation
)
63 && 0 <= rmtioctl (archive
, MTIOCTOP
, &operation
))))
67 mtioseekable_archive
= false;
75 sys_get_archive_stat (void)
81 sys_file_is_archive (struct tar_stat_info
*p
)
87 sys_detect_dev_null_output (void)
89 static char const dev_null
[] = "nul";
91 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
92 || (! _isrmt (archive
)));
96 sys_wait_for_child (pid_t child_pid
, bool eof
)
101 sys_spawn_shell (void)
103 spawnl (P_WAIT
, getenv ("COMSPEC"), "-", 0);
106 /* stat() in djgpp's C library gives a constant number of 42 as the
107 uid and gid of a file. So, comparing an FTP'ed archive just after
108 unpack would fail on MSDOS. */
111 sys_compare_uid (struct stat
*a
, struct stat
*b
)
117 sys_compare_gid (struct stat
*a
, struct stat
*b
)
123 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
129 sys_truncate (int fd
)
131 return write (fd
, "", 0);
135 sys_write_archive_buffer (void)
137 return full_write (archive
, record_start
->buffer
, record_size
);
140 /* Set ARCHIVE for writing, then compressing an archive. */
142 sys_child_open_for_compress (void)
144 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
147 /* Set ARCHIVE for uncompressing, then reading an archive. */
149 sys_child_open_for_uncompress (void)
151 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
155 sys_exec_setmtime_script (const char *script_name
,
157 const char *file_name
,
161 FATAL_ERROR ((0, 0, _("--set-mtime-command not implemented on this platform")));
165 extern union block
*record_start
; /* FIXME */
168 sys_get_archive_stat (void)
170 bool remote
= _isrmt (archive
);
171 mtioseekable_archive
= true;
172 if (!remote
&& 0 <= archive
&& fstat (archive
, &archive_stat
) == 0)
174 if (!S_ISCHR (archive_stat
.st_mode
))
175 mtioseekable_archive
= false;
180 /* FIXME: This memset should not be needed. It is present only
181 because other parts of tar may incorrectly access
182 archive_stat even if it's not the archive status. */
183 memset (&archive_stat
, 0, sizeof archive_stat
);
190 sys_file_is_archive (struct tar_stat_info
*p
)
192 return (!dev_null_output
&& !_isrmt (archive
)
193 && p
->stat
.st_dev
== archive_stat
.st_dev
194 && p
->stat
.st_ino
== archive_stat
.st_ino
);
197 static char const dev_null
[] = "/dev/null";
199 /* Detect if outputting to "/dev/null". */
201 sys_detect_dev_null_output (void)
203 static struct stat dev_null_stat
;
205 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
206 || (! _isrmt (archive
)
207 && S_ISCHR (archive_stat
.st_mode
)
208 && (dev_null_stat
.st_ino
!= 0
209 || stat (dev_null
, &dev_null_stat
) == 0)
210 && archive_stat
.st_ino
== dev_null_stat
.st_ino
211 && archive_stat
.st_dev
== dev_null_stat
.st_dev
));
215 sys_wait_for_child (pid_t child_pid
, bool eof
)
221 while (waitpid (child_pid
, &wait_status
, 0) == -1)
224 waitpid_error (use_compress_program_option
);
228 if (WIFSIGNALED (wait_status
))
230 int sig
= WTERMSIG (wait_status
);
231 if (!(!eof
&& sig
== SIGPIPE
))
232 FATAL_ERROR ((0, 0, _("Child died with signal %d"), sig
));
234 else if (WEXITSTATUS (wait_status
) != 0)
235 FATAL_ERROR ((0, 0, _("Child returned status %d"),
236 WEXITSTATUS (wait_status
)));
241 sys_spawn_shell (void)
244 const char *shell
= getenv ("SHELL");
250 priv_set_restore_linkdir ();
251 execlp (shell
, "-sh", "-i", NULL
);
257 while (waitpid (child
, &wait_status
, 0) == -1)
260 waitpid_error (shell
);
267 sys_compare_uid (struct stat
*a
, struct stat
*b
)
269 return a
->st_uid
== b
->st_uid
;
273 sys_compare_gid (struct stat
*a
, struct stat
*b
)
275 return a
->st_gid
== b
->st_gid
;
279 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
281 return stat_data
->st_dev
== link_data
->st_dev
282 && stat_data
->st_ino
== link_data
->st_ino
;
286 sys_truncate (int fd
)
288 off_t pos
= lseek (fd
, (off_t
) 0, SEEK_CUR
);
289 return pos
< 0 ? -1 : ftruncate (fd
, pos
);
292 /* Return nonzero if NAME is the name of a regular file, or if the file
293 does not exist (so it would be created as a regular file). */
295 is_regular_file (const char *name
)
299 if (stat (name
, &stbuf
) == 0)
300 return S_ISREG (stbuf
.st_mode
);
302 return errno
== ENOENT
;
306 sys_write_archive_buffer (void)
308 return rmtwrite (archive
, record_start
->buffer
, record_size
);
311 #define PREAD 0 /* read file descriptor from pipe() */
312 #define PWRITE 1 /* write file descriptor from pipe() */
314 /* Work around GCC bug 109839. */
316 # pragma GCC diagnostic ignored "-Wanalyzer-fd-leak"
319 /* Duplicate file descriptor FROM into becoming INTO.
320 INTO is closed first and has to be the next available slot. */
322 xdup2 (int from
, int into
)
326 if (dup2 (from
, into
) < 0)
329 FATAL_ERROR ((0, e
, _("Cannot dup2")));
335 /* Propagate any failure of the grandchild back to the parent. */
336 static _Noreturn
void
337 wait_for_grandchild (pid_t pid
)
342 while (waitpid (pid
, &wait_status
, 0) == -1)
345 waitpid_error (use_compress_program_option
);
349 if (WIFSIGNALED (wait_status
))
350 raise (WTERMSIG (wait_status
));
351 else if (WEXITSTATUS (wait_status
) != 0)
352 exit_code
= WEXITSTATUS (wait_status
);
357 /* Set ARCHIVE for writing, then compressing an archive. */
359 sys_child_open_for_compress (void)
363 pid_t grandchild_pid
;
366 signal (SIGPIPE
, SIG_IGN
);
368 child_pid
= xfork ();
372 /* The parent tar is still here! Just clean up. */
374 archive
= parent_pipe
[PWRITE
];
375 xclose (parent_pipe
[PREAD
]);
379 /* The new born child tar is here! */
381 set_program_name (_("tar (child)"));
382 signal (SIGPIPE
, SIG_DFL
);
384 xdup2 (parent_pipe
[PREAD
], STDIN_FILENO
);
385 xclose (parent_pipe
[PWRITE
]);
387 /* Check if we need a grandchild tar. This happens only if either:
388 a) the file is to be accessed by rmt: compressor doesn't know how;
389 b) the file is not a plain file. */
391 if (!_remdev (archive_name_array
[0])
392 && is_regular_file (archive_name_array
[0]))
395 maybe_backup_file (archive_name_array
[0], 1);
397 /* We don't need a grandchild tar. Open the archive and launch the
399 if (strcmp (archive_name_array
[0], "-"))
401 archive
= creat (archive_name_array
[0], MODE_RW
);
404 int saved_errno
= errno
;
409 open_fatal (archive_name_array
[0]);
411 xdup2 (archive
, STDOUT_FILENO
);
413 priv_set_restore_linkdir ();
414 xexec (use_compress_program_option
);
417 /* We do need a grandchild tar. */
420 grandchild_pid
= xfork ();
422 if (grandchild_pid
== 0)
424 /* The newborn grandchild tar is here! Launch the compressor. */
426 set_program_name (_("tar (grandchild)"));
428 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
429 xclose (child_pipe
[PREAD
]);
430 priv_set_restore_linkdir ();
431 xexec (use_compress_program_option
);
434 /* The child tar is still here! */
436 /* Prepare for reblocking the data from the compressor into the archive. */
438 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
439 xclose (child_pipe
[PWRITE
]);
441 if (strcmp (archive_name_array
[0], "-") == 0)
442 archive
= STDOUT_FILENO
;
445 archive
= rmtcreat (archive_name_array
[0], MODE_RW
, rsh_command_option
);
447 open_fatal (archive_name_array
[0]);
450 /* Let's read out of the stdin pipe and write an archive. */
458 /* Assemble a record. */
460 for (length
= 0, cursor
= record_start
->buffer
;
461 length
< record_size
;
462 length
+= status
, cursor
+= status
)
464 size_t size
= record_size
- length
;
466 status
= safe_read (STDIN_FILENO
, cursor
, size
);
467 if (status
== SAFE_READ_ERROR
)
468 read_fatal (use_compress_program_option
);
473 /* Copy the record. */
477 /* We hit the end of the file. Write last record at
478 full length, as the only role of the grandchild is
479 doing proper reblocking. */
483 memset (record_start
->buffer
+ length
, 0, record_size
- length
);
484 status
= sys_write_archive_buffer ();
485 if (status
!= record_size
)
486 archive_write_error (status
);
489 /* There is nothing else to read, break out. */
493 status
= sys_write_archive_buffer ();
494 if (status
!= record_size
)
495 archive_write_error (status
);
498 wait_for_grandchild (grandchild_pid
);
502 run_decompress_program (void)
505 const char *p
, *prog
= NULL
;
507 int wsflags
= (WRDSF_DEFFLAGS
| WRDSF_ENV
| WRDSF_DOOFFS
) & ~WRDSF_NOVAR
;
509 ws
.ws_env
= (const char **) environ
;
512 for (p
= first_decompress_program (&i
); p
; p
= next_decompress_program (&i
))
516 WARNOPT (WARN_DECOMPRESS_PROGRAM
,
517 (0, errno
, _("cannot run %s"), prog
));
518 WARNOPT (WARN_DECOMPRESS_PROGRAM
,
519 (0, 0, _("trying %s"), p
));
521 if (wordsplit (p
, &ws
, wsflags
))
522 FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
523 p
, wordsplit_strerror (&ws
)));
524 wsflags
|= WRDSF_REUSE
;
525 memmove(ws
.ws_wordv
, ws
.ws_wordv
+ ws
.ws_offs
,
526 sizeof(ws
.ws_wordv
[0])*ws
.ws_wordc
);
527 ws
.ws_wordv
[ws
.ws_wordc
] = (char *) "-d";
529 execvp (ws
.ws_wordv
[0], ws
.ws_wordv
);
530 ws
.ws_wordv
[ws
.ws_wordc
] = NULL
;
533 FATAL_ERROR ((0, 0, _("unable to run decompression program")));
537 /* Set ARCHIVE for uncompressing, then reading an archive. */
539 sys_child_open_for_uncompress (void)
543 pid_t grandchild_pid
;
547 child_pid
= xfork ();
551 /* The parent tar is still here! Just clean up. */
553 archive
= parent_pipe
[PREAD
];
554 xclose (parent_pipe
[PWRITE
]);
558 /* The newborn child tar is here! */
560 set_program_name (_("tar (child)"));
561 signal (SIGPIPE
, SIG_DFL
);
563 xdup2 (parent_pipe
[PWRITE
], STDOUT_FILENO
);
564 xclose (parent_pipe
[PREAD
]);
566 /* Check if we need a grandchild tar. This happens only if either:
567 a) we're reading stdin: to force unblocking;
568 b) the file is to be accessed by rmt: compressor doesn't know how;
569 c) the file is not a plain file. */
571 if (strcmp (archive_name_array
[0], "-") != 0
572 && !_remdev (archive_name_array
[0])
573 && is_regular_file (archive_name_array
[0]))
575 /* We don't need a grandchild tar. Open the archive and launch the
578 archive
= open (archive_name_array
[0], O_RDONLY
| O_BINARY
, MODE_RW
);
580 open_fatal (archive_name_array
[0]);
581 xdup2 (archive
, STDIN_FILENO
);
582 priv_set_restore_linkdir ();
583 run_decompress_program ();
586 /* We do need a grandchild tar. */
589 grandchild_pid
= xfork ();
591 if (grandchild_pid
== 0)
593 /* The newborn grandchild tar is here! Launch the uncompressor. */
595 set_program_name (_("tar (grandchild)"));
597 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
598 xclose (child_pipe
[PWRITE
]);
599 priv_set_restore_linkdir ();
600 run_decompress_program ();
603 /* The child tar is still here! */
605 /* Prepare for unblocking the data from the archive into the
608 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
609 xclose (child_pipe
[PREAD
]);
611 if (strcmp (archive_name_array
[0], "-") == 0)
612 archive
= STDIN_FILENO
;
614 archive
= rmtopen (archive_name_array
[0], O_RDONLY
| O_BINARY
,
615 MODE_RW
, rsh_command_option
);
617 open_fatal (archive_name_array
[0]);
619 /* Let's read the archive and pipe it into stdout. */
628 clear_read_error_count ();
631 status
= rmtread (archive
, record_start
->buffer
, record_size
);
632 if (status
== SAFE_READ_ERROR
)
634 archive_read_error ();
639 cursor
= record_start
->buffer
;
643 count
= maximum
< BLOCKSIZE
? maximum
: BLOCKSIZE
;
644 if (full_write (STDOUT_FILENO
, cursor
, count
) != count
)
645 write_error (use_compress_program_option
);
651 xclose (STDOUT_FILENO
);
653 wait_for_grandchild (grandchild_pid
);
659 dec_to_env (char const *envar
, uintmax_t num
)
661 char buf
[UINTMAX_STRSIZE_BOUND
];
664 numstr
= STRINGIFY_BIGINT (num
, buf
);
665 if (setenv (envar
, numstr
, 1) != 0)
670 time_to_env (char const *envar
, struct timespec t
)
672 char buf
[TIMESPEC_STRSIZE_BOUND
];
673 if (setenv (envar
, code_timespec (t
, buf
), 1) != 0)
678 oct_to_env (char const *envar
, unsigned long num
)
680 char buf
[1+1+(sizeof(unsigned long)*CHAR_BIT
+2)/3];
682 snprintf (buf
, sizeof buf
, "0%lo", num
);
683 if (setenv (envar
, buf
, 1) != 0)
688 str_to_env (char const *envar
, char const *str
)
692 if (setenv (envar
, str
, 1) != 0)
700 chr_to_env (char const *envar
, char c
)
705 if (setenv (envar
, buf
, 1) != 0)
710 stat_to_env (char *name
, char type
, struct tar_stat_info
*st
)
712 str_to_env ("TAR_VERSION", PACKAGE_VERSION
);
713 str_to_env ("TAR_ARCHIVE", *archive_name_cursor
);
714 dec_to_env ("TAR_VOLUME", archive_name_cursor
- archive_name_array
+ 1);
715 dec_to_env ("TAR_BLOCKING_FACTOR", blocking_factor
);
716 str_to_env ("TAR_FORMAT",
717 archive_format_string (current_format
== DEFAULT_FORMAT
?
718 archive_format
: current_format
));
719 chr_to_env ("TAR_FILETYPE", type
);
720 oct_to_env ("TAR_MODE", st
->stat
.st_mode
);
721 str_to_env ("TAR_FILENAME", name
);
722 str_to_env ("TAR_REALNAME", st
->file_name
);
723 str_to_env ("TAR_UNAME", st
->uname
);
724 str_to_env ("TAR_GNAME", st
->gname
);
725 time_to_env ("TAR_ATIME", st
->atime
);
726 time_to_env ("TAR_MTIME", st
->mtime
);
727 time_to_env ("TAR_CTIME", st
->ctime
);
728 dec_to_env ("TAR_SIZE", st
->stat
.st_size
);
729 dec_to_env ("TAR_UID", st
->stat
.st_uid
);
730 dec_to_env ("TAR_GID", st
->stat
.st_gid
);
736 dec_to_env ("TAR_MINOR", minor (st
->stat
.st_rdev
));
737 dec_to_env ("TAR_MAJOR", major (st
->stat
.st_rdev
));
738 unsetenv ("TAR_LINKNAME");
743 unsetenv ("TAR_MINOR");
744 unsetenv ("TAR_MAJOR");
745 str_to_env ("TAR_LINKNAME", st
->link_name
);
749 unsetenv ("TAR_MINOR");
750 unsetenv ("TAR_MAJOR");
751 unsetenv ("TAR_LINKNAME");
756 static pid_t global_pid
;
757 static void (*pipe_handler
) (int sig
);
760 sys_exec_command (char *file_name
, int typechar
, struct tar_stat_info
*st
)
765 pipe_handler
= signal (SIGPIPE
, SIG_IGN
);
766 global_pid
= xfork ();
775 xdup2 (p
[PREAD
], STDIN_FILENO
);
778 stat_to_env (file_name
, typechar
, st
);
780 priv_set_restore_linkdir ();
781 xexec (to_command_option
);
785 sys_wait_command (void)
792 signal (SIGPIPE
, pipe_handler
);
793 while (waitpid (global_pid
, &status
, 0) == -1)
797 waitpid_error (to_command_option
);
801 if (WIFEXITED (status
))
803 if (!ignore_command_error_option
&& WEXITSTATUS (status
))
804 ERROR ((0, 0, _("%lu: Child returned status %d"),
805 (unsigned long) global_pid
, WEXITSTATUS (status
)));
807 else if (WIFSIGNALED (status
))
809 WARN ((0, 0, _("%lu: Child terminated on signal %d"),
810 (unsigned long) global_pid
, WTERMSIG (status
)));
813 ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
814 (unsigned long) global_pid
));
820 sys_exec_info_script (const char **archive_name
, int volume_number
)
823 char uintbuf
[UINTMAX_STRSIZE_BOUND
];
825 static void (*saved_handler
) (int sig
);
828 saved_handler
= signal (SIGPIPE
, SIG_IGN
);
843 fp
= fdopen (p
[PREAD
], "r");
844 rc
= getline (&buf
, &size
, fp
);
847 if (rc
> 0 && buf
[rc
-1] == '\n')
850 while (waitpid (pid
, &status
, 0) == -1)
853 signal (SIGPIPE
, saved_handler
);
854 waitpid_error (info_script_option
);
858 signal (SIGPIPE
, saved_handler
);
860 if (WIFEXITED (status
))
862 if (WEXITSTATUS (status
) == 0 && rc
> 0)
866 return WEXITSTATUS (status
);
874 setenv ("TAR_VERSION", PACKAGE_VERSION
, 1);
875 setenv ("TAR_ARCHIVE", *archive_name
, 1);
876 setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number
, uintbuf
), 1);
877 setenv ("TAR_BLOCKING_FACTOR",
878 STRINGIFY_BIGINT (blocking_factor
, uintbuf
), 1);
879 setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option
), 1);
880 setenv ("TAR_FORMAT",
881 archive_format_string (current_format
== DEFAULT_FORMAT
?
882 archive_format
: current_format
), 1);
883 setenv ("TAR_FD", STRINGIFY_BIGINT (p
[PWRITE
], uintbuf
), 1);
887 priv_set_restore_linkdir ();
888 xexec (info_script_option
);
892 sys_exec_checkpoint_script (const char *script_name
,
893 const char *archive_name
,
894 int checkpoint_number
)
897 char uintbuf
[UINTMAX_STRSIZE_BOUND
];
907 while (waitpid (pid
, &status
, 0) == -1)
910 waitpid_error (script_name
);
918 setenv ("TAR_VERSION", PACKAGE_VERSION
, 1);
919 setenv ("TAR_ARCHIVE", archive_name
, 1);
920 setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number
, uintbuf
), 1);
921 setenv ("TAR_BLOCKING_FACTOR",
922 STRINGIFY_BIGINT (blocking_factor
, uintbuf
), 1);
923 setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option
), 1);
924 setenv ("TAR_FORMAT",
925 archive_format_string (current_format
== DEFAULT_FORMAT
?
926 archive_format
: current_format
), 1);
927 priv_set_restore_linkdir ();
932 sys_exec_setmtime_script (const char *script_name
,
934 const char *file_name
,
950 FATAL_ERROR ((0, errno
, _("pipe failed")));
952 if ((pid
= xfork ()) == 0)
954 char *command
= xmalloc (strlen (script_name
) + strlen (file_name
) + 2);
956 strcpy (command
, script_name
);
957 strcat (command
, " ");
958 strcat (command
, file_name
);
960 if (dirfd
!= AT_FDCWD
)
963 FATAL_ERROR ((0, errno
, _("chdir failed")));
969 if (open (dev_null
, O_RDONLY
) == -1)
970 open_error (dev_null
);
972 if (dup2 (p
[1], 1) == -1)
973 FATAL_ERROR ((0, errno
, _("dup2 failed")));
976 priv_set_restore_linkdir ();
986 int n
= poll (&pfd
, 1, -1);
991 ERROR ((0, errno
, _("poll failed")));
998 if (pfd
.revents
& POLLIN
)
1000 if (buflen
== bufsize
)
1004 buffer
= x2nrealloc (buffer
, &bufsize
, 1);
1006 n
= read (pfd
.fd
, buffer
+ buflen
, bufsize
- buflen
);
1009 ERROR ((0, errno
, _("error reading output of %s"), script_name
));
1017 else if (pfd
.revents
& POLLHUP
)
1023 kill (SIGKILL
, pid
);
1025 sys_wait_for_child (pid
, false);
1035 ERROR ((0, 0, _("empty output from \"%s %s\""), script_name
, file_name
));
1039 cp
= memchr (buffer
, '\n', buflen
);
1044 if (buflen
== bufsize
)
1045 buffer
= x2nrealloc (buffer
, &bufsize
, 1);
1053 cp
= strptime (buffer
, fmt
, &tm
);
1056 ERROR ((0, 0, _("output from \"%s %s\" does not satisfy format string: %s"),
1057 script_name
, file_name
, buffer
));
1062 WARN ((0, 0, _("unconsumed output from \"%s %s\": %s"),
1063 script_name
, file_name
, cp
));
1069 if (t
== (time_t) -1)
1071 ERROR ((0, errno
, _("mktime failed")));
1081 else if (! parse_datetime (ts
, buffer
, NULL
))
1083 ERROR ((0, 0, _("unparsable output from \"%s %s\": %s"),
1084 script_name
, file_name
, buffer
));
1093 #endif /* not MSDOS */