| @@ -1,47 +1,46 @@ | | | @@ -1,47 +1,46 @@ |
1 | /* $NetBSD: gzip.c,v 1.118 2022/01/22 14:00:45 christos Exp $ */ | | 1 | /* $NetBSD: gzip.c,v 1.118.2.1 2024/02/04 11:07:40 martin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1997, 1998, 2003, 2004, 2006, 2008, 2009, 2010, 2011, 2015, 2017 | | 4 | * Copyright (c) 1997-2024 Matthew R. Green |
5 | * Matthew R. Green | | | |
6 | * All rights reserved. | | 5 | * All rights reserved. |
7 | * | | 6 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 9 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
16 | * | | 15 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
22 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
24 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 | * SUCH DAMAGE. | | 26 | * SUCH DAMAGE. |
28 | */ | | 27 | */ |
29 | | | 28 | |
30 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
31 | #ifndef lint | | 30 | #ifndef lint |
32 | __COPYRIGHT("@(#) Copyright (c) 1997, 1998, 2003, 2004, 2006, 2008,\ | | 31 | __COPYRIGHT("@(#) Copyright (c) 1997-2024 Matthew R. Green. " |
33 | 2009, 2010, 2011, 2015, 2017 Matthew R. Green. All rights reserved."); | | 32 | "All rights reserved."); |
34 | __RCSID("$NetBSD: gzip.c,v 1.118 2022/01/22 14:00:45 christos Exp $"); | | 33 | __RCSID("$NetBSD: gzip.c,v 1.118.2.1 2024/02/04 11:07:40 martin Exp $"); |
35 | #endif /* not lint */ | | 34 | #endif /* not lint */ |
36 | | | 35 | |
37 | /* | | 36 | /* |
38 | * gzip.c -- GPL free gzip using zlib. | | 37 | * gzip.c -- GPL free gzip using zlib. |
39 | * | | 38 | * |
40 | * RFC 1950 covers the zlib format | | 39 | * RFC 1950 covers the zlib format |
41 | * RFC 1951 covers the deflate format | | 40 | * RFC 1951 covers the deflate format |
42 | * RFC 1952 covers the gzip format | | 41 | * RFC 1952 covers the gzip format |
43 | * | | 42 | * |
44 | * TODO: | | 43 | * TODO: |
45 | * - use mmap where possible | | 44 | * - use mmap where possible |
46 | * - handle some signals better (remove outfile?) | | 45 | * - handle some signals better (remove outfile?) |
47 | * - make bzip2/compress -v/-t/-l support work as well as possible | | 46 | * - make bzip2/compress -v/-t/-l support work as well as possible |
| @@ -163,27 +162,27 @@ static suffixes_t suffixes[] = { | | | @@ -163,27 +162,27 @@ static suffixes_t suffixes[] = { |
163 | #ifndef NO_XZ_SUPPORT | | 162 | #ifndef NO_XZ_SUPPORT |
164 | SUFFIX(XZ_SUFFIX, ""), | | 163 | SUFFIX(XZ_SUFFIX, ""), |
165 | #endif | | 164 | #endif |
166 | #ifndef NO_LZ_SUPPORT | | 165 | #ifndef NO_LZ_SUPPORT |
167 | SUFFIX(LZ_SUFFIX, ""), | | 166 | SUFFIX(LZ_SUFFIX, ""), |
168 | #endif | | 167 | #endif |
169 | SUFFIX(GZ_SUFFIX, ""), /* Overwritten by -S "" */ | | 168 | SUFFIX(GZ_SUFFIX, ""), /* Overwritten by -S "" */ |
170 | #endif /* SMALL */ | | 169 | #endif /* SMALL */ |
171 | #undef SUFFIX | | 170 | #undef SUFFIX |
172 | }; | | 171 | }; |
173 | #define NUM_SUFFIXES (sizeof suffixes / sizeof suffixes[0]) | | 172 | #define NUM_SUFFIXES (sizeof suffixes / sizeof suffixes[0]) |
174 | #define SUFFIX_MAXLEN 30 | | 173 | #define SUFFIX_MAXLEN 30 |
175 | | | 174 | |
176 | static const char gzip_version[] = "NetBSD gzip 20170803"; | | 175 | static const char gzip_version[] = "NetBSD gzip 20240203"; |
177 | | | 176 | |
178 | static int cflag; /* stdout mode */ | | 177 | static int cflag; /* stdout mode */ |
179 | static int dflag; /* decompress mode */ | | 178 | static int dflag; /* decompress mode */ |
180 | static int lflag; /* list mode */ | | 179 | static int lflag; /* list mode */ |
181 | static int numflag = 6; /* gzip -1..-9 value */ | | 180 | static int numflag = 6; /* gzip -1..-9 value */ |
182 | | | 181 | |
183 | #ifndef SMALL | | 182 | #ifndef SMALL |
184 | static int fflag; /* force mode */ | | 183 | static int fflag; /* force mode */ |
185 | static int kflag; /* don't delete input files */ | | 184 | static int kflag; /* don't delete input files */ |
186 | static int nflag; /* don't save name/timestamp */ | | 185 | static int nflag; /* don't save name/timestamp */ |
187 | static int Nflag; /* don't restore name/timestamp */ | | 186 | static int Nflag; /* don't restore name/timestamp */ |
188 | static int qflag; /* quiet mode */ | | 187 | static int qflag; /* quiet mode */ |
189 | static int rflag; /* recursive mode */ | | 188 | static int rflag; /* recursive mode */ |
| @@ -1104,34 +1103,34 @@ copymodes(int fd, const struct stat *sbp | | | @@ -1104,34 +1103,34 @@ copymodes(int fd, const struct stat *sbp |
1104 | | | 1103 | |
1105 | /* if the chown fails, remove set-id bits as-per compress(1) */ | | 1104 | /* if the chown fails, remove set-id bits as-per compress(1) */ |
1106 | if (fchown(fd, sb.st_uid, sb.st_gid) < 0) { | | 1105 | if (fchown(fd, sb.st_uid, sb.st_gid) < 0) { |
1107 | if (errno != EPERM) | | 1106 | if (errno != EPERM) |
1108 | maybe_warn("couldn't fchown: %s", file); | | 1107 | maybe_warn("couldn't fchown: %s", file); |
1109 | sb.st_mode &= ~(S_ISUID|S_ISGID); | | 1108 | sb.st_mode &= ~(S_ISUID|S_ISGID); |
1110 | } | | 1109 | } |
1111 | | | 1110 | |
1112 | /* we only allow set-id and the 9 normal permission bits */ | | 1111 | /* we only allow set-id and the 9 normal permission bits */ |
1113 | sb.st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; | | 1112 | sb.st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; |
1114 | if (fchmod(fd, sb.st_mode) < 0) | | 1113 | if (fchmod(fd, sb.st_mode) < 0) |
1115 | maybe_warn("couldn't fchmod: %s", file); | | 1114 | maybe_warn("couldn't fchmod: %s", file); |
1116 | | | 1115 | |
1117 | /* only try flags if they exist already */ | | | |
1118 | if (sb.st_flags != 0 && fchflags(fd, sb.st_flags) < 0) | | | |
1119 | maybe_warn("couldn't fchflags: %s", file); | | | |
1120 | | | | |
1121 | TIMESPEC_TO_TIMEVAL(×[0], &sb.st_atimespec); | | 1116 | TIMESPEC_TO_TIMEVAL(×[0], &sb.st_atimespec); |
1122 | TIMESPEC_TO_TIMEVAL(×[1], &sb.st_mtimespec); | | 1117 | TIMESPEC_TO_TIMEVAL(×[1], &sb.st_mtimespec); |
1123 | if (futimes(fd, times) < 0) | | 1118 | if (futimes(fd, times) < 0) |
1124 | maybe_warn("couldn't utimes: %s", file); | | 1119 | maybe_warn("couldn't utimes: %s", file); |
| | | 1120 | |
| | | 1121 | /* finally, only try flags if they exist already */ |
| | | 1122 | if (sb.st_flags != 0 && fchflags(fd, sb.st_flags) < 0) |
| | | 1123 | maybe_warn("couldn't fchflags: %s", file); |
1125 | } | | 1124 | } |
1126 | #endif | | 1125 | #endif |
1127 | | | 1126 | |
1128 | /* what sort of file is this? */ | | 1127 | /* what sort of file is this? */ |
1129 | static enum filetype | | 1128 | static enum filetype |
1130 | file_gettype(u_char *buf) | | 1129 | file_gettype(u_char *buf) |
1131 | { | | 1130 | { |
1132 | | | 1131 | |
1133 | if (buf[0] == GZIP_MAGIC0 && | | 1132 | if (buf[0] == GZIP_MAGIC0 && |
1134 | (buf[1] == GZIP_MAGIC1 || buf[1] == GZIP_OMAGIC1)) | | 1133 | (buf[1] == GZIP_MAGIC1 || buf[1] == GZIP_OMAGIC1)) |
1135 | return FT_GZIP; | | 1134 | return FT_GZIP; |
1136 | else | | 1135 | else |
1137 | #ifndef NO_BZIP2_SUPPORT | | 1136 | #ifndef NO_BZIP2_SUPPORT |
| @@ -1390,27 +1389,27 @@ file_compress(char *file, char *outfile, | | | @@ -1390,27 +1389,27 @@ file_compress(char *file, char *outfile, |
1390 | maybe_warnx("leaving original %s", file); | | 1389 | maybe_warnx("leaving original %s", file); |
1391 | unlink(outfile); | | 1390 | unlink(outfile); |
1392 | return size; | | 1391 | return size; |
1393 | #endif | | 1392 | #endif |
1394 | } | | 1393 | } |
1395 | | | 1394 | |
1396 | /* uncompress the given file and remove the original */ | | 1395 | /* uncompress the given file and remove the original */ |
1397 | static off_t | | 1396 | static off_t |
1398 | file_uncompress(char *file, char *outfile, size_t outsize) | | 1397 | file_uncompress(char *file, char *outfile, size_t outsize) |
1399 | { | | 1398 | { |
1400 | struct stat isb, osb; | | 1399 | struct stat isb, osb; |
1401 | off_t size; | | 1400 | off_t size; |
1402 | ssize_t rbytes; | | 1401 | ssize_t rbytes; |
1403 | unsigned char header1[4]; | | 1402 | unsigned char fourbytes[4]; |
1404 | enum filetype method; | | 1403 | enum filetype method; |
1405 | int fd, ofd, zfd = -1; | | 1404 | int fd, ofd, zfd = -1; |
1406 | size_t in_size; | | 1405 | size_t in_size; |
1407 | #ifndef SMALL | | 1406 | #ifndef SMALL |
1408 | ssize_t rv; | | 1407 | ssize_t rv; |
1409 | time_t timestamp = 0; | | 1408 | time_t timestamp = 0; |
1410 | char name[PATH_MAX + 1]; | | 1409 | char name[PATH_MAX + 1]; |
1411 | #endif | | 1410 | #endif |
1412 | | | 1411 | |
1413 | /* gather the old name info */ | | 1412 | /* gather the old name info */ |
1414 | | | 1413 | |
1415 | fd = open(file, O_RDONLY); | | 1414 | fd = open(file, O_RDONLY); |
1416 | if (fd < 0) { | | 1415 | if (fd < 0) { |
| @@ -1424,66 +1423,66 @@ file_uncompress(char *file, char *outfil | | | @@ -1424,66 +1423,66 @@ file_uncompress(char *file, char *outfil |
1424 | } | | 1423 | } |
1425 | if (S_ISREG(isb.st_mode)) | | 1424 | if (S_ISREG(isb.st_mode)) |
1426 | in_size = isb.st_size; | | 1425 | in_size = isb.st_size; |
1427 | else | | 1426 | else |
1428 | in_size = 0; | | 1427 | in_size = 0; |
1429 | infile_set(file, in_size); | | 1428 | infile_set(file, in_size); |
1430 | | | 1429 | |
1431 | strlcpy(outfile, file, outsize); | | 1430 | strlcpy(outfile, file, outsize); |
1432 | if (check_suffix(outfile, 1) == NULL && !(cflag || lflag)) { | | 1431 | if (check_suffix(outfile, 1) == NULL && !(cflag || lflag)) { |
1433 | maybe_warnx("%s: unknown suffix -- ignored", file); | | 1432 | maybe_warnx("%s: unknown suffix -- ignored", file); |
1434 | goto lose; | | 1433 | goto lose; |
1435 | } | | 1434 | } |
1436 | | | 1435 | |
1437 | rbytes = read(fd, header1, sizeof header1); | | 1436 | rbytes = read(fd, fourbytes, sizeof fourbytes); |
1438 | if (rbytes != sizeof header1) { | | 1437 | if (rbytes != sizeof fourbytes) { |
1439 | /* we don't want to fail here. */ | | 1438 | /* we don't want to fail here. */ |
1440 | #ifndef SMALL | | 1439 | #ifndef SMALL |
1441 | if (fflag) | | 1440 | if (fflag) |
1442 | goto lose; | | 1441 | goto lose; |
1443 | #endif | | 1442 | #endif |
1444 | if (rbytes == -1) | | 1443 | if (rbytes == -1) |
1445 | maybe_warn("can't read %s", file); | | 1444 | maybe_warn("can't read %s", file); |
1446 | else | | 1445 | else |
1447 | goto unexpected_EOF; | | 1446 | goto unexpected_EOF; |
1448 | goto lose; | | 1447 | goto lose; |
1449 | } | | 1448 | } |
1450 | infile_newdata(rbytes); | | 1449 | infile_newdata(rbytes); |
1451 | | | 1450 | |
1452 | method = file_gettype(header1); | | 1451 | method = file_gettype(fourbytes); |
1453 | #ifndef SMALL | | 1452 | #ifndef SMALL |
1454 | if (fflag == 0 && method == FT_UNKNOWN) { | | 1453 | if (fflag == 0 && method == FT_UNKNOWN) { |
1455 | maybe_warnx("%s: not in gzip format", file); | | 1454 | maybe_warnx("%s: not in gzip format", file); |
1456 | goto lose; | | 1455 | goto lose; |
1457 | } | | 1456 | } |
1458 | | | 1457 | |
1459 | #endif | | 1458 | #endif |
1460 | | | 1459 | |
1461 | #ifndef SMALL | | 1460 | #ifndef SMALL |
1462 | if (method == FT_GZIP && Nflag) { | | 1461 | if (method == FT_GZIP && Nflag) { |
1463 | unsigned char ts[4]; /* timestamp */ | | 1462 | unsigned char ts[4]; /* timestamp */ |
1464 | | | 1463 | |
1465 | rv = pread(fd, ts, sizeof ts, GZIP_TIMESTAMP); | | 1464 | rv = pread(fd, ts, sizeof ts, GZIP_TIMESTAMP); |
1466 | if (rv >= 0 && rv < (ssize_t)(sizeof ts)) | | 1465 | if (rv >= 0 && rv < (ssize_t)(sizeof ts)) |
1467 | goto unexpected_EOF; | | 1466 | goto unexpected_EOF; |
1468 | if (rv == -1) { | | 1467 | if (rv == -1) { |
1469 | if (!fflag) | | 1468 | if (!fflag) |
1470 | maybe_warn("can't read %s", file); | | 1469 | maybe_warn("can't read %s", file); |
1471 | goto lose; | | 1470 | goto lose; |
1472 | } | | 1471 | } |
1473 | infile_newdata(rv); | | 1472 | infile_newdata(rv); |
1474 | timestamp = ts[3] << 24 | ts[2] << 16 | ts[1] << 8 | ts[0]; | | 1473 | timestamp = ts[3] << 24 | ts[2] << 16 | ts[1] << 8 | ts[0]; |
1475 | | | 1474 | |
1476 | if (header1[3] & ORIG_NAME) { | | 1475 | if (fourbytes[3] & ORIG_NAME) { |
1477 | rbytes = pread(fd, name, sizeof(name) - 1, GZIP_ORIGNAME); | | 1476 | rbytes = pread(fd, name, sizeof(name) - 1, GZIP_ORIGNAME); |
1478 | if (rbytes < 0) { | | 1477 | if (rbytes < 0) { |
1479 | maybe_warn("can't read %s", file); | | 1478 | maybe_warn("can't read %s", file); |
1480 | goto lose; | | 1479 | goto lose; |
1481 | } | | 1480 | } |
1482 | if (name[0] != '\0') { | | 1481 | if (name[0] != '\0') { |
1483 | char *dp, *nf; | | 1482 | char *dp, *nf; |
1484 | | | 1483 | |
1485 | /* Make sure that name is NUL-terminated */ | | 1484 | /* Make sure that name is NUL-terminated */ |
1486 | name[rbytes] = '\0'; | | 1485 | name[rbytes] = '\0'; |
1487 | | | 1486 | |
1488 | /* strip saved directory name */ | | 1487 | /* strip saved directory name */ |
1489 | nf = strrchr(name, '/'); | | 1488 | nf = strrchr(name, '/'); |
| @@ -1777,27 +1776,27 @@ cat_fd(unsigned char * prepend, size_t c | | | @@ -1777,27 +1776,27 @@ cat_fd(unsigned char * prepend, size_t c |
1777 | in_tot += rv; | | 1776 | in_tot += rv; |
1778 | } | | 1777 | } |
1779 | | | 1778 | |
1780 | if (gsizep) | | 1779 | if (gsizep) |
1781 | *gsizep = in_tot; | | 1780 | *gsizep = in_tot; |
1782 | return (in_tot); | | 1781 | return (in_tot); |
1783 | } | | 1782 | } |
1784 | #endif | | 1783 | #endif |
1785 | | | 1784 | |
1786 | static void | | 1785 | static void |
1787 | handle_stdin(void) | | 1786 | handle_stdin(void) |
1788 | { | | 1787 | { |
1789 | struct stat isb; | | 1788 | struct stat isb; |
1790 | unsigned char header1[4]; | | 1789 | unsigned char fourbytes[4]; |
1791 | size_t in_size; | | 1790 | size_t in_size; |
1792 | off_t usize, gsize; | | 1791 | off_t usize, gsize; |
1793 | enum filetype method; | | 1792 | enum filetype method; |
1794 | ssize_t bytes_read; | | 1793 | ssize_t bytes_read; |
1795 | #ifndef NO_COMPRESS_SUPPORT | | 1794 | #ifndef NO_COMPRESS_SUPPORT |
1796 | FILE *in; | | 1795 | FILE *in; |
1797 | #endif | | 1796 | #endif |
1798 | | | 1797 | |
1799 | #ifndef SMALL | | 1798 | #ifndef SMALL |
1800 | if (fflag == 0 && lflag == 0 && isatty(STDIN_FILENO)) { | | 1799 | if (fflag == 0 && lflag == 0 && isatty(STDIN_FILENO)) { |
1801 | maybe_warnx("standard input is a terminal -- ignoring"); | | 1800 | maybe_warnx("standard input is a terminal -- ignoring"); |
1802 | goto out; | | 1801 | goto out; |
1803 | } | | 1802 | } |
| @@ -1808,84 +1807,84 @@ handle_stdin(void) | | | @@ -1808,84 +1807,84 @@ handle_stdin(void) |
1808 | goto out; | | 1807 | goto out; |
1809 | } | | 1808 | } |
1810 | if (S_ISREG(isb.st_mode)) | | 1809 | if (S_ISREG(isb.st_mode)) |
1811 | in_size = isb.st_size; | | 1810 | in_size = isb.st_size; |
1812 | else | | 1811 | else |
1813 | in_size = 0; | | 1812 | in_size = 0; |
1814 | infile_set("(stdin)", in_size); | | 1813 | infile_set("(stdin)", in_size); |
1815 | | | 1814 | |
1816 | if (lflag) { | | 1815 | if (lflag) { |
1817 | print_list(STDIN_FILENO, in_size, infile, isb.st_mtime); | | 1816 | print_list(STDIN_FILENO, in_size, infile, isb.st_mtime); |
1818 | goto out; | | 1817 | goto out; |
1819 | } | | 1818 | } |
1820 | | | 1819 | |
1821 | bytes_read = read_retry(STDIN_FILENO, header1, sizeof header1); | | 1820 | bytes_read = read_retry(STDIN_FILENO, fourbytes, sizeof fourbytes); |
1822 | if (bytes_read == -1) { | | 1821 | if (bytes_read == -1) { |
1823 | maybe_warn("can't read stdin"); | | 1822 | maybe_warn("can't read stdin"); |
1824 | goto out; | | 1823 | goto out; |
1825 | } else if (bytes_read != sizeof(header1)) { | | 1824 | } else if (bytes_read != sizeof(fourbytes)) { |
1826 | maybe_warnx("(stdin): unexpected end of file"); | | 1825 | maybe_warnx("(stdin): unexpected end of file"); |
1827 | goto out; | | 1826 | goto out; |
1828 | } | | 1827 | } |
1829 | | | 1828 | |
1830 | method = file_gettype(header1); | | 1829 | method = file_gettype(fourbytes); |
1831 | switch (method) { | | 1830 | switch (method) { |
1832 | default: | | 1831 | default: |
1833 | #ifndef SMALL | | 1832 | #ifndef SMALL |
1834 | if (fflag == 0) { | | 1833 | if (fflag == 0) { |
1835 | maybe_warnx("unknown compression format"); | | 1834 | maybe_warnx("unknown compression format"); |
1836 | goto out; | | 1835 | goto out; |
1837 | } | | 1836 | } |
1838 | usize = cat_fd(header1, sizeof header1, &gsize, STDIN_FILENO); | | 1837 | usize = cat_fd(fourbytes, sizeof fourbytes, &gsize, STDIN_FILENO); |
1839 | break; | | 1838 | break; |
1840 | #endif | | 1839 | #endif |
1841 | case FT_GZIP: | | 1840 | case FT_GZIP: |
1842 | usize = gz_uncompress(STDIN_FILENO, STDOUT_FILENO, | | 1841 | usize = gz_uncompress(STDIN_FILENO, STDOUT_FILENO, |
1843 | (char *)header1, sizeof header1, &gsize, "(stdin)"); | | 1842 | (char *)fourbytes, sizeof fourbytes, &gsize, "(stdin)"); |
1844 | break; | | 1843 | break; |
1845 | #ifndef NO_BZIP2_SUPPORT | | 1844 | #ifndef NO_BZIP2_SUPPORT |
1846 | case FT_BZIP2: | | 1845 | case FT_BZIP2: |
1847 | usize = unbzip2(STDIN_FILENO, STDOUT_FILENO, | | 1846 | usize = unbzip2(STDIN_FILENO, STDOUT_FILENO, |
1848 | (char *)header1, sizeof header1, &gsize); | | 1847 | (char *)fourbytes, sizeof fourbytes, &gsize); |
1849 | break; | | 1848 | break; |
1850 | #endif | | 1849 | #endif |
1851 | #ifndef NO_COMPRESS_SUPPORT | | 1850 | #ifndef NO_COMPRESS_SUPPORT |
1852 | case FT_Z: | | 1851 | case FT_Z: |
1853 | if ((in = zdopen(STDIN_FILENO)) == NULL) { | | 1852 | if ((in = zdopen(STDIN_FILENO)) == NULL) { |
1854 | maybe_warnx("zopen of stdin"); | | 1853 | maybe_warnx("zopen of stdin"); |
1855 | goto out; | | 1854 | goto out; |
1856 | } | | 1855 | } |
1857 | | | 1856 | |
1858 | usize = zuncompress(in, stdout, (char *)header1, | | 1857 | usize = zuncompress(in, stdout, (char *)fourbytes, |
1859 | sizeof header1, &gsize); | | 1858 | sizeof fourbytes, &gsize); |
1860 | fclose(in); | | 1859 | fclose(in); |
1861 | break; | | 1860 | break; |
1862 | #endif | | 1861 | #endif |
1863 | #ifndef NO_PACK_SUPPORT | | 1862 | #ifndef NO_PACK_SUPPORT |
1864 | case FT_PACK: | | 1863 | case FT_PACK: |
1865 | usize = unpack(STDIN_FILENO, STDOUT_FILENO, | | 1864 | usize = unpack(STDIN_FILENO, STDOUT_FILENO, |
1866 | (char *)header1, sizeof header1, &gsize); | | 1865 | (char *)fourbytes, sizeof fourbytes, &gsize); |
1867 | break; | | 1866 | break; |
1868 | #endif | | 1867 | #endif |
1869 | #ifndef NO_XZ_SUPPORT | | 1868 | #ifndef NO_XZ_SUPPORT |
1870 | case FT_XZ: | | 1869 | case FT_XZ: |
1871 | usize = unxz(STDIN_FILENO, STDOUT_FILENO, | | 1870 | usize = unxz(STDIN_FILENO, STDOUT_FILENO, |
1872 | (char *)header1, sizeof header1, &gsize); | | 1871 | (char *)fourbytes, sizeof fourbytes, &gsize); |
1873 | break; | | 1872 | break; |
1874 | #endif | | 1873 | #endif |
1875 | #ifndef NO_LZ_SUPPORT | | 1874 | #ifndef NO_LZ_SUPPORT |
1876 | case FT_LZ: | | 1875 | case FT_LZ: |
1877 | usize = unlz(STDIN_FILENO, STDOUT_FILENO, | | 1876 | usize = unlz(STDIN_FILENO, STDOUT_FILENO, |
1878 | (char *)header1, sizeof header1, &gsize); | | 1877 | (char *)fourbytes, sizeof fourbytes, &gsize); |
1879 | break; | | 1878 | break; |
1880 | #endif | | 1879 | #endif |
1881 | } | | 1880 | } |
1882 | | | 1881 | |
1883 | #ifndef SMALL | | 1882 | #ifndef SMALL |
1884 | if (vflag && !tflag && usize != -1 && gsize != -1) | | 1883 | if (vflag && !tflag && usize != -1 && gsize != -1) |
1885 | print_verbage(NULL, NULL, usize, gsize); | | 1884 | print_verbage(NULL, NULL, usize, gsize); |
1886 | if (vflag && tflag) | | 1885 | if (vflag && tflag) |
1887 | print_test("(stdin)", usize != -1); | | 1886 | print_test("(stdin)", usize != -1); |
1888 | #else | | 1887 | #else |
1889 | (void)&usize; | | 1888 | (void)&usize; |
1890 | #endif | | 1889 | #endif |
1891 | | | 1890 | |
| @@ -2027,45 +2026,45 @@ handle_file(char *file, struct stat *sbp | | | @@ -2027,45 +2026,45 @@ handle_file(char *file, struct stat *sbp |
2027 | } | | 2026 | } |
2028 | | | 2027 | |
2029 | #ifndef SMALL | | 2028 | #ifndef SMALL |
2030 | /* this is used with -r to recursively descend directories */ | | 2029 | /* this is used with -r to recursively descend directories */ |
2031 | static void | | 2030 | static void |
2032 | handle_dir(char *dir) | | 2031 | handle_dir(char *dir) |
2033 | { | | 2032 | { |
2034 | char *path_argv[2]; | | 2033 | char *path_argv[2]; |
2035 | FTS *fts; | | 2034 | FTS *fts; |
2036 | FTSENT *entry; | | 2035 | FTSENT *entry; |
2037 | | | 2036 | |
2038 | path_argv[0] = dir; | | 2037 | path_argv[0] = dir; |
2039 | path_argv[1] = 0; | | 2038 | path_argv[1] = 0; |
2040 | fts = fts_open(path_argv, FTS_PHYSICAL, NULL); | | 2039 | fts = fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL); |
2041 | if (fts == NULL) { | | 2040 | if (fts == NULL) { |
2042 | warn("couldn't fts_open %s", dir); | | 2041 | warn("couldn't fts_open %s", dir); |
2043 | return; | | 2042 | return; |
2044 | } | | 2043 | } |
2045 | | | 2044 | |
2046 | while ((entry = fts_read(fts))) { | | 2045 | while ((entry = fts_read(fts))) { |
2047 | switch(entry->fts_info) { | | 2046 | switch(entry->fts_info) { |
2048 | case FTS_D: | | 2047 | case FTS_D: |
2049 | case FTS_DP: | | 2048 | case FTS_DP: |
2050 | continue; | | 2049 | continue; |
2051 | | | 2050 | |
2052 | case FTS_DNR: | | 2051 | case FTS_DNR: |
2053 | case FTS_ERR: | | 2052 | case FTS_ERR: |
2054 | case FTS_NS: | | 2053 | case FTS_NS: |
2055 | maybe_warn("%s", entry->fts_path); | | 2054 | maybe_warn("%s", entry->fts_path); |
2056 | continue; | | 2055 | continue; |
2057 | case FTS_F: | | 2056 | case FTS_F: |
2058 | handle_file(entry->fts_name, entry->fts_statp); | | 2057 | handle_file(entry->fts_path, entry->fts_statp); |
2059 | } | | 2058 | } |
2060 | } | | 2059 | } |
2061 | (void)fts_close(fts); | | 2060 | (void)fts_close(fts); |
2062 | } | | 2061 | } |
2063 | #endif | | 2062 | #endif |
2064 | | | 2063 | |
2065 | /* print a ratio - size reduction as a fraction of uncompressed size */ | | 2064 | /* print a ratio - size reduction as a fraction of uncompressed size */ |
2066 | static void | | 2065 | static void |
2067 | print_ratio(off_t in, off_t out, FILE *where) | | 2066 | print_ratio(off_t in, off_t out, FILE *where) |
2068 | { | | 2067 | { |
2069 | int percent10; /* 10 * percent */ | | 2068 | int percent10; /* 10 * percent */ |
2070 | off_t diff; | | 2069 | off_t diff; |
2071 | char buff[8]; | | 2070 | char buff[8]; |