]> Dogcows Code - chaz/tar/commitdiff
Keep a detailed map of archive members stored in the record buffer.
authorSergey Poznyakoff <gray@gnu.org.ua>
Sun, 11 Jul 2010 16:56:45 +0000 (19:56 +0300)
committerSergey Poznyakoff <gray@gnu.org.ua>
Sun, 11 Jul 2010 19:57:17 +0000 (22:57 +0300)
A separate map (bufmap) provides information for creating
multi-volume continuation headers.

* src/buffer.c (bufmap): New struct.
(bufmap_head, bufmap_tail, inhibit_map): New variables.
(mv_begin_write): New function.
(mv_begin): Rename to mv_begin_read. Rewrite using mv_begin_write.
All callers changed.
(mv_total_size): Remove.
(bufmap_locate, bufmap_free, bufmap_reset): New functions.
(_flush_write): Update bufmap.
(close_archive): Free bufmap.
(add_chunk_header): Take a bufmap argument.
(gnu_add_multi_volume_header): Likewise.
(add_multi_volume_header): Likewise.
(_gnu_flush_write): Rewrite using bufmap.
(real_s_name, real_s_totsize)
(real_s_sizeleft)
(save_name, save_totsize, save_sizeleft): Removed. All
uses updated.
(mv_size_left): Update bufmap_head.
(mv_end): Rewrite.
(multi_volume_sync): Remove.

* src/common.h (mv_begin_write): New prototype.
(mv_begin): Rename to mv_begin_read.
* src/create.c: Use mv_begin_write instead of mv_begin.
Remove calls to mv_size_left and mv_end.
* src/sparse.c: Likewise.

* tests/multiv07.at: Close stdin.
* tests/spmvp00.at: Update AT_KEYWORDS.
* tests/spmvp10.at: Likewise.

* tests/multiv08.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add multiv08.at.

14 files changed:
src/buffer.c
src/common.h
src/compare.c
src/create.c
src/extract.c
src/incremen.c
src/list.c
src/sparse.c
tests/Makefile.am
tests/multiv07.at
tests/multiv08.at [new file with mode: 0644]
tests/spmvp00.at
tests/spmvp10.at
tests/testsuite.at

index 444f61251f8fec9a09719784c609f5c2732ba2a5..07b11ab9c487d6c4c70f99c7e03fff0cbd87378e 100644 (file)
@@ -76,8 +76,7 @@ static bool read_full_records = false;
 
 /* We're reading, but we just read the last block and it's time to update.
    Declared in update.c
-
-   As least EXTERN like this one as possible. (?? --gray)
+   
    FIXME: Either eliminate it or move it to common.h.
 */
 extern bool time_to_start_writing;
@@ -101,19 +100,94 @@ static int global_volno = 1;    /* volume number to print in external
 
 bool write_archive_to_stdout;
 
-/* Used by flush_read and flush_write to store the real info about saved
-   names.  */
-static char *real_s_name;
-static off_t real_s_totsize;
-static off_t real_s_sizeleft;
-
 \f
 /* Multi-volume tracking support */
