Browse Source

(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 years ago
parent
commit
ee734033e8
1 changed files with 45 additions and 19 deletions
  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 ();