Improve handling of --test-label.

* 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.
This commit is contained in:
Sergey Poznyakoff
2010-01-24 16:52:24 +02:00
parent 166b7c7d02
commit 28f2669b15
5 changed files with 105 additions and 41 deletions

View 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 ()
}
#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;
}

View 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);

View 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 ();
}

View 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);

View File

@@ -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)