-static char *save_name;         /* name of the file we are currently writing */
-static off_t save_totsize;      /* total size of file we are writing, only
-                                   valid if save_name is nonzero */
-static off_t save_sizeleft;     /* where we are in the file we are writing,
-                                   only valid if save_name is nonzero */
+
+/* When creating a multi-volume archive, each `bufmap' represents
+   a member stored (perhaps partly) in the current record buffer.
+   After flushing the record to the output media, all bufmaps that
+   represent fully written members are removed from the list, then
+   the sizeleft and start numbers in the remaining bufmaps are updated.
+
+   When reading from a multi-volume archive, the list degrades to a
+   single element, which keeps information about the member currently
+   being read.
+*/
+
+struct bufmap
+{
+  struct bufmap *next;          /* Pointer to the next map entry */
+  size_t start;                 /* Offset of the first data block */
+  char *file_name;              /* Name of the stored file */
+  off_t sizetotal;              /* Size of the stored file */
+  off_t sizeleft;               /* Size left to read/write */
+};
+static struct bufmap *bufmap_head, *bufmap_tail;
+
+/* This variable, when set, inhibits updating the bufmap chain after
+   a write.  This is necessary when writing extended POSIX headers. */
+static int inhibit_map;
+
+void
+mv_begin_write (const char *file_name, off_t totsize, off_t sizeleft)
+{
+  if (multi_volume_option)
+    {
+      struct bufmap *bp = xmalloc (sizeof bp[0]);
+      if (bufmap_tail)
+       bufmap_tail->next = bp;
+      else
+       bufmap_head = bp;
+      bufmap_tail = bp;
+
+      bp->next = NULL;
+      bp->start = current_block - record_start;
+      bp->file_name = xstrdup (file_name);
+      bp->sizetotal = totsize;
+      bp->sizeleft = sizeleft;
+    }
+}
+
+static struct bufmap *
+bufmap_locate (size_t off)
+{
+  struct bufmap *map;
+  
+  for (map = bufmap_head; map; map = map->next)
+    {
+      if (!map->next
+         || off < map->next->start * BLOCKSIZE)
+       break;
+    }
+  return map;
+}
+
+static void
+bufmap_free (struct bufmap *mark)
+{
+  struct bufmap *map;
+  for (map = bufmap_head; map && map != mark; )
+    {
+      struct bufmap *next = map->next;
+      free (map->file_name);
+      free (map);
+      map = next;
+    }
+  bufmap_head = map;
+  if (!bufmap_head)
+    bufmap_tail = bufmap_head;
+}
+
+static void
+bufmap_reset (struct bufmap *map, ssize_t fixup)
+{
+  bufmap_free (map);
+  if (map)
+    {
+      for (; map; map = map->next)
+       map->start += fixup;
+    }
+}
 
 \f
 static struct tar_stat_info dummy;
@@ -125,32 +199,23 @@ buffer_write_global_xheader ()
 }
 
 void
-mv_begin (struct tar_stat_info *st)
+mv_begin_read (struct tar_stat_info *st)
 {
-  if (multi_volume_option)
-    {
-      assign_string (&save_name,  st->orig_file_name);
-      save_totsize = save_sizeleft = st->stat.st_size;
-    }
+  mv_begin_write (st->orig_file_name, st->stat.st_size, st->stat.st_size);
 }
 
 void
 mv_end ()
 {
   if (multi_volume_option)
-    assign_string (&save_name, 0);
-}
-
-void
-mv_total_size (off_t size)
-{
-  save_totsize = size;
+    bufmap_free (NULL);
 }
 
 void
 mv_size_left (off_t size)
 {
-  save_sizeleft = size;
+  if (bufmap_head)
+    bufmap_head->sizeleft = size;
 }
 
 \f
@@ -511,9 +576,7 @@ _open_archive (enum access_mode wanted_access)
     FATAL_ERROR ((0, 0, _("No archive name given")));
 
   tar_stat_destroy (&current_stat_info);
-  save_name = 0;
-  real_s_name = 0;
-
+  
   record_index = 0;
   init_buffer ();
 
@@ -673,6 +736,20 @@ _flush_write (void)
   else
     status = sys_write_archive_buffer ();
 
+  if (status && multi_volume_option && !inhibit_map)
+    {
+      struct bufmap *map = bufmap_locate (status);
+      if (map)
+       {
+         size_t delta = status - map->start * BLOCKSIZE;
+         if (delta > map->sizeleft)
+           delta = map->sizeleft;
+         map->sizeleft -= delta;
+         if (map->sizeleft == 0)
+           map = map->next;
+         bufmap_reset (map, map ? (- map->start) : 0);
+       }
+    }  
   return status;
 }
 
@@ -907,12 +984,9 @@ close_archive (void)
   sys_wait_for_child (child_pid, hit_eof);
 
   tar_stat_destroy (&current_stat_info);
