X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Flist.c;h=bba430ad8531ed73ec15f8b707fa861e3de97321;hb=2947023d277cb0a787c73721d6190a75444cd65f;hp=19666e998637755c5df57e2e79c125791eaa77bd;hpb=6315d1700be0c937d05aa8889fd2673044160cfe;p=chaz%2Ftar diff --git a/src/list.c b/src/list.c index 19666e9..bba430a 100644 --- a/src/list.c +++ b/src/list.c @@ -1,13 +1,13 @@ /* 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 @@ -76,7 +76,6 @@ read_and (void (*do_something) (void)) { prev_status = status; tar_stat_destroy (¤t_stat_info); - xheader_destroy (&extended_header); status = read_header (false); switch (status) @@ -107,7 +106,6 @@ read_and (void (*do_something) (void)) { case GNUTYPE_VOLHDR: case GNUTYPE_MULTIVOL: - case GNUTYPE_NAMES: break; case DIRTYPE: @@ -143,8 +141,9 @@ read_and (void (*do_something) (void)) 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; @@ -303,8 +302,8 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info) 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) { @@ -388,12 +387,16 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info) } 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! */ @@ -467,6 +470,47 @@ read_header (bool raw_extended_headers) return read_header_primitive (raw_extended_headers, ¤t_stat_info); } +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 @@ -487,7 +531,9 @@ decode_header (union block *header, struct tar_stat_info *stat_info, 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 @@ -496,18 +542,18 @@ decode_header (union block *header, struct tar_stat_info *stat_info, && 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, @@ -584,6 +630,17 @@ decode_header (union block *header, struct tar_stat_info *stat_info, || 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 @@ -830,25 +887,28 @@ minor_from_header (const char *p, size_t s) (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 @@ -980,7 +1040,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal) char modes[11]; char const *time_stamp; int time_stamp_len; - char *temp_name = st->orig_file_name ? st->orig_file_name : st->file_name; + char *temp_name; /* These hold formatted ints. */ char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND]; @@ -994,21 +1054,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal) if (test_label_option && current_header->header.typeflag != GNUTYPE_VOLHDR) return; - if (show_stored_names_option) - { - switch (subcommand_option) - { - case CAT_SUBCOMMAND: - case UPDATE_SUBCOMMAND: - case APPEND_SUBCOMMAND: - case CREATE_SUBCOMMAND: - temp_name = st->file_name ? st->file_name : st->orig_file_name; - break; - - default: - temp_name = st->orig_file_name ? st->orig_file_name : st->file_name; - } - } + if (show_transformed_names_option) + temp_name = st->file_name ? st->file_name : st->orig_file_name; else temp_name = st->orig_file_name ? st->orig_file_name : st->file_name; @@ -1043,10 +1090,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal) modes[0] = 'M'; break; - case GNUTYPE_NAMES: - modes[0] = 'N'; - break; - case GNUTYPE_LONGNAME: case GNUTYPE_LONGLINK: modes[0] = 'L'; @@ -1230,10 +1273,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal) uintbuf)); fprintf (stdlis, _("--Continued at byte %s--\n"), size); break; - - case GNUTYPE_NAMES: - fprintf (stdlis, _("--Mangled file names--\n")); - break; } } fflush (stdlis);