]> Dogcows Code - chaz/tar/blobdiff - src/system.c
New option --full-time.
[chaz/tar] / src / system.c
index 63f9849cf9a027f956e811a23398face0e7f6ac8..d646822c4a6ccc65ae0ad098b1b1f47956db6dd4 100644 (file)
@@ -1,10 +1,11 @@
 /* System-dependent calls for tar.
 
 /* System-dependent calls for tar.
 
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007,
+   2008 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any later
+   Free Software Foundation; either version 3, or (at your option) any later
    version.
 
    This program is distributed in the hope that it will be useful, but
    version.
 
    This program is distributed in the hope that it will be useful, but
@@ -51,12 +52,7 @@ sys_detect_dev_null_output (void)
 }
 
 void
 }
 
 void
-sys_drain_input_pipe (void)
-{
-}
-
-void
-sys_wait_for_child (pid_t child_pid)
+sys_wait_for_child (pid_t child_pid, bool eof)
 {
 }
 
 {
 }
 
@@ -160,26 +156,8 @@ sys_detect_dev_null_output (void)
                         && archive_stat.st_ino == dev_null_stat.st_ino));
 }
 
                         && archive_stat.st_ino == dev_null_stat.st_ino));
 }
 
-/* Manage to fully drain a pipe we might be reading, so to not break it on
-   the producer after the EOF block.  FIXME: one of these days, GNU tar
-   might become clever enough to just stop working, once there is no more
-   work to do, we might have to revise this area in such time.  */
-
 void
 void
-sys_drain_input_pipe (void)
-{
-  size_t r;
-
-  if (access_mode == ACCESS_READ
-      && ! _isrmt (archive)
-      && (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
-    while ((r = rmtread (archive, record_start->buffer, record_size)) != 0
-          && r != SAFE_READ_ERROR)
-      continue;
-}
-
-void
-sys_wait_for_child (pid_t child_pid)
+sys_wait_for_child (pid_t child_pid, bool eof)
 {
   if (child_pid)
     {
 {
   if (child_pid)
     {
@@ -193,11 +171,14 @@ sys_wait_for_child (pid_t child_pid)
          }
 
       if (WIFSIGNALED (wait_status))
          }
 
       if (WIFSIGNALED (wait_status))
-       ERROR ((0, 0, _("Child died with signal %d"),
-               WTERMSIG (wait_status)));
+       {
+         int sig = WTERMSIG (wait_status);
+         if (!(!eof && sig == SIGPIPE))
+           FATAL_ERROR ((0, 0, _("Child died with signal %d"), sig));
+       }
       else if (WEXITSTATUS (wait_status) != 0)
       else if (WEXITSTATUS (wait_status) != 0)
-       ERROR ((0, 0, _("Child returned status %d"),
-               WEXITSTATUS (wait_status)));
+       FATAL_ERROR ((0, 0, _("Child returned status %d"),
+                     WEXITSTATUS (wait_status)));
     }
 }
 
     }
 }
 
@@ -302,6 +283,30 @@ xdup2 (int from, int into)
     }
 }
 
     }
 }
 
+void wait_for_grandchild (pid_t pid) __attribute__ ((__noreturn__));
+
+/* Propagate any failure of the grandchild back to the parent.  */
+void
+wait_for_grandchild (pid_t pid)
+{
+  int wait_status;
+  int exit_code = 0;
+  
+  while (waitpid (pid, &wait_status, 0) == -1)
+    if (errno != EINTR)
+      {
+       waitpid_error (use_compress_program_option);
+       break;
+      }
+
+  if (WIFSIGNALED (wait_status))
+    raise (WTERMSIG (wait_status));
+  else if (WEXITSTATUS (wait_status) != 0)
+    exit_code = WEXITSTATUS (wait_status);
+  
+  exit (exit_code);
+}
+
 /* Set ARCHIVE for writing, then compressing an archive.  */
 pid_t
 sys_child_open_for_compress (void)
 /* Set ARCHIVE for writing, then compressing an archive.  */
 pid_t
 sys_child_open_for_compress (void)
@@ -310,7 +315,6 @@ sys_child_open_for_compress (void)
   int child_pipe[2];
   pid_t grandchild_pid;
   pid_t child_pid;
   int child_pipe[2];
   pid_t grandchild_pid;
   pid_t child_pid;
-  int wait_status;
 
   xpipe (parent_pipe);
   child_pid = xfork ();
 
   xpipe (parent_pipe);
   child_pid = xfork ();
