]> Dogcows Code - chaz/tar/blobdiff - src/buffer.c
Started merging with cpio into paxutils.
[chaz/tar] / src / buffer.c
index 8dc6e88888dcb632c2b226b1737a5a8f77743a08..69812ec71597cfc502f207ef86cb7fab3ce71869 100644 (file)
@@ -19,7 +19,7 @@
    with this program; if not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include "system.h"
+#include <system.h>
 
 #include <signal.h>
 
@@ -28,7 +28,7 @@
 #include <quotearg.h>
 
 #include "common.h"
-#include "rmt.h"
+#include <rmt.h>
 
 /* Number of retries before giving up on read.  */
 #define        READ_ERROR_MAX 10
@@ -40,6 +40,7 @@
 
 static tarlong prev_written;   /* bytes written on previous volumes */
 static tarlong bytes_written;  /* bytes written on this volume */
+static void *record_buffer;    /* allocated memory */
 
 /* FIXME: The following variables should ideally be static to this
    module.  However, this cannot be done yet.  The cleanup continues!  */
@@ -75,7 +76,7 @@ static int checkpoint;
    Declared in update.c
 
    As least EXTERN like this one as possible. (?? --gray)
-   FIXME: Either eliminate it or move it to common.h. 
+   FIXME: Either eliminate it or move it to common.h.
 */
 extern bool time_to_start_writing;
 
@@ -109,37 +110,58 @@ static off_t real_s_sizeleft;
 /* Functions.  */
 
 void
-clear_read_error_count ()
+clear_read_error_count (void)
 {
   read_error_count = 0;
 }
 
+\f
+/* Time-related functions */
+
+double duration;
+
 void
-print_total_written (void)
+set_start_time ()
 {
-  tarlong written = prev_written + bytes_written;
-  char bytes[sizeof (tarlong) * CHAR_BIT];
-  char abbr[LONGEST_HUMAN_READABLE + 1];
-  char rate[LONGEST_HUMAN_READABLE + 1];
-  double seconds;
-  int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
+#if HAVE_CLOCK_GETTIME
+  if (clock_gettime (CLOCK_REALTIME, &start_timespec) != 0)
+#endif
+    start_time = time (0);
+}
 
