浏览代码

(write_archive_buffer): New function.
(child_open_for_compress, flush_write, flush_read): Use it to write
buffers.
(open_archive): Report error if fstat of archive fails.
Improve efficiency of check for /dev/null.
Also, fix some corner cases with remote archives and /dev/null checking.
(close_archive): Test for input fifo only if not remote.
Truncate output archive only if it's not remote.

Paul Eggert 26 年之前
父节点
当前提交
ee734033e8
共有 1 个文件被更改,包括 45 次插入19 次删除
  1. 45 19
      src/buffer.c

+ 45 - 19
src/buffer.c

@@ -319,6 +319,24 @@ is_regular_file (const char *name)
   return 0;
   return 0;
 }
 }
 
 
+static ssize_t
+write_archive_buffer (void)
+{
+  ssize_t status;
+  ssize_t written = 0;
+
+  while (0 <= (status = rmtwrite (archive, record_start->buffer + written,
+				  record_size - written)))
+    {
+      written += status;
+      if (written == record_size
+	  || _isrmt (archive) || ! S_ISFIFO (archive_stat.st_mode))
+	break;
+    }
+
+  return written ? written : status;
+}
+
 /*-------------------------------------------------------.
 /*-------------------------------------------------------.
 | Set ARCHIVE for writing, then compressing an archive.	 |
 | Set ARCHIVE for writing, then compressing an archive.	 |
 `-------------------------------------------------------*/
 `-------------------------------------------------------*/
@@ -460,7 +478,7 @@ child_open_for_compress (void)
 	  if (length > 0)
 	  if (length > 0)
 	    {
 	    {
 	      memset (record_start->buffer + length, 0, record_size - length);
 	      memset (record_start->buffer + length, 0, record_size - length);
-	      status = rmtwrite (archive, record_start->buffer, record_size);
+	      status = write_archive_buffer ();
 	      if (status != record_size)
 	      if (status != record_size)
 		write_error (status);
 		write_error (status);
 	    }
 	    }
@@ -469,7 +487,7 @@ child_open_for_compress (void)
 	  break;
 	  break;
 	}
 	}
 
 
-      status = rmtwrite (archive, record_start->buffer, record_size);
+      status = write_archive_buffer ();
       if (status != record_size)
       if (status != record_size)
  	write_error (status);
  	write_error (status);
     }
     }
@@ -784,7 +802,8 @@ open_archive (enum access_mode access)
 	break;
 	break;
       }
       }
 
 
-  if (archive < 0)
+  if (archive < 0
+      || (! _isrmt (archive) && fstat (archive, &archive_stat) < 0))
     {
     {
       int saved_errno = errno;
       int saved_errno = errno;
 
 
@@ -796,15 +815,17 @@ open_archive (enum access_mode access)
 
 
 #if !MSDOS
 #if !MSDOS
 
 
-  fstat (archive, &archive_stat);
-
   /* Detect if outputting to "/dev/null".  */
   /* Detect if outputting to "/dev/null".  */
   {
   {
+    static char const dev_null[] = "/dev/null";
     struct stat dev_null_stat;
     struct stat dev_null_stat;
 
 
-    stat ("/dev/null", &dev_null_stat);
-    dev_null_output = (S_ISCHR (archive_stat.st_mode)
-		       && archive_stat.st_rdev == dev_null_stat.st_rdev);
+    dev_null_output =
+      (strcmp (archive_name_array[0], dev_null) == 0
+       || (! _isrmt (archive)
+	   && stat (dev_null, &dev_null_stat) == 0
+	   && S_ISCHR (archive_stat.st_mode)
+	   && archive_stat.st_rdev == dev_null_stat.st_rdev));
   }
   }
 
 
   if (!_isrmt (archive) && S_ISREG (archive_stat.st_mode))
   if (!_isrmt (archive) && S_ISREG (archive_stat.st_mode))
@@ -812,6 +833,8 @@ open_archive (enum access_mode access)
       ar_dev = archive_stat.st_dev;
       ar_dev = archive_stat.st_dev;
       ar_ino = archive_stat.st_ino;
       ar_ino = archive_stat.st_ino;
     }
     }
+  else
+    ar_dev = 0;
 
 
 #endif /* not MSDOS */
 #endif /* not MSDOS */
 
 
@@ -884,7 +907,7 @@ flush_write (void)
   else if (dev_null_output)
   else if (dev_null_output)
     status = record_size;
     status = record_size;
   else
   else
-    status = rmtwrite (archive, record_start->buffer, record_size);
+    status = write_archive_buffer ();
   if (status != record_size && !multi_volume_option)
   if (status != record_size && !multi_volume_option)
     write_error (status);
     write_error (status);
   else if (totals_option)
   else if (totals_option)
@@ -984,7 +1007,7 @@ flush_write (void)
 	record_start--;
 	record_start--;
     }
     }
 
 
-  status = rmtwrite (archive, record_start->buffer, record_size);
+  status = write_archive_buffer ();
   if (status != record_size)
   if (status != record_size)
     write_error (status);
     write_error (status);
   else if (totals_option)
   else if (totals_option)
@@ -1089,7 +1112,7 @@ flush_read (void)
 
 
   if (write_archive_to_stdout && record_start_block != 0)
   if (write_archive_to_stdout && record_start_block != 0)
     {
     {
-      status = rmtwrite (1, record_start->buffer, record_size);
+      status = write_archive_buffer ();
       if (status != record_size)
       if (status != record_size)
 	write_error (status);
 	write_error (status);
     }
     }
@@ -1375,22 +1398,25 @@ close_archive (void)
      might become clever enough to just stop working, once there is no more
      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.  */
      work to do, we might have to revise this area in such time.  */
 
 
-  if (access_mode == ACCESS_READ && S_ISFIFO (archive_stat.st_mode) &&
-      !ending_file_option)
+  if (access_mode == ACCESS_READ
+      && ! _isrmt (archive)
+      && S_ISFIFO (archive_stat.st_mode)
+      && ! ending_file_option)
     while (rmtread (archive, record_start->buffer, record_size) > 0)
     while (rmtread (archive, record_start->buffer, record_size) > 0)
       continue;
       continue;
 #endif
 #endif
 
 
-  if (subcommand_option == DELETE_SUBCOMMAND)
+  if (! _isrmt (archive) && subcommand_option == DELETE_SUBCOMMAND)
     {
     {
-      off_t pos;
-
-      pos = rmtlseek (archive, (off_t) 0, 1);
 #if MSDOS
 #if MSDOS
-      rmtwrite (archive, "", 0);
+      int status = write (archive, "", 0);
 #else
 #else
-      ftruncate (archive, pos);
+      off_t pos = lseek (archive, (off_t) 0, 1);
+      int status = pos == -1 ? -1 : ftruncate (archive, pos);
 #endif
 #endif
+      if (status != 0)
+	WARN ((0, errno, _("WARNING: Cannot truncate %s"),
+	       *archive_name_cursor));
     }
     }
   if (verify_option)
   if (verify_option)
     verify_volume ();
     verify_volume ();