@@ -326,8 +330,9 @@ sys_child_open_for_compress (void)
 
   /* The new born child tar is here!  */
 
 
   /* The new born child tar is here!  */
 
-  program_name = _("tar (child)");
-
+  set_program_name (_("tar (child)"));
+  signal (SIGPIPE, SIG_DFL);
+  
   xdup2 (parent_pipe[PREAD], STDIN_FILENO);
   xclose (parent_pipe[PWRITE]);
 
   xdup2 (parent_pipe[PREAD], STDIN_FILENO);
   xclose (parent_pipe[PWRITE]);
 
@@ -349,7 +354,7 @@ sys_child_open_for_compress (void)
          if (archive < 0)
            {
              int saved_errno = errno;
          if (archive < 0)
            {
              int saved_errno = errno;
-             
+
              if (backup_option)
                undo_last_backup ();
              errno = saved_errno;
              if (backup_option)
                undo_last_backup ();
              errno = saved_errno;
@@ -370,7 +375,7 @@ sys_child_open_for_compress (void)
     {
       /* The newborn grandchild tar is here!  Launch the compressor.  */
 
     {
       /* The newborn grandchild tar is here!  Launch the compressor.  */
 
-      program_name = _("tar (grandchild)");
+      set_program_name (_("tar (grandchild)"));
 
       xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
       xclose (child_pipe[PREAD]);
 
       xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
       xclose (child_pipe[PREAD]);
@@ -443,24 +448,7 @@ sys_child_open_for_compress (void)
        archive_write_error (status);
     }
 
        archive_write_error (status);
     }
 
-  /* Propagate any failure of the grandchild back to the parent.  */
-
-  while (waitpid (grandchild_pid, &wait_status, 0) == -1)
-    if (errno != EINTR)
-      {
-       waitpid_error (use_compress_program_option);
-       break;
-      }
-
-  if (WIFSIGNALED (wait_status))
-    {
-      kill (child_pid, WTERMSIG (wait_status));
-      exit_status = TAREXIT_FAILURE;
-    }
-  else if (WEXITSTATUS (wait_status) != 0)
-    exit_status = WEXITSTATUS (wait_status);
-
-  exit (exit_status);
+  wait_for_grandchild (grandchild_pid);
 }
 
 /* Set ARCHIVE for uncompressing, then reading an archive.  */
 }
 
 /* Set ARCHIVE for uncompressing, then reading an archive.  */
@@ -471,7 +459,6 @@ sys_child_open_for_uncompress (void)
   int child_pipe[2];
   pid_t grandchild_pid;
   pid_t child_pid;
   int child_pipe[2];
   pid_t grandchild_pid;
   pid_t child_pid;
-  int wait_status;
 
   xpipe (parent_pipe);
   child_pid = xfork ();
 
   xpipe (parent_pipe);
   child_pid = xfork ();
@@ -487,8 +474,9 @@ sys_child_open_for_uncompress (void)
 
   /* The newborn child tar is here!  */
 
 
   /* The newborn child tar is here!  */
 
-  program_name = _("tar (child)");
-
+  set_program_name (_("tar (child)"));
+  signal (SIGPIPE, SIG_DFL);
+  
   xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
   xclose (parent_pipe[PREAD]);
 
   xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
   xclose (parent_pipe[PREAD]);
 
@@ -522,7 +510,7 @@ sys_child_open_for_uncompress (void)
     {
       /* The newborn grandchild tar is here!  Launch the uncompressor.  */
 
     {
       /* The newborn grandchild tar is here!  Launch the uncompressor.  */
 
-      program_name = _("tar (grandchild)");
+      set_program_name (_("tar (grandchild)"));
 
       xdup2 (child_pipe[PREAD], STDIN_FILENO);
       xclose (child_pipe[PWRITE]);
 
       xdup2 (child_pipe[PREAD], STDIN_FILENO);
       xclose (child_pipe[PWRITE]);
@@ -581,24 +569,7 @@ sys_child_open_for_uncompress (void)
 
   xclose (STDOUT_FILENO);
 
 
   xclose (STDOUT_FILENO);
 
-  /* Propagate any failure of the grandchild back to the parent.  */
-
-  while (waitpid (grandchild_pid, &wait_status, 0) == -1)
-    if (errno != EINTR)
-      {
-       waitpid_error (use_compress_program_option);
-       break;
-      }
-
-  if (WIFSIGNALED (wait_status))
-    {
-      kill (child_pid, WTERMSIG (wait_status));
-      exit_status = TAREXIT_FAILURE;
-    }
-  else if (WEXITSTATUS (wait_status) != 0)
-    exit_status = WEXITSTATUS (wait_status);
-
-  exit (exit_status);
+  wait_for_grandchild (grandchild_pid);
 }
 
 \f
 }
 
 \f
