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:
44
src/buffer.c
44
src/buffer.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
74
src/list.c
74
src/list.c
@@ -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 (¤t_header, ¤t_stat_info, false)
|
||||
== HEADER_SUCCESS)
|
||||
{
|
||||
char *s = NULL;
|
||||
|
||||
decode_header (current_header,
|
||||
¤t_stat_info, ¤t_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 ();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
18
src/tar.c
18
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)
|
||||
|
||||
Reference in New Issue
Block a user