size_t recent_long_link_blocks; /* likewise, for long link */
union block *recent_global_header; /* Recent global header block */
+#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
+#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
+#define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
+#define MODE_FROM_HEADER(where, hbits) \
+ mode_from_header (where, sizeof (where), hbits)
+#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
+#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
+
+static gid_t gid_from_header (const char *buf, size_t size);
+static major_t major_from_header (const char *buf, size_t size);
+static minor_t minor_from_header (const char *buf, size_t size);
+static mode_t mode_from_header (const char *buf, size_t size, unsigned *hbits);
+static time_t time_from_header (const char *buf, size_t size);
+static uid_t uid_from_header (const char *buf, size_t size);
static uintmax_t from_header (const char *, size_t, const char *,
uintmax_t, uintmax_t, bool, bool);
base64_map[(int) base_64_digits[i]] = i;
}
+static char *
+decode_xform (char *file_name, void *data)
+{
+ int type = *(int*)data;
+
+ switch (type)
+ {
+ case XFORM_SYMLINK:
+ /* FIXME: It is not quite clear how and to which extent are the symbolic
+ links subject to filename transformation. In the absence of another
+ solution, symbolic links are exempt from component stripping and
+ name suffix normalization, but subject to filename transformation
+ proper. */
+ return file_name;
+
+ case XFORM_LINK:
+ file_name = safer_name_suffix (file_name, true, absolute_names_option);
+ break;
+
+ case XFORM_REGFILE:
+ file_name = safer_name_suffix (file_name, false, absolute_names_option);
+ break;
+ }
+
+ if (strip_name_components)
+ {
+ size_t prefix_len = stripped_prefix_len (file_name,
+ strip_name_components);
+ if (prefix_len == (size_t) -1)
+ prefix_len = strlen (file_name);
+ file_name += prefix_len;
+ }
+ return file_name;
+}
+
+static bool
+transform_member_name (char **pinput, int type)
+{
+ return transform_name_fp (pinput, type, decode_xform, &type);
+}
+
+void
+transform_stat_info (int typeflag, struct tar_stat_info *stat_info)
+{
+ if (typeflag == GNUTYPE_VOLHDR)
+ /* Name transformations don't apply to volume headers. */
+ return;
+
+ transform_member_name (&stat_info->file_name, XFORM_REGFILE);
+ switch (typeflag)
+ {
+ case SYMTYPE:
+ transform_member_name (&stat_info->link_name, XFORM_SYMLINK);
+ break;
+
+ case LNKTYPE:
+ transform_member_name (&stat_info->link_name, XFORM_LINK);
+ }
+}
+
/* Main loop for reading an archive. */
void
read_and (void (*do_something) (void))
prev_status = status;
tar_stat_destroy (¤t_stat_info);
- status = read_header (¤t_header, ¤t_stat_info,
+ status = read_header (¤t_header, ¤t_stat_info,
read_header_auto);
switch (status)
{
/* Valid header. We should decode next field (mode) first.
Ensure incoming names are null terminated. */
-
+ decode_header (current_header, ¤t_stat_info,
+ ¤t_format, 1);
if (! name_match (current_stat_info.file_name)
|| (NEWER_OPTION_INITIALIZED (newer_mtime_option)
/* FIXME: We get mtime now, and again later; this causes
quotearg_colon (current_stat_info.file_name)));
/* Fall through. */
default:
- decode_header (current_header,
- ¤t_stat_info, ¤t_format, 0);
skip_member ();
continue;
}
}
-
+ transform_stat_info (current_header->header.typeflag,
+ ¤t_stat_info);
(*do_something) ();
continue;
{
char buf[UINTMAX_STRSIZE_BOUND];
- status = read_header (¤t_header, ¤t_stat_info,
+ status = read_header (¤t_header, ¤t_stat_info,
read_header_auto);
if (status == HEADER_ZERO_BLOCK)
break;
off_t block_ordinal = current_block_ordinal ();
/* Print the header block. */
-
- decode_header (current_header, ¤t_stat_info, ¤t_format, 0);
if (verbose_option)
print_header (¤t_stat_info, current_header, block_ordinal);
}
}
-static char *
-decode_xform (char *file_name, void *data)
-{
- int type = *(int*)data;
-
- switch (type)
- {
- case XFORM_SYMLINK:
- /* FIXME: It is not quite clear how and to which extent are the symbolic
- links subject to filename transformation. In the absence of another
- solution, symbolic links are exempt from component stripping and
- name suffix normalization, but subject to filename transformation
- proper. */
- return file_name;
-
- case XFORM_LINK:
- file_name = safer_name_suffix (file_name, true, absolute_names_option);
- break;
-
- case XFORM_REGFILE:
- file_name = safer_name_suffix (file_name, false, absolute_names_option);
- break;
- }
-
- if (strip_name_components)
- {
- size_t prefix_len = stripped_prefix_len (file_name,
- strip_name_components);
- if (prefix_len == (size_t) -1)
- prefix_len = strlen (file_name);
- file_name += prefix_len;
- }
- return file_name;
-}
-
-bool
-transform_member_name (char **pinput, int type)
-{
- return transform_name_fp (pinput, type, decode_xform, &type);
-}
-
#define ISOCTAL(c) ((c)>='0'&&(c)<='7')
/* Decode things from a file HEADER block into STAT_INFO, also setting
enum archive_format format;
unsigned hbits; /* high bits of the file mode. */
mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
-
+
if (strcmp (header->header.magic, TMAGIC) == 0)
{
if (header->star_header.prefix[130] == 0
else
format = USTAR_FORMAT;
}
- else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
+ else if (strcmp (header->buffer + offsetof (struct posix_header, magic),
+ OLDGNU_MAGIC)
+ == 0)
format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
else
format = V7_FORMAT;
|| stat_info->dumpdir)
stat_info->is_dumpdir = true;
}
-
- transform_member_name (&stat_info->file_name, XFORM_REGFILE);
- switch (header->header.typeflag)
- {
- case SYMTYPE:
- transform_member_name (&stat_info->link_name, XFORM_SYMLINK);
- break;
-
- case LNKTYPE:
- transform_member_name (&stat_info->link_name, XFORM_LINK);
- }
}
+
/* Convert buffer at WHERE0 of size DIGS from external format to
uintmax_t. DIGS must be positive. If TYPE is nonnull, the data
are of type TYPE. The buffer must represent a value in the range
return -1;
}
-gid_t
+static gid_t
gid_from_header (const char *p, size_t s)
{
return from_header (p, s, "gid_t",
false, false);
}
-major_t
+static major_t
major_from_header (const char *p, size_t s)
{
return from_header (p, s, "major_t",
(uintmax_t) TYPE_MAXIMUM (major_t), false, false);
}
-minor_t
+static minor_t
minor_from_header (const char *p, size_t s)
{
return from_header (p, s, "minor_t",
/* Convert P to the file mode, as understood by tar.
Store unrecognized mode bits (from 10th up) in HBITS. */
-mode_t
+static mode_t
mode_from_header (const char *p, size_t s, unsigned *hbits)
{
unsigned u = from_header (p, s, "mode_t",
(uintmax_t) TYPE_MAXIMUM (off_t), false, false);
}
-size_t
-size_from_header (const char *p, size_t s)
-{
- return from_header (p, s, "size_t", (uintmax_t) 0,
- (uintmax_t) TYPE_MAXIMUM (size_t), false, false);
-}
-
-time_t
+static time_t
time_from_header (const char *p, size_t s)
{
return from_header (p, s, "time_t",
(uintmax_t) TYPE_MAXIMUM (time_t), false, false);
}
-uid_t
+static uid_t
uid_from_header (const char *p, size_t s)
{
return from_header (p, s, "uid_t",
/* Time stamp. */
- time_stamp = tartime (st->mtime, false);
+ time_stamp = tartime (st->mtime, full_time_option);
time_stamp_len = strlen (time_stamp);
if (datewidth < time_stamp_len)
datewidth = time_stamp_len;
}
-void
-print_volume_label ()
+static void
+print_volume_label (void)
{
struct tar_stat_info vstat;
union block vblk;
{
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)
{
char save_typeflag = current_header->header.typeflag;
set_next_block_after (current_header);
- mv_begin (¤t_stat_info);
+ mv_begin_read (¤t_stat_info);
if (current_stat_info.is_sparse)
sparse_skip_file (¤t_stat_info);
if (read_header (¤t_header, ¤t_stat_info, read_header_auto)
== 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);
+ 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 ();
- names_notfound ();
+ label_notfound ();
}