@@ -658,6 +629,12 @@ static void
 stat_to_env (char *name, char type, struct tar_stat_info *st)
 {
   str_to_env ("TAR_VERSION", PACKAGE_VERSION);
 stat_to_env (char *name, char type, struct tar_stat_info *st)
 {
   str_to_env ("TAR_VERSION", PACKAGE_VERSION);
+  str_to_env ("TAR_ARCHIVE", *archive_name_cursor);
+  dec_to_env ("TAR_VOLUME", archive_name_cursor - archive_name_array + 1);
+  dec_to_env ("TAR_BLOCKING_FACTOR", blocking_factor);
+  str_to_env ("TAR_FORMAT",
+             archive_format_string (current_format == DEFAULT_FORMAT ?
+                                    archive_format : current_format));
   chr_to_env ("TAR_FILETYPE", type);
   oct_to_env ("TAR_MODE", st->stat.st_mode);
   str_to_env ("TAR_FILENAME", name);
   chr_to_env ("TAR_FILETYPE", type);
   oct_to_env ("TAR_MODE", st->stat.st_mode);
   str_to_env ("TAR_FILENAME", name);
@@ -695,7 +672,7 @@ stat_to_env (char *name, char type, struct tar_stat_info *st)
     }
 }
 
     }
 }
 
-static pid_t pid;
+static pid_t global_pid;
 static RETSIGTYPE (*pipe_handler) (int sig);
 
 int
 static RETSIGTYPE (*pipe_handler) (int sig);
 
 int
@@ -706,9 +683,9 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
 
   xpipe (p);
   pipe_handler = signal (SIGPIPE, SIG_IGN);
 
   xpipe (p);
   pipe_handler = signal (SIGPIPE, SIG_IGN);
-  pid = xfork ();
+  global_pid = xfork ();
 
 
-  if (pid != 0)
+  if (global_pid != 0)
     {
       xclose (p[PREAD]);
       return p[PWRITE];
     {
       xclose (p[PREAD]);
       return p[PWRITE];
@@ -735,14 +712,14 @@ sys_wait_command (void)
 {
   int status;
 
 {
   int status;
 
-  if (pid < 0)
+  if (global_pid < 0)
     return;
 
   signal (SIGPIPE, pipe_handler);
     return;
 
   signal (SIGPIPE, pipe_handler);
-  while (waitpid (pid, &status, 0) == -1)
+  while (waitpid (global_pid, &status, 0) == -1)
     if (errno != EINTR)
       {
     if (errno != EINTR)
       {
-        pid = -1;
+        global_pid = -1;
         waitpid_error (to_command_option);
         return;
       }
         waitpid_error (to_command_option);
         return;
       }
@@ -751,18 +728,18 @@ sys_wait_command (void)
     {
       if (!ignore_command_error_option && WEXITSTATUS (status))
        ERROR ((0, 0, _("%lu: Child returned status %d"),
     {
       if (!ignore_command_error_option && WEXITSTATUS (status))
        ERROR ((0, 0, _("%lu: Child returned status %d"),
-               (unsigned long) pid, WEXITSTATUS (status)));
+               (unsigned long) global_pid, WEXITSTATUS (status)));
     }
   else if (WIFSIGNALED (status))
     {
       WARN ((0, 0, _("%lu: Child terminated on signal %d"),
     }
   else if (WIFSIGNALED (status))
     {
       WARN ((0, 0, _("%lu: Child terminated on signal %d"),
-            (unsigned long) pid, WTERMSIG (status)));
+            (unsigned long) global_pid, WTERMSIG (status)));
     }
   else
     ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
     }
   else
     ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
-           (unsigned long) pid));
+           (unsigned long) global_pid));
 
 
-  pid = -1;
+  global_pid = -1;
 }
 
 int
 }
 
 int
@@ -772,9 +749,10 @@ sys_exec_info_script (const char **archive_name, int volume_number)
   char *argv[4];
   char uintbuf[UINTMAX_STRSIZE_BOUND];
   int p[2];
   char *argv[4];
   char uintbuf[UINTMAX_STRSIZE_BOUND];
   int p[2];
+  static RETSIGTYPE (*saved_handler) (int sig);
   
   xpipe (p);
   
   xpipe (p);
