Control: tag -1 + patch The attached patch fixes the issue. It uses st.st_mode as a base when creating a new file (falling back to usual 0666 when dealing with stdin). It also uses the same stat attributes as used when creating the file.
One more thing which is good to have here (it is also potential security issue) is to use fchmod/fchown/etc instead of chmod/chown/etc, due to possible symlink tricks, but this might be a bit more changes than needed for the main fix. Thanks, /mjt
--- pigz.c.orig 2012-03-11 22:36:30.000000000 +0400 +++ pigz.c 2013-02-16 12:11:46.107311386 +0400 @@ -2926,29 +2926,24 @@ local char *justname(char *path) return p + 1; } -/* Copy file attributes, from -> to, as best we can. This is best effort, so +/* Set file attributes, st -> to, as best we can. This is best effort, so no errors are reported. The mode bits, including suid, sgid, and the sticky - bit are copied (if allowed), the owner's user id and group id are copied - (again if allowed), and the access and modify times are copied. */ -local void copymeta(char *from, char *to) + bit are set (if allowed), the owner's user id and group id are set + (again if allowed), and the access and modify times are set. */ +local void setmeta(const struct stat *st, char *to) { - struct stat st; struct timeval times[2]; - /* get all of from's Unix meta data, return if not a regular file */ - if (stat(from, &st) != 0 || (st.st_mode & S_IFMT) != S_IFREG) - return; - /* set to's mode bits, ignore errors */ - (void)chmod(to, st.st_mode & 07777); + (void)chmod(to, st->st_mode & 07777); /* copy owner's user and group, ignore errors */ - (void)chown(to, st.st_uid, st.st_gid); + (void)chown(to, st->st_uid, st->st_gid); /* copy access and modify times, ignore errors */ - times[0].tv_sec = st.st_atime; + times[0].tv_sec = st->st_atime; times[0].tv_usec = 0; - times[1].tv_sec = st.st_mtime; + times[1].tv_sec = st->st_mtime; times[1].tv_usec = 0; (void)utimes(to, times); } @@ -2984,6 +2979,7 @@ local void process(char *path) mtime = headis & 2 ? (fstat(ind, &st) ? time(NULL) : st.st_mtime) : 0; len = 0; + st.st_mode = 0666; } else { /* set input file name (already set if recursed here) */ @@ -3228,7 +3224,7 @@ local void process(char *path) memcpy(out, to, len); strcpy(out + len, decode ? "" : sufx); outd = open(out, O_CREAT | O_TRUNC | O_WRONLY | - (force ? 0 : O_EXCL), 0666); + (force ? 0 : O_EXCL), st.st_mode & 0777); /* if exists and not -f, give user a chance to overwrite */ if (outd < 0 && errno == EEXIST && isatty(0) && verbosity) { @@ -3244,7 +3240,7 @@ local void process(char *path) } while (ch != EOF && ch != '\n' && ch != '\r'); if (reply == 1) outd = open(out, O_CREAT | O_TRUNC | O_WRONLY, - 0666); + st.st_mode & 0777); } /* if exists and no overwrite, report and go on to next */ @@ -3297,7 +3293,7 @@ local void process(char *path) bail("write error on ", out); outd = -1; /* now prevent deletion on interrupt */ if (ind != 0) { - copymeta(in, out); + setmeta(&st, out); if (!keep) unlink(in); }