From: Paul Eggert Date: Fri, 2 Jul 1999 21:05:50 +0000 (+0000) Subject: (mode_to_oct): Do not assume internal mode_t and external octal modes X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=66e89f0fa59bb2907084585efbbc03af70949099;p=chaz%2Ftar (mode_to_oct): Do not assume internal mode_t and external octal modes have the same bit patterns. (start_header): Do not assume mode bits have traditional Unix values. (finish_sparse_file): Use lseek whence macros instead of integers. (dump_file): Do not assume mode bits have traditional Unix values. Do not invoke finish_sparse_file on a negative file descriptor. --- diff --git a/src/create.c b/src/create.c index 7c2b49f..ebc0442 100644 --- a/src/create.c +++ b/src/create.c @@ -141,7 +141,29 @@ minor_to_oct (minor_t v, char *p, size_t s) void mode_to_oct (mode_t v, char *p, size_t s) { - to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "mode_t"); + /* In the common case where the internal and external mode bits are the same, + propagate all unknown bits to the external mode. + This matches historical practice. + Otherwise, just copy the bits we know about. */ + uintmax_t u = + ((S_ISUID == TSUID && S_ISGID == TSGID && S_ISVTX == TSVTX + && S_IRUSR == TUREAD && S_IWUSR == TUWRITE && S_IXUSR == TUEXEC + && S_IRGRP == TGREAD && S_IWGRP == TGWRITE && S_IXGRP == TGEXEC + && S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC) + ? v + : ((v & S_ISUID ? TSUID : 0) + | (v & S_ISGID ? TSGID : 0) + | (v & S_ISVTX ? TSVTX : 0) + | (v & S_IRUSR ? TUREAD : 0) + | (v & S_IWUSR ? TUWRITE : 0) + | (v & S_IXUSR ? TUEXEC : 0) + | (v & S_IRGRP ? TGREAD : 0) + | (v & S_IWGRP ? TGWRITE : 0) + | (v & S_IXGRP ? TGEXEC : 0) + | (v & S_IROTH ? TOREAD : 0) + | (v & S_IWOTH ? TOWRITE : 0) + | (v & S_IXOTH ? TOEXEC : 0))); + to_oct (u, (uintmax_t) 0, p, s, "mode_t"); } void off_to_oct (off_t v, char *p, size_t s) @@ -332,7 +354,7 @@ Removing leading `/' from absolute path names in the archive"))); acceptor for Paul's test. */ if (archive_format == V7_FORMAT) - MODE_TO_OCT (st->st_mode & 07777, header->header.mode); + MODE_TO_OCT (st->st_mode & MODE_ALL, header->header.mode); else MODE_TO_OCT (st->st_mode, header->header.mode); @@ -404,8 +426,8 @@ finish_header (union block *header) /* Fill in the checksum field. It's formatted differently from the other fields: it has [6] digits, a null, then a space -- rather than digits, then a null. We use to_oct. - The final space is already there, from checksumming, - and to_oct doesn't modify it. + The final space is already there, from + checksumming, and to_oct doesn't modify it. This is a fast way to do: @@ -620,7 +642,7 @@ finish_sparse_file (int file, off_t *sizeleft, off_t fullsize, char *name) break; } - if (lseek (file, sparsearray[sparse_index++].offset, 0) < 0) + if (lseek (file, sparsearray[sparse_index++].offset, SEEK_SET) < 0) { char buf[UINTMAX_STRSIZE_BOUND]; ERROR ((0, errno, _("lseek error at byte %s in file %s"), @@ -1061,7 +1083,8 @@ Removing leading `/' from absolute links"))); files when archive is meant for /dev/null. */ if (dev_null_output - || (sizeleft == 0 && 0444 == (0444 & current_stat.st_mode))) + || (sizeleft == 0 + && MODE_R == (MODE_R & current_stat.st_mode))) f = -1; else { @@ -1144,7 +1167,8 @@ Removing leading `/' from absolute links"))); } if (save_typeflag == GNUTYPE_SPARSE) { - if (finish_sparse_file (f, &sizeleft, current_stat.st_size, p)) + if (f < 0 + || finish_sparse_file (f, &sizeleft, current_stat.st_size, p)) goto padit; } else