-  pipe_handler = signal (SIGPIPE, SIG_IGN);
+  saved_handler = signal (SIGPIPE, SIG_IGN);
 
   pid = xfork ();
 
 
   pid = xfork ();
 
@@ -784,10 +762,10 @@ sys_exec_info_script (const char **archive_name, int volume_number)
 
       int rc;
       int status;
 
       int rc;
       int status;
-      char *buf;
+      char *buf = NULL;
       size_t size = 0;
       FILE *fp;
       size_t size = 0;
       FILE *fp;
-      
+
       xclose (p[PWRITE]);
       fp = fdopen (p[PREAD], "r");
       rc = getline (&buf, &size, fp);
       xclose (p[PWRITE]);
       fp = fdopen (p[PREAD], "r");
       rc = getline (&buf, &size, fp);
@@ -795,13 +773,16 @@ sys_exec_info_script (const char **archive_name, int volume_number)
 
       if (rc > 0 && buf[rc-1] == '\n')
        buf[--rc] = 0;
 
       if (rc > 0 && buf[rc-1] == '\n')
        buf[--rc] = 0;
-      
+
       while (waitpid (pid, &status, 0) == -1)
        if (errno != EINTR)
          {
       while (waitpid (pid, &status, 0) == -1)
        if (errno != EINTR)
          {
+           signal (SIGPIPE, saved_handler);
            waitpid_error (info_script_option);
            return -1;
          }
            waitpid_error (info_script_option);
            return -1;
          }
+
+      signal (SIGPIPE, saved_handler);
       
       if (WIFEXITED (status))
        {
       
       if (WIFEXITED (status))
        {
@@ -811,7 +792,7 @@ sys_exec_info_script (const char **archive_name, int volume_number)
            free (buf);
          return WEXITSTATUS (status);
        }
            free (buf);
          return WEXITSTATUS (status);
        }
-      
+
       free (buf);
       return -1;
     }
       free (buf);
       return -1;
     }
@@ -820,13 +801,15 @@ sys_exec_info_script (const char **archive_name, int volume_number)
   setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
   setenv ("TAR_ARCHIVE", *archive_name, 1);
   setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
   setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
   setenv ("TAR_ARCHIVE", *archive_name, 1);
   setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
+  setenv ("TAR_BLOCKING_FACTOR",
+         STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
   setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
   setenv ("TAR_FORMAT",
          archive_format_string (current_format == DEFAULT_FORMAT ?
                                 archive_format : current_format), 1);
   setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
   setenv ("TAR_FORMAT",
          archive_format_string (current_format == DEFAULT_FORMAT ?
                                 archive_format : current_format), 1);
+  setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1);
 
   xclose (p[PREAD]);
 
   xclose (p[PREAD]);
-  xdup2 (p[PWRITE], 3);
 
   argv[0] = "/bin/sh";
   argv[1] = "-c";
 
   argv[0] = "/bin/sh";
   argv[1] = "-c";
@@ -838,5 +821,51 @@ sys_exec_info_script (const char **archive_name, int volume_number)
   exec_fatal (info_script_option);
 }
 
   exec_fatal (info_script_option);
 }
 
+void
+sys_exec_checkpoint_script (const char *script_name,
+                           const char *archive_name,
+                           int checkpoint_number)
+{
+  pid_t pid;
+  char *argv[4];
+  char uintbuf[UINTMAX_STRSIZE_BOUND];
+
+  pid = xfork ();
+
+  if (pid != 0)
+    {
+      /* Master */
+
+      int status;
+
+      while (waitpid (pid, &status, 0) == -1)
+       if (errno != EINTR)
+         {
+           waitpid_error (script_name);
+           break;
+         }
+
+      return;
+    }
+
+  /* Child */
+  setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
+  setenv ("TAR_ARCHIVE", archive_name, 1);
+  setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1);
+  setenv ("TAR_BLOCKING_FACTOR",
+         STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
+  setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
+  setenv ("TAR_FORMAT",
+         archive_format_string (current_format == DEFAULT_FORMAT ?
+                                archive_format : current_format), 1);
+  argv[0] = "/bin/sh";
+  argv[1] = "-c";
+  argv[2] = (char*) script_name;
+  argv[3] = NULL;
+
+  execv (argv[0], argv);
+
+  exec_fatal (script_name);
+}
 
 #endif /* not MSDOS */
 
 #endif /* not MSDOS */
This page took 0.030208 seconds and 4 git commands to generate.