-  if (save_name)
-    free (save_name);
-  if (real_s_name)
-    free (real_s_name);
   free (record_buffer[0]);
   free (record_buffer[1]);
+  bufmap_free (NULL);
 }
 
 /* Called to initialize the global volume number.  */
@@ -1280,30 +1354,30 @@ try_new_volume (void)
       break;
     }
 
-  if (real_s_name)
+  if (bufmap_head)
     {
       uintmax_t s;
       if (!continued_file_name
-          || strcmp (continued_file_name, real_s_name))
+          || strcmp (continued_file_name, bufmap_head->file_name))
         {
           if ((archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
-              && strlen (real_s_name) >= NAME_FIELD_SIZE
-              && strncmp (continued_file_name, real_s_name,
+              && strlen (bufmap_head->file_name) >= NAME_FIELD_SIZE
+              && strncmp (continued_file_name, bufmap_head->file_name,
                           NAME_FIELD_SIZE) == 0)
             WARN ((0, 0,
  _("%s is possibly continued on this volume: header contains truncated name"),
-                   quote (real_s_name)));
+                   quote (bufmap_head->file_name)));
           else
             {
               WARN ((0, 0, _("%s is not continued on this volume"),
-                     quote (real_s_name)));
+                     quote (bufmap_head->file_name)));
               return false;
             }
         }
 
       s = continued_file_size + continued_file_offset;
 
-      if (real_s_totsize != s || s < continued_file_offset)
+      if (bufmap_head->sizetotal != s || s < continued_file_offset)
         {
           char totsizebuf[UINTMAX_STRSIZE_BOUND];
           char s1buf[UINTMAX_STRSIZE_BOUND];
@@ -1311,21 +1385,22 @@ try_new_volume (void)
 
           WARN ((0, 0, _("%s is the wrong size (%s != %s + %s)"),
                  quote (continued_file_name),
-                 STRINGIFY_BIGINT (save_totsize, totsizebuf),
+                 STRINGIFY_BIGINT (bufmap_head->sizetotal, totsizebuf),
                  STRINGIFY_BIGINT (continued_file_size, s1buf),
                  STRINGIFY_BIGINT (continued_file_offset, s2buf)));
           return false;
         }
 
-      if (real_s_totsize - real_s_sizeleft != continued_file_offset)
+      if (bufmap_head->sizetotal - bufmap_head->sizeleft !=
+         continued_file_offset)
         {
           char totsizebuf[UINTMAX_STRSIZE_BOUND];
           char s1buf[UINTMAX_STRSIZE_BOUND];
           char s2buf[UINTMAX_STRSIZE_BOUND];
 
           WARN ((0, 0, _("This volume is out of sequence (%s - %s != %s)"),
-                 STRINGIFY_BIGINT (real_s_totsize, totsizebuf),
-                 STRINGIFY_BIGINT (real_s_sizeleft, s1buf),
+                 STRINGIFY_BIGINT (bufmap_head->sizetotal, totsizebuf),
+                 STRINGIFY_BIGINT (bufmap_head->sizeleft, s1buf),
                  STRINGIFY_BIGINT (continued_file_offset, s2buf)));
 
           return false;
@@ -1477,26 +1552,24 @@ add_volume_label (void)
 }
 
 static void
