]> Dogcows Code - chaz/tar/blobdiff - src/list.c
Fix `--test-label' and `--label -r' behavior.
[chaz/tar] / src / list.c
index 3394e90d30d8896f7544e233c7a9455aaacccd76..0474fb1e5ad40a02cab4f5c76f076ed7e1e9ffc3 100644 (file)
@@ -78,7 +78,8 @@ read_and (void (*do_something) (void))
       prev_status = status;
       tar_stat_destroy (&current_stat_info);
 
-      status = read_header (&current_header, &current_stat_info, false);
+      status = read_header (&current_header, &current_stat_info, 
+                            read_header_auto);
       switch (status)
        {
        case HEADER_STILL_UNREAD:
@@ -139,7 +140,8 @@ read_and (void (*do_something) (void))
            {
              char buf[UINTMAX_STRSIZE_BOUND];
 
-             status = read_header (&current_header, &current_stat_info, false);
+             status = read_header (&current_header, &current_stat_info, 
+                                   read_header_auto);
              if (status == HEADER_ZERO_BLOCK)
                break;
              WARNOPT (WARN_ALONE_ZERO_BLOCK,
@@ -282,21 +284,29 @@ tar_checksum (union block *header, bool silent)
 }
 
 /* Read a block that's supposed to be a header block.  Return its
-   address in "current_header", and if it is good, the file's size
-   and names (file name, link name) in *info.
+   address in *RETURN_BLOCK, and if it is good, the file's size
+   and names (file name, link name) in *INFO.
 
-   Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a
-   block full of zeros (EOF marker).
+   Return one of enum read_header describing the status of the
+   operation.
 
-   If RAW_EXTENDED_HEADERS is nonzero, do not automagically fold the
-   GNU long name and link headers into later headers.
+   The MODE parameter instructs read_header what to do with special
+   header blocks, i.e.: extended POSIX, GNU long name or long link,
+   etc.:
 
-   You must always set_next_block_after(current_header) to skip past
+     read_header_auto        process them automatically,
+     read_header_x_raw       when a special header is read, return
+                             HEADER_SUCCESS_EXTENDED without actually
+                            processing the header,
+     read_header_x_global    when a POSIX global header is read,
+                             decode it and return HEADER_SUCCESS_EXTENDED.
+
+   You must always set_next_block_after(*return_block) to skip past
    the header which this routine reads.  */
 
 enum read_header
 read_header (union block **return_block, struct tar_stat_info *info,
-            bool raw_extended_headers)
+            enum read_header_mode mode)
 {
   union block *header;
   union block *header_copy;
@@ -333,7 +343,7 @@ read_header (union block **return_block, struct tar_stat_info *info,
          || header->header.typeflag == XGLTYPE
          || header->header.typeflag == SOLARIS_XHDTYPE)
        {
-         if (raw_extended_headers)
+         if (mode == read_header_x_raw)
            return HEADER_SUCCESS_EXTENDED;
          else if (header->header.typeflag == GNUTYPE_LONGNAME
                   || header->header.typeflag == GNUTYPE_LONGLINK)
@@ -405,6 +415,8 @@ read_header (union block **return_block, struct tar_stat_info *info,
                            OFF_FROM_HEADER (header->header.size));
              xheader_decode_global (&xhdr);
              xheader_destroy (&xhdr);
+             if (mode == read_header_x_global)
+               return HEADER_SUCCESS_EXTENDED;
            }
 
          /* Loop!  */
@@ -672,7 +684,8 @@ from_header (char const *where0, size_t digs, char const *type,
        {
          if (type && !silent)
            ERROR ((0, 0,
-                   /* TRANSLATORS: %s is type of the value (gid_t, uid_t, etc.) */
+                   /* TRANSLATORS: %s is type of the value (gid_t, uid_t,
+                      etc.) */
                    _("Blanks in header where numeric %s value expected"),
                    type));
          return -1;
@@ -1053,9 +1066,6 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
   int pad;
   int sizelen;
 
-  if (test_label_option && blk->header.typeflag != GNUTYPE_VOLHDR)
-    return;
-
   if (show_transformed_names_option)
     temp_name = st->file_name ? st->file_name : st->orig_file_name;
   else
@@ -1282,30 +1292,36 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
 }
 
 
+void
+print_volume_label ()
+{
+  struct tar_stat_info vstat;
+  union block vblk;
+  enum archive_format dummy;
+
+  memset (&vblk, 0, sizeof (vblk));
+  vblk.header.typeflag = GNUTYPE_VOLHDR;
+  if (recent_global_header)
+    memcpy (vblk.header.mtime, recent_global_header->header.mtime,
+           sizeof vblk.header.mtime);
+  tar_stat_init (&vstat);
+  assign_string (&vstat.file_name, ".");
+  decode_header (&vblk, &vstat, &dummy, 0);
+  assign_string (&vstat.file_name, volume_label);
+  simple_print_header (&vstat, &vblk, 0);
+  tar_stat_destroy (&vstat);
+}
+
 void
 print_header (struct tar_stat_info *st, union block *blk,
              off_t block_ordinal)
 {
   if (current_format == POSIX_FORMAT && !volume_label_printed && volume_label)
     {
-      struct tar_stat_info vstat;
-      union block vblk;
-      enum archive_format dummy;
-
+      print_volume_label ();
       volume_label_printed = true;
-
-      memset (&vblk, 0, sizeof (vblk));
-      vblk.header.typeflag = GNUTYPE_VOLHDR;
-      if (recent_global_header)
-       memcpy (vblk.header.mtime, recent_global_header->header.mtime,
-               sizeof vblk.header.mtime);
-      tar_stat_init (&vstat);
-      assign_string (&vstat.file_name, ".");
-      decode_header (&vblk, &vstat, &dummy, 0);
-      assign_string (&vstat.file_name, volume_label);
-      simple_print_header (&vstat, &vblk, block_ordinal);
-      tar_stat_destroy (&vstat);
     }
+
   simple_print_header (st, blk, block_ordinal);
 }
 
@@ -1385,3 +1401,34 @@ skip_member (void)
       mv_end ();
     }
 }
+
+void
+test_archive_label ()
+{
+  base64_init ();
+  name_gather ();
+
+  open_archive (ACCESS_READ);
+  if (read_header (&current_header, &current_stat_info, read_header_auto)
+      == HEADER_SUCCESS)
+    {
+      decode_header (current_header,
+                    &current_stat_info, &current_format, 0);
+      if (current_header->header.typeflag == GNUTYPE_VOLHDR)
+       assign_string (&volume_label, current_header->header.name);
+      
+      if (volume_label)
+       {
+         if (verbose_option)
+           print_volume_label ();
+         if (!name_match (volume_label) && multi_volume_option)
+           {
+             char *s = drop_volume_label_suffix (volume_label);
+             name_match (s);
+             free (s);
+           }
+       }
+    }
+  close_archive ();
+  label_notfound ();
+}
This page took 0.02657 seconds and 4 git commands to generate.