/* List a tar archive, with support routines for reading a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
- 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-26.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any later
+ Free Software Foundation; either version 3, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
{
prev_status = status;
tar_stat_destroy (¤t_stat_info);
- xheader_destroy (&extended_header);
status = read_header (false);
switch (status)
status = read_header (false);
if (status == HEADER_ZERO_BLOCK)
break;
- WARN ((0, 0, _("A lone zero block at %s"),
- STRINGIFY_BIGINT (current_block_ordinal (), buf)));
+ WARNOPT (WARN_ALONE_ZERO_BLOCK,
+ (0, 0, _("A lone zero block at %s"),
+ STRINGIFY_BIGINT (current_block_ordinal (), buf)));
break;
}
status = prev_status;
size_t size, written;
union block *next_long_name = 0;
union block *next_long_link = 0;
- size_t next_long_name_blocks;
- size_t next_long_link_blocks;
+ size_t next_long_name_blocks = 0;
+ size_t next_long_link_blocks = 0;
while (1)
{
}
else if (header->header.typeflag == XHDTYPE
|| header->header.typeflag == SOLARIS_XHDTYPE)
- xheader_read (header, OFF_FROM_HEADER (header->header.size));
+ xheader_read (&info->xhdr, header,
+ OFF_FROM_HEADER (header->header.size));
else if (header->header.typeflag == XGLTYPE)
{
- xheader_read (header, OFF_FROM_HEADER (header->header.size));
- xheader_decode_global ();
- xheader_destroy (&extended_header);
+ struct xheader xhdr;
+ memset (&xhdr, 0, sizeof xhdr);
+ xheader_read (&xhdr, header,
+ OFF_FROM_HEADER (header->header.size));
+ xheader_decode_global (&xhdr);
+ xheader_destroy (&xhdr);
}
/* Loop! */
}
static char *
-decode_xform (char *file_name)
+decode_xform (char *file_name, void *data)
{
- file_name = safer_name_suffix (file_name, false, absolute_names_option);
+ 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,
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_pointer, int do_user_group)
{
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
&& ISOCTAL (header->star_header.ctime[0])
&& header->star_header.ctime[11] == ' ')
format = STAR_FORMAT;
- else if (extended_header.size)
+ else if (stat_info->xhdr.size)
format = POSIX_FORMAT;
else
format = USTAR_FORMAT;
}
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
- format = OLDGNU_FORMAT;
+ format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
else
format = V7_FORMAT;
*format_pointer = format;
- stat_info->stat.st_mode = MODE_FROM_HEADER (header->header.mode);
+ stat_info->stat.st_mode = mode;
stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
stat_info->mtime.tv_nsec = 0;
assign_string (&stat_info->uname,
stat_info->is_dumpdir = true;
}
- transform_name_fp (&stat_info->file_name, decode_xform);
+ 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) TYPE_MAXIMUM (minor_t), false, false);
}
+/* Convert P to the file mode, as understood by tar.
+ Store unrecognized mode bits (from 10th up) in HBITS. */
mode_t
-mode_from_header (const char *p, size_t s)
+mode_from_header (const char *p, size_t s, unsigned *hbits)
{
- /* Do not complain about unrecognized mode bits. */
unsigned u = from_header (p, s, "mode_t",
- (uintmax_t) TYPE_MINIMUM (mode_t),
TYPE_MAXIMUM (uintmax_t), false, false);
- return ((u & TSUID ? S_ISUID : 0)
- | (u & TSGID ? S_ISGID : 0)
- | (u & TSVTX ? S_ISVTX : 0)
- | (u & TUREAD ? S_IRUSR : 0)
- | (u & TUWRITE ? S_IWUSR : 0)
- | (u & TUEXEC ? S_IXUSR : 0)
- | (u & TGREAD ? S_IRGRP : 0)
- | (u & TGWRITE ? S_IWGRP : 0)
- | (u & TGEXEC ? S_IXGRP : 0)
- | (u & TOREAD ? S_IROTH : 0)
- | (u & TOWRITE ? S_IWOTH : 0)
- | (u & TOEXEC ? S_IXOTH : 0));
+ mode_t mode = ((u & TSUID ? S_ISUID : 0)
+ | (u & TSGID ? S_ISGID : 0)
+ | (u & TSVTX ? S_ISVTX : 0)
+ | (u & TUREAD ? S_IRUSR : 0)
+ | (u & TUWRITE ? S_IWUSR : 0)
+ | (u & TUEXEC ? S_IXUSR : 0)
+ | (u & TGREAD ? S_IRGRP : 0)
+ | (u & TGWRITE ? S_IWGRP : 0)
+ | (u & TGEXEC ? S_IXGRP : 0)
+ | (u & TOREAD ? S_IROTH : 0)
+ | (u & TOWRITE ? S_IWOTH : 0)
+ | (u & TOEXEC ? S_IXOTH : 0));
+ *hbits = mode ^ u;
+ return mode;
}
off_t