-add_chunk_header (void)
+add_chunk_header (struct bufmap *map)
 {
   if (archive_format == POSIX_FORMAT)
     {
       off_t block_ordinal;
       union block *blk;
       struct tar_stat_info st;
-      static size_t real_s_part_no; /* FIXME */
 
-      real_s_part_no++;
       memset (&st, 0, sizeof st);
-      st.orig_file_name = st.file_name = real_s_name;
+      st.orig_file_name = st.file_name = map->file_name;
       st.stat.st_mode = S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
       st.stat.st_uid = getuid ();
       st.stat.st_gid = getgid ();
       st.orig_file_name = xheader_format_name (&st,
                                                "%d/GNUFileParts.%p/%f.%n",
-                                               real_s_part_no);
+                                               volno);
       st.file_name = st.orig_file_name;
-      st.archive_file_size = st.stat.st_size = real_s_sizeleft;
+      st.archive_file_size = st.stat.st_size = map->sizeleft;
 
       block_ordinal = current_block_ordinal ();
       blk = start_header (&st);
@@ -1520,27 +1593,23 @@ write_volume_label (void)
 
 /* Write GNU multi-volume header */
 static void
-gnu_add_multi_volume_header (void)
+gnu_add_multi_volume_header (struct bufmap *map)
 {
   int tmp;
   union block *block = find_next_block ();
 
-  if (strlen (real_s_name) > NAME_FIELD_SIZE)
+  if (strlen (map->file_name) > NAME_FIELD_SIZE)
     WARN ((0, 0,
            _("%s: file name too long to be stored in a GNU multivolume header, truncated"),
-           quotearg_colon (real_s_name)));
+           quotearg_colon (map->file_name)));
 
   memset (block, 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.  */
-
-  strncpy (block->header.name, real_s_name, NAME_FIELD_SIZE);
+  strncpy (block->header.name, map->file_name, NAME_FIELD_SIZE);
   block->header.typeflag = GNUTYPE_MULTIVOL;
 
-  OFF_TO_CHARS (real_s_sizeleft, block->header.size);
-  OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
+  OFF_TO_CHARS (map->sizeleft, block->header.size);
+  OFF_TO_CHARS (map->sizetotal - map->sizeleft,
                 block->oldgnu_header.offset);
 
   tmp = verbose_option;
@@ -1553,40 +1622,17 @@ gnu_add_multi_volume_header (void)
 /* Add a multi volume header to the current archive. The exact header format
    depends on the archive format. */
 static void
-add_multi_volume_header (void)
+add_multi_volume_header (struct bufmap *map)
 {
   if (archive_format == POSIX_FORMAT)
     {
-      off_t d = real_s_totsize - real_s_sizeleft;
-      xheader_store ("GNU.volume.filename", &dummy, real_s_name);
-      xheader_store ("GNU.volume.size", &dummy, &real_s_sizeleft);
+      off_t d = map->sizetotal - map->sizeleft;
+      xheader_store ("GNU.volume.filename", &dummy, map->file_name);
+      xheader_store ("GNU.volume.size", &dummy, &map->sizeleft);
       xheader_store ("GNU.volume.offset", &dummy, &d);
     }
   else
-    gnu_add_multi_volume_header ();
-}
-
-/* Synchronize multi-volume globals */
-static void
-multi_volume_sync (void)
-{
-  if (multi_volume_option)
-    {
-      if (save_name)
-        {
-          assign_string (&real_s_name,
-                         safer_name_suffix (save_name, false,
-                                            absolute_names_option));
-          real_s_totsize = save_totsize;
-          real_s_sizeleft = save_sizeleft;
-        }
-      else
-        {
-          assign_string (&real_s_name, 0);
-          real_s_totsize = 0;
-          real_s_sizeleft = 0;
-        }
-    }
+    gnu_add_multi_volume_header (map);
 }
 
 \f
@@ -1673,8 +1719,6 @@ _gnu_flush_read (void)
         archive_write_error (status);
     }
 
