]> Dogcows Code - chaz/tar/commitdiff
Improve handling of --test-label.
authorSergey Poznyakoff <gray@gnu.org.ua>
Sun, 24 Jan 2010 14:52:24 +0000 (16:52 +0200)
committerSergey Poznyakoff <gray@gnu.org.ua>
Sun, 24 Jan 2010 14:58:04 +0000 (16:58 +0200)
* src/list.c (print_volume_label): New function.
(print_header): Call print_volume_label.
(test_archive_label): New function.
* src/buffer.c (VOLUME_LABEL_APPEND): Remove.
(VOLUME_TEXT, VOLUME_TEXT_LEN): New macros
(drop_volume_label_suffix): New function.
(check_label_pattern): Use drop_volume_label_suffix.
* src/common.h (subcommand): New constant TEST_LABEL_SUBCOMMAND.
(test_label_option): Remove.
(drop_volume_label_suffix): New proto.
(test_archive_label): New proto.
* src/names.c (all_names_found): Remove test for test_label_option.
* src/tar.c (subcommand_string): Handle TEST_LABEL_SUBCOMMAND.
(set_subcommand_option): Improve diagnostics.
(parse_opt): Set subcommand if --test-label is given.
(main): Handle TEST_LABEL_SUBCOMMAND.

src/buffer.c
src/common.h
src/list.c
src/names.c
src/tar.c

index ed7530342398c15f316c3c2e372db25a3c81a7f3..f419dd7bcb357232ca76f254a78417c0a6794142 100644 (file)
@@ -36,9 +36,6 @@
 /* Number of retries before giving up on read.  */
 #define READ_ERROR_MAX 10
 
-/* Globbing pattern to append to volume label if initial match failed.  */
-#define VOLUME_LABEL_APPEND " Volume [1-9]*"
-
 /* Variables.  */
 
 static tarlong prev_written;    /* bytes written on previous volumes */
@@ -1313,6 +1310,35 @@ try_new_volume ()
 }
 
 \f
+#define VOLUME_TEXT " Volume "
+#define VOLUME_TEXT_LEN (sizeof VOLUME_TEXT - 1)
+
+char *
+drop_volume_label_suffix (const char *label)
+{
+  const char *p;
+  size_t len = strlen (label);
+
+  if (len < 1)
+    return NULL;
+  
+  for (p = label + len - 1; p > label && isdigit ((unsigned char) *p); p--)
+    ;
+  if (p > label && p - (VOLUME_TEXT_LEN - 1) > label)
+    {
+      p -= VOLUME_TEXT_LEN - 1;
+      if (memcmp (p, VOLUME_TEXT, VOLUME_TEXT_LEN) == 0)
+       {
+         char *s = xmalloc ((len = p - label) + 1);
+         memcpy (s, label, len);
+         s[len] = 0;
+         return s;
+       }
+    }
+
+  return NULL;
+}
+      
 /* Check LABEL against the volume label, seen as a globbing
    pattern.  Return true if the pattern matches.  In case of failure,
    retry matching a volume sequence number before giving up in
@@ -1329,12 +1355,12 @@ check_label_pattern (const char *label)
   if (!multi_volume_option)
     return false;
 
-  string = xmalloc (strlen (volume_label_option)
-                    + sizeof VOLUME_LABEL_APPEND + 1);
-  strcpy (string, volume_label_option);
-  strcat (string, VOLUME_LABEL_APPEND);
-  result = fnmatch (string, label, 0) == 0;
-  free (string);
+  string = drop_volume_label_suffix (label);
+  if (string)
+    {
+      result = fnmatch (string, volume_label_option, 0) == 0;
+      free (string);
+    }
   return result;
 }
 
index 2af403c102535725e4279b2526242071edd5b3b1..271211592eaa395b0d9a05ca9a493da596410a45 100644 (file)
@@ -85,7 +85,8 @@ enum subcommand
   DIFF_SUBCOMMAND,             /* -d */
   EXTRACT_SUBCOMMAND,          /* -x */
   LIST_SUBCOMMAND,             /* -t */
-  UPDATE_SUBCOMMAND            /* -u */
+  UPDATE_SUBCOMMAND,           /* -u */
+  TEST_LABEL_SUBCOMMAND,        /* --test-label */
 };
 
 GLOBAL enum subcommand subcommand_option;
@@ -362,8 +363,6 @@ GLOBAL dev_t root_device;
 /* Unquote filenames */
 GLOBAL bool unquote_option;
 
-GLOBAL bool test_label_option; /* Test archive volume label and exit */
-
 /* Show file or archive names after transformation.
    In particular, when creating archive in verbose mode, list member names
    as stored in the archive */
