]> Dogcows Code - chaz/tar/blobdiff - src/buffer.c
(flush_write): Limit filenames
[chaz/tar] / src / buffer.c
index f3cebc0aed908a5450a26404c927fd817164f2ae..d7c6844c4fd9da9eb8873d94991334f6ad4397ce 100644 (file)
@@ -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!  */
@@ -270,17 +271,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 +289,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 +510,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,
@@ -768,7 +768,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)));
@@ -889,6 +889,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)
@@ -911,7 +947,7 @@ close_archive (void)
     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.  */
This page took 0.023618 seconds and 4 git commands to generate.