X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Flist.c;h=bba430ad8531ed73ec15f8b707fa861e3de97321;hb=2947023d277cb0a787c73721d6190a75444cd65f;hp=98c1e396b3547cb22a5ac590bb24d03b03a9b521;hpb=b4ec8aedf9c8948bee9bf1635132a7da7a522611;p=chaz%2Ftar diff --git a/src/list.c b/src/list.c index 98c1e39..bba430a 100644 --- a/src/list.c +++ b/src/list.c @@ -141,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; @@ -530,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 @@ -545,12 +548,12 @@ decode_header (union block *header, struct tar_stat_info *stat_info, 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, @@ -884,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