+void
+compute_duration ()
+{
 #if HAVE_CLOCK_GETTIME
   struct timespec now;
   if (clock_gettime (CLOCK_REALTIME, &now) == 0)
-    seconds = ((now.tv_sec - start_timespec.tv_sec)
-              + (now.tv_nsec - start_timespec.tv_nsec) / 1e9);
+    duration += ((now.tv_sec - start_timespec.tv_sec)
+                + (now.tv_nsec - start_timespec.tv_nsec) / 1e9);
   else
 #endif
-    seconds = time (0) - start_time;
+    duration += time (NULL) - start_time;
+  set_start_time ();
+}
+
+\f
+
+void
+print_total_written (void)
+{
+  tarlong written = prev_written + bytes_written;
+  char bytes[sizeof (tarlong) * CHAR_BIT];
+  char abbr[LONGEST_HUMAN_READABLE + 1];
+  char rate[LONGEST_HUMAN_READABLE + 1];
+  
+  int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
 
   sprintf (bytes, TARLONG_FORMAT, written);
 
   /* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*".  */
   fprintf (stderr, _("Total bytes written: %s (%s, %s/s)\n"), bytes,
           human_readable (written, abbr, human_opts, 1, 1),
-          (0 < seconds && written / seconds < (uintmax_t) -1
-           ? human_readable (written / seconds, rate, human_opts, 1, 1)
+          (0 < duration && written / duration < (uintmax_t) -1
+           ? human_readable (written / duration, rate, human_opts, 1, 1)
            : "?"));
 }
 
@@ -270,17 +292,12 @@ open_archive (enum access_mode wanted_access)
   save_name = 0;
   real_s_name = 0;
 
+  record_start =
+    page_aligned_alloc (&record_buffer,
+                       (record_size
+                        + (multi_volume_option ? 2 * BLOCKSIZE : 0)));
   if (multi_volume_option)
-    {
-      record_start = valloc (record_size + (2 * BLOCKSIZE));
-      if (record_start)
-       record_start += 2;
-    }
-  else
-    record_start = valloc (record_size);
-  if (!record_start)
-    FATAL_ERROR ((0, 0, _("Cannot allocate memory for blocking factor %d"),
-                 blocking_factor));
+    record_start += 2;
 
   current_block = record_start;
   record_end = record_start + blocking_factor;
@@ -293,7 +310,6 @@ open_archive (enum access_mode wanted_access)
        {
        case ACCESS_READ:
          child_pid = sys_child_open_for_uncompress ();
-         read_full_records_option = false;
          break;
 
        case ACCESS_WRITE:
@@ -515,13 +531,18 @@ flush_write (void)
       if (volume_label_option)
        record_start++;
 
+      if (strlen (real_s_name) > NAME_FIELD_SIZE)
+       FATAL_ERROR ((0, 0,
+                     _("%s: file name too long to be stored in a GNU multivolume header"),
+                     quotearg_colon (real_s_name)));
+      
       memset (record_start, 0, BLOCKSIZE);
 
       /* FIXME: Michael P Urban writes: [a long name file] is being written
         when a new volume rolls around [...]  Looks like the wrong value is
         being preserved in real_s_name, though.  */
 
-      strcpy (record_start->header.name, real_s_name);
+      strncpy (record_start->header.name, real_s_name, NAME_FIELD_SIZE);
       record_start->header.typeflag = GNUTYPE_MULTIVOL;
       OFF_TO_CHARS (real_s_sizeleft, record_start->header.size);
       OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
@@ -600,7 +621,7 @@ archive_read_error (void)
 }
 
 static void
-short_read (ssize_t status)
+short_read (size_t status)
 {
   size_t left;                 /* bytes left */
   char *more;                  /* pointer to next byte to read */
@@ -612,23 +633,23 @@ short_read (ssize_t status)
         || (left && status && read_full_records_option))
     {
       if (status)
-       while ((status = rmtread (archive, more, left)) < 0)
+       while ((status = rmtread (archive, more, left)) == SAFE_READ_ERROR)
          archive_read_error ();
 
       if (status == 0)
        {
          char buf[UINTMAX_STRSIZE_BOUND];
-         
+
          WARN((0, 0, _("Read %s bytes from %s"),
                STRINGIFY_BIGINT (record_size - left, buf),
                *archive_name_cursor));
          break;
        }
-  
+
       if (! read_full_records_option)
        {
          unsigned long rest = record_size - left;
-         
+
          FATAL_ERROR ((0, 0,
                        ngettext ("Unaligned block (%lu byte) in archive",
                                  "Unaligned block (%lu bytes) in archive",
@@ -646,7 +667,7 @@ short_read (ssize_t status)
      about the problem.  */
 
   if (!read_full_records_option && verbose_option > 1
-      && record_start_block == 0 && status > 0)
+      && record_start_block == 0 && status != 0)
     {
       unsigned long rsize = (record_size - left) / BLOCKSIZE;
       WARN ((0, 0,
@@ -664,7 +685,7 @@ short_read (ssize_t status)
 void
 flush_read (void)
 {
-  ssize_t status;              /* result from system call */
+  size_t status;               /* result from system call */
 
   if (checkpoint_option && !(++checkpoint % 10))
     WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
@@ -711,9 +732,9 @@ flush_read (void)
      This is incorrect since even if new_volume() succeeds, the
      subsequent call to rmtread will overwrite the chunk of data
      already read in the buffer, so the processing will fail */
-        
+
   if ((status == 0
-       || (status < 0 && errno == ENOSPC))
+       || (status == SAFE_READ_ERROR && errno == ENOSPC))
       && multi_volume_option)
     {
       union block *cursor;
@@ -734,12 +755,12 @@ flush_read (void)
          break;
        }
 
-      while ((status =
-             rmtread (archive, record_start->buffer, record_size)) < 0)
+      while ((status = rmtread (archive, record_start->buffer, record_size))
+            == SAFE_READ_ERROR)
        archive_read_error ();
-      
+
       if (status != record_size)
-       short_read (status); 
+       short_read (status);
 
       cursor = record_start;
 
@@ -768,7 +789,7 @@ flush_read (void)
        {
          uintmax_t s1, s2;
          if (cursor->header.typeflag != GNUTYPE_MULTIVOL
-             || strcmp (cursor->header.name, real_s_name))
+             || strncmp (cursor->header.name, real_s_name, NAME_FIELD_SIZE))
            {
              WARN ((0, 0, _("%s is not continued on this volume"),
                     quote (real_s_name)));
@@ -807,7 +828,7 @@ flush_read (void)
       records_read++;
       return;
     }
-  else if (status < 0)
+  else if (status == SAFE_READ_ERROR)
     {
       archive_read_error ();
       goto error_loop;         /* try again */
@@ -889,6 +910,42 @@ backspace_output (void)
   }
 }
 
+off_t
+seek_archive (off_t size)
+{
+  off_t start = current_block_ordinal ();
+  off_t offset;
+  off_t nrec, nblk;
+  off_t skipped = (blocking_factor - (current_block - record_start));
+  
+  size -= skipped * BLOCKSIZE;
+  
+  if (size < record_size)
+    return 0;
+  /* FIXME: flush? */
+  
+  /* Compute number of records to skip */
+  nrec = size / record_size;
+  offset = rmtlseek (archive, nrec * record_size, SEEK_CUR);
+  if (offset < 0)
+    return offset;
+
+  if (offset % record_size)
+    FATAL_ERROR ((0, 0, _("rmtlseek not stopped at a record boundary")));
+
+  /* Convert to number of records */
+  offset /= BLOCKSIZE;
+  /* Compute number of skipped blocks */
+  nblk = offset - start;
+
+  /* Update buffering info */
+  records_read += nblk / blocking_factor;
+  record_start_block = offset - blocking_factor;
+  current_block = record_end;
+  return nblk;
+}
+
 /* Close the archive file.  */
 void
 close_archive (void)
@@ -897,21 +954,22 @@ close_archive (void)
     flush_archive ();
 
   sys_drain_input_pipe ();
-  
-  if (verify_option)
+
+  compute_duration ();
+  if (verify_option) 
     verify_volume ();
 
   if (rmtclose (archive) != 0)
     close_warn (*archive_name_cursor);
 
   sys_wait_for_child (child_pid);
-  
+
   tar_stat_destroy (&current_stat_info);
   if (save_name)
     free (save_name);
   if (real_s_name)
     free (real_s_name);
-  free (multi_volume_option ? record_start - 2 : record_start);
+  free (record_buffer);
 }
 
 /* Called to initialize the global volume number.  */
@@ -957,7 +1015,7 @@ closeout_volume_number (void)
    Return nonzero on success.
 */
 static bool
-new_volume (enum access_mode access)
+new_volume (enum access_mode mode)
 {
   static FILE *read_file;
   static int looped;
@@ -1086,7 +1144,7 @@ new_volume (enum access_mode access)
     archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW,
                       rsh_command_option);
   else
-    switch (access)
+    switch (mode)
       {
       case ACCESS_READ:
        archive = rmtopen (*archive_name_cursor, O_RDONLY, MODE_RW,
@@ -1109,7 +1167,7 @@ new_volume (enum access_mode access)
   if (archive < 0)
     {
       open_warn (*archive_name_cursor);
-      if (!verify_option && access == ACCESS_WRITE && backup_option)
+      if (!verify_option && mode == ACCESS_WRITE && backup_option)
        undo_last_backup ();
       goto tryagain;
     }
This page took 0.02853 seconds and 4 git commands to generate.