Minor rewording
[tar.git] / src / system.c
blobba1d191e0824473a73b72ac2334804b497b6677e
1 /* System-dependent calls for tar.
3 Copyright (C) 2003, 2004, 2005, 2006, 2007 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
8 version.
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, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 #include <system.h>
20 #include <setenv.h>
22 #include "common.h"
23 #include <rmt.h>
24 #include <signal.h>
26 #if MSDOS
28 bool
29 sys_get_archive_stat (void)
31 return 0;
34 bool
35 sys_file_is_archive (struct tar_stat_info *p)
37 return false;
40 void
41 sys_save_archive_dev_ino (void)
45 void
46 sys_detect_dev_null_output (void)
48 static char const dev_null[] = "nul";
50 dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
51 || (! _isrmt (archive)));
54 void
55 sys_drain_input_pipe (void)
59 void
60 sys_wait_for_child (pid_t child_pid)
64 void
65 sys_spawn_shell (void)
67 spawnl (P_WAIT, getenv ("COMSPEC"), "-", 0);
70 /* stat() in djgpp's C library gives a constant number of 42 as the
71 uid and gid of a file. So, comparing an FTP'ed archive just after
72 unpack would fail on MSDOS. */
74 bool
75 sys_compare_uid (struct stat *a, struct stat *b)
77 return true;
80 bool
81 sys_compare_gid (struct stat *a, struct stat *b)
83 return true;
86 void
87 sys_compare_links (struct stat *link_data, struct stat *stat_data)
89 return true;
92 int
93 sys_truncate (int fd)
95 return write (fd, "", 0);
98 size_t
99 sys_write_archive_buffer (void)
101 return full_write (archive, record_start->buffer, record_size);
104 /* Set ARCHIVE for writing, then compressing an archive. */
105 void
106 sys_child_open_for_compress (void)
108 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
111 /* Set ARCHIVE for uncompressing, then reading an archive. */
112 void
113 sys_child_open_for_uncompress (void)
115 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
118 #else
120 extern union block *record_start; /* FIXME */
122 static struct stat archive_stat; /* stat block for archive file */
124 bool
125 sys_get_archive_stat (void)
127 return fstat (archive, &archive_stat) == 0;
130 bool
131 sys_file_is_archive (struct tar_stat_info *p)
133 return (ar_dev && p->stat.st_dev == ar_dev && p->stat.st_ino == ar_ino);
136 /* Save archive file inode and device numbers */
137 void
138 sys_save_archive_dev_ino (void)
140 if (!_isrmt (archive) && S_ISREG (archive_stat.st_mode))
142 ar_dev = archive_stat.st_dev;
143 ar_ino = archive_stat.st_ino;
145 else
146 ar_dev = 0;
149 /* Detect if outputting to "/dev/null". */
150 void
151 sys_detect_dev_null_output (void)
153 static char const dev_null[] = "/dev/null";
154 struct stat dev_null_stat;
156 dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
157 || (! _isrmt (archive)
158 && S_ISCHR (archive_stat.st_mode)
159 && stat (dev_null, &dev_null_stat) == 0
160 && archive_stat.st_dev == dev_null_stat.st_dev
161 && archive_stat.st_ino == dev_null_stat.st_ino));
164 /* Manage to fully drain a pipe we might be reading, so to not break it on
165 the producer after the EOF block. FIXME: one of these days, GNU tar
166 might become clever enough to just stop working, once there is no more
167 work to do, we might have to revise this area in such time. */
169 void
170 sys_drain_input_pipe (void)
172 size_t r;
174 if (access_mode == ACCESS_READ
175 && ! _isrmt (archive)
176 && (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
177 while ((r = rmtread (archive, record_start->buffer, record_size)) != 0
178 && r != SAFE_READ_ERROR)
179 continue;
182 void
183 sys_wait_for_child (pid_t child_pid)
185 if (child_pid)
187 int wait_status;
189 while (waitpid (child_pid, &wait_status, 0) == -1)
190 if (errno != EINTR)
192 waitpid_error (use_compress_program_option);
193 break;
196 if (WIFSIGNALED (wait_status))
197 ERROR ((0, 0, _("Child died with signal %d"),
198 WTERMSIG (wait_status)));
199 else if (WEXITSTATUS (wait_status) != 0)
200 ERROR ((0, 0, _("Child returned status %d"),
201 WEXITSTATUS (wait_status)));
205 void
206 sys_spawn_shell (void)
208 pid_t child;
209 const char *shell = getenv ("SHELL");
210 if (! shell)
211 shell = "/bin/sh";
212 child = xfork ();
213 if (child == 0)
215 execlp (shell, "-sh", "-i", (char *) 0);
216 exec_fatal (shell);
218 else
220 int wait_status;
221 while (waitpid (child, &wait_status, 0) == -1)
222 if (errno != EINTR)
224 waitpid_error (shell);
225 break;
230 bool
231 sys_compare_uid (struct stat *a, struct stat *b)
233 return a->st_uid == b->st_uid;
236 bool
237 sys_compare_gid (struct stat *a, struct stat *b)
239 return a->st_gid == b->st_gid;
242 bool
243 sys_compare_links (struct stat *link_data, struct stat *stat_data)
245 return stat_data->st_dev == link_data->st_dev
246 && stat_data->st_ino == link_data->st_ino;
250 sys_truncate (int fd)
252 off_t pos = lseek (fd, (off_t) 0, SEEK_CUR);
253 return pos < 0 ? -1 : ftruncate (fd, pos);
256 /* Return nonzero if NAME is the name of a regular file, or if the file
257 does not exist (so it would be created as a regular file). */
258 static int
259 is_regular_file (const char *name)
261 struct stat stbuf;
263 if (stat (name, &stbuf) == 0)
264 return S_ISREG (stbuf.st_mode);
265 else
266 return errno == ENOENT;
269 size_t
270 sys_write_archive_buffer (void)
272 return rmtwrite (archive, record_start->buffer, record_size);
275 #define PREAD 0 /* read file descriptor from pipe() */
276 #define PWRITE 1 /* write file descriptor from pipe() */
278 /* Duplicate file descriptor FROM into becoming INTO.
279 INTO is closed first and has to be the next available slot. */
280 static void
281 xdup2 (int from, int into)
283 if (from != into)
285 int status = close (into);
287 if (status != 0 && errno != EBADF)
289 int e = errno;
290 FATAL_ERROR ((0, e, _("Cannot close")));
292 status = dup (from);
293 if (status != into)
295 if (status < 0)
297 int e = errno;
298 FATAL_ERROR ((0, e, _("Cannot dup")));
300 abort ();
302 xclose (from);
306 /* Set ARCHIVE for writing, then compressing an archive. */
307 pid_t
308 sys_child_open_for_compress (void)
310 int parent_pipe[2];
311 int child_pipe[2];
312 pid_t grandchild_pid;
313 pid_t child_pid;
314 int wait_status;
316 xpipe (parent_pipe);
317 child_pid = xfork ();
319 if (child_pid > 0)
321 /* The parent tar is still here! Just clean up. */
323 archive = parent_pipe[PWRITE];
324 xclose (parent_pipe[PREAD]);
325 return child_pid;
328 /* The new born child tar is here! */
330 program_name = _("tar (child)");
332 xdup2 (parent_pipe[PREAD], STDIN_FILENO);
333 xclose (parent_pipe[PWRITE]);
335 /* Check if we need a grandchild tar. This happens only if either:
336 a) the file is to be accessed by rmt: compressor doesn't know how;
337 b) the file is not a plain file. */
339 if (!_remdev (archive_name_array[0])
340 && is_regular_file (archive_name_array[0]))
342 if (backup_option)
343 maybe_backup_file (archive_name_array[0], 1);
345 /* We don't need a grandchild tar. Open the archive and launch the
346 compressor. */
347 if (strcmp (archive_name_array[0], "-"))
349 archive = creat (archive_name_array[0], MODE_RW);
350 if (archive < 0)
352 int saved_errno = errno;
354 if (backup_option)
355 undo_last_backup ();
356 errno = saved_errno;
357 open_fatal (archive_name_array[0]);
359 xdup2 (archive, STDOUT_FILENO);
361 execlp (use_compress_program_option, use_compress_program_option, NULL);
362 exec_fatal (use_compress_program_option);
365 /* We do need a grandchild tar. */
367 xpipe (child_pipe);
368 grandchild_pid = xfork ();
370 if (grandchild_pid == 0)
372 /* The newborn grandchild tar is here! Launch the compressor. */
374 program_name = _("tar (grandchild)");
376 xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
377 xclose (child_pipe[PREAD]);
378 execlp (use_compress_program_option, use_compress_program_option,
379 (char *) 0);
380 exec_fatal (use_compress_program_option);
383 /* The child tar is still here! */
385 /* Prepare for reblocking the data from the compressor into the archive. */
387 xdup2 (child_pipe[PREAD], STDIN_FILENO);
388 xclose (child_pipe[PWRITE]);
390 if (strcmp (archive_name_array[0], "-") == 0)
391 archive = STDOUT_FILENO;
392 else
394 archive = rmtcreat (archive_name_array[0], MODE_RW, rsh_command_option);
395 if (archive < 0)
396 open_fatal (archive_name_array[0]);
399 /* Let's read out of the stdin pipe and write an archive. */
401 while (1)
403 size_t status = 0;
404 char *cursor;
405 size_t length;
407 /* Assemble a record. */
409 for (length = 0, cursor = record_start->buffer;
410 length < record_size;
411 length += status, cursor += status)
413 size_t size = record_size - length;
415 status = safe_read (STDIN_FILENO, cursor, size);
416 if (status == SAFE_READ_ERROR)
417 read_fatal (use_compress_program_option);
418 if (status == 0)
419 break;
422 /* Copy the record. */
424 if (status == 0)
426 /* We hit the end of the file. Write last record at
427 full length, as the only role of the grandchild is
428 doing proper reblocking. */
430 if (length > 0)
432 memset (record_start->buffer + length, 0, record_size - length);
433 status = sys_write_archive_buffer ();
434 if (status != record_size)
435 archive_write_error (status);
438 /* There is nothing else to read, break out. */
439 break;
442 status = sys_write_archive_buffer ();
443 if (status != record_size)
444 archive_write_error (status);
447 /* Propagate any failure of the grandchild back to the parent. */
449 while (waitpid (grandchild_pid, &wait_status, 0) == -1)
450 if (errno != EINTR)
452 waitpid_error (use_compress_program_option);
453 break;
456 if (WIFSIGNALED (wait_status))
458 kill (child_pid, WTERMSIG (wait_status));
459 exit_status = TAREXIT_FAILURE;
461 else if (WEXITSTATUS (wait_status) != 0)
462 exit_status = WEXITSTATUS (wait_status);
464 exit (exit_status);
467 /* Set ARCHIVE for uncompressing, then reading an archive. */
468 pid_t
469 sys_child_open_for_uncompress (void)
471 int parent_pipe[2];
472 int child_pipe[2];
473 pid_t grandchild_pid;
474 pid_t child_pid;
475 int wait_status;
477 xpipe (parent_pipe);
478 child_pid = xfork ();
480 if (child_pid > 0)
482 /* The parent tar is still here! Just clean up. */
484 archive = parent_pipe[PREAD];
485 xclose (parent_pipe[PWRITE]);
486 return child_pid;
489 /* The newborn child tar is here! */
491 program_name = _("tar (child)");
493 xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
494 xclose (parent_pipe[PREAD]);
496 /* Check if we need a grandchild tar. This happens only if either:
497 a) we're reading stdin: to force unblocking;
498 b) the file is to be accessed by rmt: compressor doesn't know how;
499 c) the file is not a plain file. */
501 if (strcmp (archive_name_array[0], "-") != 0
502 && !_remdev (archive_name_array[0])
503 && is_regular_file (archive_name_array[0]))
505 /* We don't need a grandchild tar. Open the archive and lauch the
506 uncompressor. */
508 archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW);
509 if (archive < 0)
510 open_fatal (archive_name_array[0]);
511 xdup2 (archive, STDIN_FILENO);
512 execlp (use_compress_program_option, use_compress_program_option,
513 "-d", (char *) 0);
514 exec_fatal (use_compress_program_option);
517 /* We do need a grandchild tar. */
519 xpipe (child_pipe);
520 grandchild_pid = xfork ();
522 if (grandchild_pid == 0)
524 /* The newborn grandchild tar is here! Launch the uncompressor. */
526 program_name = _("tar (grandchild)");
528 xdup2 (child_pipe[PREAD], STDIN_FILENO);
529 xclose (child_pipe[PWRITE]);
530 execlp (use_compress_program_option, use_compress_program_option,
531 "-d", (char *) 0);
532 exec_fatal (use_compress_program_option);
535 /* The child tar is still here! */
537 /* Prepare for unblocking the data from the archive into the
538 uncompressor. */
540 xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
541 xclose (child_pipe[PREAD]);
543 if (strcmp (archive_name_array[0], "-") == 0)
544 archive = STDIN_FILENO;
545 else
546 archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
547 MODE_RW, rsh_command_option);
548 if (archive < 0)
549 open_fatal (archive_name_array[0]);
551 /* Let's read the archive and pipe it into stdout. */
553 while (1)
555 char *cursor;
556 size_t maximum;
557 size_t count;
558 size_t status;
560 clear_read_error_count ();
562 error_loop:
563 status = rmtread (archive, record_start->buffer, record_size);
564 if (status == SAFE_READ_ERROR)
566 archive_read_error ();
567 goto error_loop;
569 if (status == 0)
570 break;
571 cursor = record_start->buffer;
572 maximum = status;
573 while (maximum)
575 count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE;
576 if (full_write (STDOUT_FILENO, cursor, count) != count)
577 write_error (use_compress_program_option);
578 cursor += count;
579 maximum -= count;
583 xclose (STDOUT_FILENO);
585 /* Propagate any failure of the grandchild back to the parent. */
587 while (waitpid (grandchild_pid, &wait_status, 0) == -1)
588 if (errno != EINTR)
590 waitpid_error (use_compress_program_option);
591 break;
594 if (WIFSIGNALED (wait_status))
596 kill (child_pid, WTERMSIG (wait_status));
597 exit_status = TAREXIT_FAILURE;
599 else if (WEXITSTATUS (wait_status) != 0)
600 exit_status = WEXITSTATUS (wait_status);
602 exit (exit_status);
607 static void
608 dec_to_env (char *envar, uintmax_t num)
610 char buf[UINTMAX_STRSIZE_BOUND];
611 char *numstr;
613 numstr = STRINGIFY_BIGINT (num, buf);
614 if (setenv (envar, numstr, 1) != 0)
615 xalloc_die ();
618 static void
619 time_to_env (char *envar, struct timespec t)
621 char buf[TIMESPEC_STRSIZE_BOUND];
622 if (setenv (envar, code_timespec (t, buf), 1) != 0)
623 xalloc_die ();
626 static void
627 oct_to_env (char *envar, unsigned long num)
629 char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
631 snprintf (buf, sizeof buf, "0%lo", num);
632 if (setenv (envar, buf, 1) != 0)
633 xalloc_die ();
636 static void
637 str_to_env (char *envar, char const *str)
639 if (str)
641 if (setenv (envar, str, 1) != 0)
642 xalloc_die ();
644 else
645 unsetenv (envar);
648 static void
649 chr_to_env (char *envar, char c)
651 char buf[2];
652 buf[0] = c;
653 buf[1] = 0;
654 if (setenv (envar, buf, 1) != 0)
655 xalloc_die ();
658 static void
659 stat_to_env (char *name, char type, struct tar_stat_info *st)
661 str_to_env ("TAR_VERSION", PACKAGE_VERSION);
662 chr_to_env ("TAR_FILETYPE", type);
663 oct_to_env ("TAR_MODE", st->stat.st_mode);
664 str_to_env ("TAR_FILENAME", name);
665 str_to_env ("TAR_REALNAME", st->file_name);
666 str_to_env ("TAR_UNAME", st->uname);
667 str_to_env ("TAR_GNAME", st->gname);
668 time_to_env ("TAR_ATIME", st->atime);
669 time_to_env ("TAR_MTIME", st->mtime);
670 time_to_env ("TAR_CTIME", st->ctime);
671 dec_to_env ("TAR_SIZE", st->stat.st_size);
672 dec_to_env ("TAR_UID", st->stat.st_uid);
673 dec_to_env ("TAR_GID", st->stat.st_gid);
675 switch (type)
677 case 'b':
678 case 'c':
679 dec_to_env ("TAR_MINOR", minor (st->stat.st_rdev));
680 dec_to_env ("TAR_MAJOR", major (st->stat.st_rdev));
681 unsetenv ("TAR_LINKNAME");
682 break;
684 case 'l':
685 case 'h':
686 unsetenv ("TAR_MINOR");
687 unsetenv ("TAR_MAJOR");
688 str_to_env ("TAR_LINKNAME", st->link_name);
689 break;
691 default:
692 unsetenv ("TAR_MINOR");
693 unsetenv ("TAR_MAJOR");
694 unsetenv ("TAR_LINKNAME");
695 break;
699 static pid_t global_pid;
700 static RETSIGTYPE (*pipe_handler) (int sig);
703 sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
705 int p[2];
706 char *argv[4];
708 xpipe (p);
709 pipe_handler = signal (SIGPIPE, SIG_IGN);
710 global_pid = xfork ();
712 if (global_pid != 0)
714 xclose (p[PREAD]);
715 return p[PWRITE];
718 /* Child */
719 xdup2 (p[PREAD], STDIN_FILENO);
720 xclose (p[PWRITE]);
722 stat_to_env (file_name, typechar, st);
724 argv[0] = "/bin/sh";
725 argv[1] = "-c";
726 argv[2] = to_command_option;
727 argv[3] = NULL;
729 execv ("/bin/sh", argv);
731 exec_fatal (file_name);
734 void
735 sys_wait_command (void)
737 int status;
739 if (global_pid < 0)
740 return;
742 signal (SIGPIPE, pipe_handler);
743 while (waitpid (global_pid, &status, 0) == -1)
744 if (errno != EINTR)
746 global_pid = -1;
747 waitpid_error (to_command_option);
748 return;
751 if (WIFEXITED (status))
753 if (!ignore_command_error_option && WEXITSTATUS (status))
754 ERROR ((0, 0, _("%lu: Child returned status %d"),
755 (unsigned long) global_pid, WEXITSTATUS (status)));
757 else if (WIFSIGNALED (status))
759 WARN ((0, 0, _("%lu: Child terminated on signal %d"),
760 (unsigned long) global_pid, WTERMSIG (status)));
762 else
763 ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
764 (unsigned long) global_pid));
766 global_pid = -1;
770 sys_exec_info_script (const char **archive_name, int volume_number)
772 pid_t pid;
773 char *argv[4];
774 char uintbuf[UINTMAX_STRSIZE_BOUND];
775 int p[2];
777 xpipe (p);
778 pipe_handler = signal (SIGPIPE, SIG_IGN);
780 pid = xfork ();
782 if (pid != 0)
784 /* Master */
786 int rc;
787 int status;
788 char *buf;
789 size_t size = 0;
790 FILE *fp;
792 xclose (p[PWRITE]);
793 fp = fdopen (p[PREAD], "r");
794 rc = getline (&buf, &size, fp);
795 fclose (fp);
797 if (rc > 0 && buf[rc-1] == '\n')
798 buf[--rc] = 0;
800 while (waitpid (pid, &status, 0) == -1)
801 if (errno != EINTR)
803 waitpid_error (info_script_option);
804 return -1;
807 if (WIFEXITED (status))
809 if (WEXITSTATUS (status) == 0 && rc > 0)
810 *archive_name = buf;
811 else
812 free (buf);
813 return WEXITSTATUS (status);
816 free (buf);
817 return -1;
820 /* Child */
821 setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
822 setenv ("TAR_ARCHIVE", *archive_name, 1);
823 setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
824 setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
825 setenv ("TAR_FORMAT",
826 archive_format_string (current_format == DEFAULT_FORMAT ?
827 archive_format : current_format), 1);
828 setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1);
830 xclose (p[PREAD]);
832 argv[0] = "/bin/sh";
833 argv[1] = "-c";
834 argv[2] = (char*) info_script_option;
835 argv[3] = NULL;
837 execv (argv[0], argv);
839 exec_fatal (info_script_option);
843 #endif /* not MSDOS */