-  multi_volume_sync ();
-
   for (;;)
     {
       status = rmtread (archive, record_start->buffer, record_size);
@@ -1726,8 +1770,8 @@ _gnu_flush_write (size_t buffer_level)
   char *copy_ptr;
   size_t copy_size;
   size_t bufsize;
-  tarlong wrt;
-
+  struct bufmap *map;
+  
   status = _flush_write ();
   if (status != record_size && !multi_volume_option)
     archive_write_error (status);
@@ -1740,10 +1784,11 @@ _gnu_flush_write (size_t buffer_level)
 
   if (status == record_size)
     {
-      multi_volume_sync ();
       return;
     }
 
+  map = bufmap_locate (status);
+  
   if (status % BLOCKSIZE)
     {
       ERROR ((0, 0, _("write did not end on a block boundary")));
@@ -1755,7 +1800,6 @@ _gnu_flush_write (size_t buffer_level)
   if (status < 0 && errno != ENOSPC && errno != EIO && errno != ENXIO)
     archive_write_error (status);
 
-  real_s_sizeleft -= status;
   if (!new_volume (ACCESS_WRITE))
     return;
 
@@ -1767,25 +1811,28 @@ _gnu_flush_write (size_t buffer_level)
 
   copy_ptr = record_start->buffer + status;
   copy_size = buffer_level - status;
-
+    
   /* Switch to the next buffer */
   record_index = !record_index;
   init_buffer ();
 
+  inhibit_map = 1;
+  
   if (volume_label_option)
     add_volume_label ();
 
-  if (real_s_name)
-    add_multi_volume_header ();
+  if (map)
+    add_multi_volume_header (map);
 
   write_extended (true, &dummy, find_next_block ());
   tar_stat_destroy (&dummy);
 
-  if (real_s_name)
-    add_chunk_header ();
-  wrt = bytes_written;
+  if (map)
+    add_chunk_header (map);
   header = find_next_block ();
+  bufmap_reset (map, header - record_start);
   bufsize = available_space_after (header);
+  inhibit_map = 0;
   while (bufsize < copy_size)
     {
       memcpy (header->buffer, copy_ptr, bufsize);
@@ -1798,16 +1845,6 @@ _gnu_flush_write (size_t buffer_level)
   memcpy (header->buffer, copy_ptr, copy_size);
   memset (header->buffer + copy_size, 0, bufsize - copy_size);
   set_next_block_after (header + (copy_size - 1) / BLOCKSIZE);
-  if (multi_volume_option && wrt < bytes_written)
-    {
-      /* The value of bytes_written has changed while moving data;
-         that means that flush_archive was executed at least once in
-         between, and, as a consequence, copy_size bytes were not written
-         to disk.  We need to update sizeleft variables to compensate for
-         that. */
-      save_sizeleft += copy_size;
-      multi_volume_sync ();
-    }
   find_next_block ();
 }
 
index 9e42eec413c6c49d24e4a99b5469c4ff80fe2162..bc1f3a2585b85709296facadf1029ed2c659b0fb 100644 (file)
@@ -427,9 +427,10 @@ void archive_read_error (void);
 off_t seek_archive (off_t size);
 void set_start_time (void);
 
-void mv_begin (struct tar_stat_info *st);
+void mv_begin_write (const char *file_name, off_t totsize, off_t sizeleft);
+
+void mv_begin_read (struct tar_stat_info *st);
 void mv_end (void);
-void mv_total_size (off_t size);
 void mv_size_left (off_t size);
 
 void buffer_write_global_xheader (void);
index 437ffb3a8978511274e0c98b6c76cbc18367ff3a..ffadc24a942e03563ab8706468b6a6d52f00fbcf 100644 (file)
@@ -122,7 +122,7 @@ read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
   size_t data_size;
   off_t size = st->stat.st_size;
 
-  mv_begin (st);
+  mv_begin_read (st);
   while (size)
     {
       data_block = find_next_block ();
index c69d3406a1c859b52afd2695b9136e1bd9885b9a..f526b33053c0837d51d1efc12f8c6cf83577ae54 100644 (file)
@@ -1012,7 +1012,6 @@ pad_archive (off_t size_left)
   union block *blk;
   while (size_left > 0)
     {
-      mv_size_left (size_left);
       blk = find_next_block ();
       memset (blk->buffer, 0, BLOCKSIZE);
       set_next_block_after (blk);
@@ -1038,13 +1037,11 @@ dump_regular_file (int fd, struct tar_stat_info *st)
 
   finish_header (st, blk, block_ordinal);
 
-  mv_begin (st);
+  mv_begin_write (st->file_name, st->stat.st_size, st->stat.st_size);
   while (size_left > 0)
     {
       size_t bufsize, count;
       
-      mv_size_left (size_left);
-
       blk = find_next_block ();
 
       bufsize = available_space_after (blk);
@@ -1138,11 +1135,9 @@ dump_dir0 (char *directory,
          p_buffer = buffer;
          size_left = totsize;
          
-         mv_begin (st);
-         mv_total_size (totsize);
+         mv_begin_write (st->file_name, totsize, totsize);
          while (size_left > 0)
            {
-             mv_size_left (size_left);
              blk = find_next_block ();
              bufsize = available_space_after (blk);
              if (size_left < bufsize)
@@ -1157,7 +1152,6 @@ dump_dir0 (char *directory,
              p_buffer += bufsize;
              set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
            }
-         mv_end ();
        }
       return;
     }
@@ -1619,7 +1613,6 @@ dump_file0 (struct tar_stat_info *st, const char *p,
            {
            case dump_status_ok:
            case dump_status_short:
-             mv_end ();
              file_count_links (st);
              break;
 
index 0f0d03fe9ada9741ff7da53abf743089bf353a89..7ce9ce863f188f3c8babb83e3eb829d05ab83820 100644 (file)
@@ -812,7 +812,7 @@ extract_file (char *file_name, int typeflag)
        }
     }
 
-  mv_begin (&current_stat_info);
+  mv_begin_read (&current_stat_info);
   if (current_stat_info.is_sparse)
     sparse_extract_file (fd, &current_stat_info, &size);
   else
index e61eb79739e9a6bd607ee226cbea63cfb4eb6ce4..0d1c115ca99d06a58924b404ba52b85393e5bfaa 100644 (file)
@@ -1452,7 +1452,7 @@ get_gnu_dumpdir (struct tar_stat_info *stat_info)
   to = archive_dir;
 
   set_next_block_after (current_header);
-  mv_begin (stat_info);
+  mv_begin_read (stat_info);
 
   for (; size > 0; size -= copied)
     {
index 74df7618e1c23cad8bdc30625a0684ffce8d9a8c..9184beab739f70631c371a517b0c119af001e781 100644 (file)
@@ -1353,7 +1353,7 @@ skip_file (off_t size)
 {
   union block *x;
 
-  /* FIXME: Make sure mv_begin is always called before it */
+  /* FIXME: Make sure mv_begin_read is always called before it */
 
   if (seekable_archive)
     {
@@ -1388,7 +1388,7 @@ skip_member (void)
       char save_typeflag = current_header->header.typeflag;
       set_next_block_after (current_header);
 
-      mv_begin (&current_stat_info);
+      mv_begin_read (&current_stat_info);
 
       if (current_stat_info.is_sparse)
        sparse_skip_file (&current_stat_info);
index 4a391a9cc6bd5202f89edc1b61dd81fd06a12a7c..67e5a857166df9f31c98644dd024a4423cf01520 100644 (file)
@@ -324,7 +324,6 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
       memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
       bytes_left -= bytes_read;
       file->dumped_size += bytes_read;
-      mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
       set_next_block_after (blk);
     }
 
@@ -398,10 +397,11 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
        {
          size_t i;
 
-         mv_begin (file.stat_info);
+         mv_begin_write (file.stat_info->file_name,
+                         file.stat_info->stat.st_size,
+                         file.stat_info->archive_file_size - file.dumped_size);
          for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
            rc = tar_sparse_dump_region (&file, i);
-         mv_end ();
        }
     }
 
@@ -566,7 +566,7 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
   file.seekable = true; /* File *must* be seekable for compare to work */
 
   rc = tar_sparse_decode_header (&file);
-  mv_begin (st);
+  mv_begin_read (st);
   for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
     {
       rc = check_sparse_region (&file,
index 97a678dbed8538855c2e64550c696c8b315480ef..f5bc4ef487e95ab43e1183a8fb180edb46d76dfe 100644 (file)
@@ -110,6 +110,7 @@ TESTSUITE_AT = \
  multiv05.at\
  multiv06.at\
  multiv07.at\
+ multiv08.at\
  old.at\
  options.at\
  options02.at\
index ff965d6c1aea1ec59650a7e5aeb8eb7605953f27..fc3e82da56024973186b19ae9ef03a37ffdc09c3 100644 (file)
@@ -31,6 +31,8 @@ AT_XFAIL_IF(test -f $[]XFAILFILE)
 AT_TARBALL_PREREQ([xsplit-1.tar],[0e008c84c517e48fbf23ca6a7033cde6])
 AT_TARBALL_PREREQ([xsplit-2.tar],[03150b9852d285458f43734e9e0b9a45])
 
+exec <&-
+
 cd $TEST_DATA_DIR
 tar -t -M -fxsplit-1.tar -fxsplit-2.tar
 ],
diff --git a/tests/multiv08.at b/tests/multiv08.at
new file mode 100644 (file)
index 0000000..7f4f38e
--- /dev/null
@@ -0,0 +1,51 @@
+# Test suite for GNU tar.                             -*- Autotest -*-
+# Copyright (C) 2010 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 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 WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Description: Tar 1.23 would in some cases silently fail to create
+# a continuation header in multivolume archives.
+#
+# In this testcase, the file `a' is 18.5 blocks long and the file `b'
+# is 19.5 blocks long.
+
+AT_SETUP([multivolume header creation])
+AT_KEYWORDS([multivolume multiv multiv08])
+
+AT_TAR_CHECK([
+genfile --length 9472 --file a
+genfile --length 9984 --file b
+decho Creating
+tar -c -M -L10 -f A.tar -f B.tar -f C.tar a b
+decho Testing
+tar -tMR -f A.tar -f B.tar -f C.tar
+],
+[0],
+[Creating
+Testing
+block 0: a
+block 21: b
+block 43: ** Block of NULs **
+],
+[Creating
+Testing
+],
+[],
+[],
+[gnu])
+
+AT_CLEANUP
+
+
+
index eb460cc66ad6b87647f85d6cbc0f16a6b46c7025..48597d4c6ca61afb899e4c1a5679181fce57cd35 100644 (file)
@@ -19,7 +19,7 @@
 # 02110-1301, USA.
 
 AT_SETUP([sparse files in PAX MV archives, v.0.0])
-AT_KEYWORDS([sparse multiv sparsemvp sparsemvp00])
+AT_KEYWORDS([sparse multivolume multiv sparsemvp sparsemvp00])
 
 TAR_MVP_TEST(0.0, [0 ABCDEFGHI 1M ABCDEFGHI], [0 ABCDEFGH 1M ABCDEFGHI])
 
index 5a4ad26db64bc0fefe86c731322ff1e05a3aad6e..8e1dccbc9b80cfee2583f060db091fa416358e6c 100644 (file)
@@ -19,7 +19,7 @@
 # 02110-1301, USA.
 
 AT_SETUP([sparse files in PAX MV archives, v.1.0])
-AT_KEYWORDS([sparse multiv sparsemvp sparsemvp10])
+AT_KEYWORDS([sparse multivolume multiv sparsemvp sparsemvp10])
 
 TAR_MVP_TEST(1.0, [0 ABCDEFGH 1M ABCDEFGHI], [0 ABCDEFG 1M ABCDEFGHI])
 
index 2661904d8b66ac4725a763c048387fba90b74a97..37c19073550bae84297142da9eefb377ddb01d36 100644 (file)
@@ -196,6 +196,7 @@ m4_include([multiv04.at])
 m4_include([multiv05.at])
 m4_include([multiv06.at])
 m4_include([multiv07.at])
+m4_include([multiv08.at])
 
 m4_include([old.at])
 
This page took 0.048009 seconds and 4 git commands to generate.