]> Dogcows Code - chaz/tar/blobdiff - src/system.c
Do not try to drain the input pipe before closing the archive.
[chaz/tar] / src / system.c
index 63f9849cf9a027f956e811a23398face0e7f6ac8..c90a40d1217b0441571604ead5f9af839675793c 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,8 +171,11 @@ 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))
+           ERROR ((0, 0, _("Child died with signal %d"), sig));
+       }
       else if (WEXITSTATUS (wait_status) != 0)
        ERROR ((0, 0, _("Child returned status %d"),
                WEXITSTATUS (wait_status)));
       else if (WEXITSTATUS (wait_status) != 0)
        ERROR ((0, 0, _("Child returned status %d"),
                WEXITSTATUS (wait_status)));
@@ -349,7 +330,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;
@@ -695,7 +676,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 +687,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 +716,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 +732,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 +753,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 +766,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 +777,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 +796,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 +805,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 +825,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.033677 seconds and 4 git commands to generate.