@@ -403,6 +402,8 @@ extern uintmax_t continued_file_size;
 extern uintmax_t continued_file_offset;
 extern off_t records_written;
 
+char *drop_volume_label_suffix (const char *label);
+
 size_t available_space_after (union block *pointer);
 off_t current_block_ordinal (void);
 void close_archive (void);
@@ -578,6 +579,7 @@ uid_t uid_from_header (const char *buf, size_t size);
 uintmax_t uintmax_from_header (const char *buf, size_t size);
 
 void list_archive (void);
+void test_archive_label (void);
 void print_for_mkdir (char *dirname, int length, mode_t mode);
 void print_header (struct tar_stat_info *st, union block *blk,
                   off_t block_ordinal);
index 3394e90d30d8896f7544e233c7a9455aaacccd76..5a341aad2c81d5deb1505ff7f48cf2d515443749 100644 (file)
@@ -672,7 +672,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 +1054,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 +1280,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 +1389,33 @@ 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, false)
+      == HEADER_SUCCESS)
+    {
+      char *s = NULL;
+       
+      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
+         && (name_match (volume_label)
+             || (multi_volume_option
+                 && (s = drop_volume_label_suffix (volume_label))
+                 && name_match (s))))
+       if (verbose_option)
+         print_volume_label ();
+      free (s);
+    }
+  close_archive ();
+  names_notfound ();
+}
index 0e50aa401b3ca31ccd33199fb5c064d1f6b6405e..ef011b70d0ea56315ea99090a43066ab0bda2bf1 100644 (file)
@@ -577,8 +577,6 @@ all_names_found (struct tar_stat_info *p)
   struct name const *cursor;
   size_t len;
 
-  if (test_label_option)
-    return true;
   if (!p->file_name || occurrence_option == 0 || p->had_trailing_slash)
     return false;
   len = strlen (p->file_name);
index a1185f6cbb089f08e8d9181cbfa84f0c5869d4ee..31e71efe2b4a11f07f52576472051ff157bd60ba 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -214,9 +214,10 @@ subcommand_string (enum subcommand c)
     case UPDATE_SUBCOMMAND:
       return "-u";
 
-    default:
-      abort ();
+    case TEST_LABEL_SUBCOMMAND:
+      return "--test-label";
     }
+  abort ();
 }
 
 void
@@ -921,7 +922,7 @@ set_subcommand_option (enum subcommand subcommand)
   if (subcommand_option != UNKNOWN_SUBCOMMAND
       && subcommand_option != subcommand)
     USAGE_ERROR ((0, 0,
-                 _("You may not specify more than one `-Acdtrux' option")));
+                 _("You may not specify more than one `-Acdtrux' or `--test-label' option")));
   
   subcommand_option = subcommand;
 }
@@ -1612,8 +1613,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
       
     case TEST_LABEL_OPTION:
-      set_subcommand_option (LIST_SUBCOMMAND);
-      test_label_option = true;
+      set_subcommand_option (TEST_LABEL_SUBCOMMAND);
       break;
       
     case 'T':
@@ -2437,7 +2437,7 @@ decode_options (int argc, char **argv)
     old_files_option = UNLINK_FIRST_OLD_FILES;
 
 
-  if (test_label_option)
+  if (subcommand_option == TEST_LABEL_SUBCOMMAND)
     {
       /* --test-label is silent if the user has specified the label name to
         compare against. */
@@ -2472,6 +2472,7 @@ decode_options (int argc, char **argv)
     case EXTRACT_SUBCOMMAND:
     case LIST_SUBCOMMAND:
     case DIFF_SUBCOMMAND:
+    case TEST_LABEL_SUBCOMMAND:
       for (archive_name_cursor = archive_name_array;
           archive_name_cursor < archive_name_array + archive_names;
           archive_name_cursor++)
@@ -2578,7 +2579,7 @@ main (int argc, char **argv)
     {
     case UNKNOWN_SUBCOMMAND:
       USAGE_ERROR ((0, 0,
-                   _("You must specify one of the `-Acdtrux' options")));
+                   _("You must specify one of the `-Acdtrux' or `--test-label'  options")));
 
     case CAT_SUBCOMMAND:
     case UPDATE_SUBCOMMAND:
@@ -2612,6 +2613,9 @@ main (int argc, char **argv)
       diff_init ();
       read_and (diff_archive);
       break;
+
+    case TEST_LABEL_SUBCOMMAND:
+      test_archive_label ();
     }
 
   if (totals_option)
This page took 0.032561 seconds and 4 git commands to generate.