X-Git-Url: https://git.saurik.com/apple/file_cmds.git/blobdiff_plain/44a7a5ab64e9df65e241260d76d3dac1160b3360..39aaa94bf0a1c68b3fe15e3622c96766f0f22ff2:/compress/compress.c diff --git a/compress/compress.c b/compress/compress.c index 2aa84ee..0732fa4 100644 --- a/compress/compress.c +++ b/compress/compress.c @@ -1,5 +1,3 @@ -/* $NetBSD: compress.c,v 1.16 1998/03/10 12:45:44 kleink Exp $ */ - /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -12,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -35,75 +29,70 @@ #include #ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ - The Regents of the University of California. All rights reserved.\n"); -#endif /* not lint */ +__used static const char copyright[] = +"@(#) Copyright (c) 1992, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif -#ifndef lint #if 0 +#ifndef lint static char sccsid[] = "@(#)compress.c 8.2 (Berkeley) 1/7/94"; -#else -__RCSID("$NetBSD: compress.c,v 1.16 1998/03/10 12:45:44 kleink Exp $"); #endif -#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/compress/compress.c,v 1.23 2010/12/11 08:32:16 joel Exp $"); #include -#include #include +#include #include #include +#include #include #include #include #include -#ifdef __STDC__ -#include -#else -#include -#endif - -void compress __P((char *, char *, int)); -void cwarn __P((const char *, ...)); -void cwarnx __P((const char *, ...)); -void decompress __P((char *, char *, int)); -int permission __P((char *)); -void setfile __P((char *, struct stat *)); -void usage __P((int)); +#include "zopen.h" -int main __P((int, char *[])); -extern FILE *zopen __P((const char *fname, const char *mode, int bits)); +void compress(const char *, const char *, int); +void cwarn(const char *, ...) __printflike(1, 2); +void cwarnx(const char *, ...) __printflike(1, 2); +void decompress(const char *, const char *, int); +int permission(const char *); +void setfile(const char *, struct stat *); +void usage(int); -int eval, force, verbose; -int isstdout, isstdin; +int eval, force, verbose, cat; int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { - enum {COMPRESS, DECOMPRESS} style = COMPRESS; + enum {COMPRESS, DECOMPRESS} style; size_t len; - int bits, cat, ch; + int bits, ch; char *p, newname[MAXPATHLEN]; - if ((p = strrchr(argv[0], '/')) == NULL) + if (argc < 1) + usage(1); + cat = 0; + if ((p = rindex(argv[0], '/')) == NULL) p = argv[0]; else ++p; if (!strcmp(p, "uncompress")) style = DECOMPRESS; - else if (!strcmp(p, "compress")) - style = COMPRESS; - else if (!strcmp(p, "zcat")) { - style = DECOMPRESS; - cat = 1; - } - else + else if (!strcmp(p, "compress")) + style = COMPRESS; + else if (!strcmp(p, "zcat")) { + cat = 1; + style = DECOMPRESS; + } else errx(1, "unknown program name"); - bits = cat = 0; + bits = 0; while ((ch = getopt(argc, argv, "b:cdfv")) != -1) switch(ch) { case 'b': @@ -131,15 +120,12 @@ main(argc, argv) argv += optind; if (argc == 0) { + cat = 1; switch(style) { case COMPRESS: - isstdout = 1; - isstdin = 1; (void)compress("/dev/stdin", "/dev/stdout", bits); break; case DECOMPRESS: - isstdout = 1; - isstdin = 1; (void)decompress("/dev/stdin", "/dev/stdout", bits); break; } @@ -149,16 +135,18 @@ main(argc, argv) if (cat == 1 && argc > 1) errx(1, "the -c option permits only a single file argument"); - for (; *argv; ++argv) { - isstdout = 0; + for (; *argv; ++argv) switch(style) { case COMPRESS: - if (cat) { - isstdout = 1; + if (strcmp(*argv, "-") == 0) { + cat = 1; + compress("/dev/stdin", "/dev/stdout", bits); + break; + } else if (cat) { compress(*argv, "/dev/stdout", bits); break; } - if ((p = strrchr(*argv, '.')) != NULL && + if ((p = rindex(*argv, '.')) != NULL && !strcmp(p, ".Z")) { cwarnx("%s: name already has trailing .Z", *argv); @@ -176,8 +164,13 @@ main(argc, argv) compress(*argv, newname, bits); break; case DECOMPRESS: + if (strcmp(*argv, "-") == 0) { + cat = 1; + decompress("/dev/stdin", "/dev/stdout", bits); + break; + } len = strlen(*argv); - if ((p = strrchr(*argv, '.')) == NULL || + if ((p = rindex(*argv, '.')) == NULL || strcmp(p, ".Z")) { if (len > sizeof(newname) - 3) { cwarnx("%s: name too long", *argv); @@ -189,8 +182,6 @@ main(argc, argv) newname[len + 2] = '\0'; decompress(newname, cat ? "/dev/stdout" : *argv, bits); - if (cat) - isstdout = 1; } else { if (len - 2 > sizeof(newname) - 1) { cwarnx("%s: name too long", *argv); @@ -200,50 +191,37 @@ main(argc, argv) newname[len - 2] = '\0'; decompress(*argv, cat ? "/dev/stdout" : newname, bits); - if (cat) - isstdout = 1; } break; } - } exit (eval); } void -compress(in, out, bits) - char *in, *out; - int bits; +compress(const char *in, const char *out, int bits) { - int nr; + size_t nr; struct stat isb, sb; - FILE *ifp, *ofp; + FILE *ifp = NULL, *ofp = NULL; int exists, isreg, oreg; - u_char buf[BUFSIZ]; + u_char buf[1024]; - if (!isstdout) { - exists = !stat(out, &sb); - if (!force && exists && S_ISREG(sb.st_mode) && !permission(out)) - return; - oreg = !exists || S_ISREG(sb.st_mode); - } else - oreg = 0; + exists = !stat(out, &sb); + if (!force && exists && S_ISREG(sb.st_mode) && !cat && !permission(out)) { + cwarnx("%s already exists", out); + return; + } + isreg = oreg = !exists || S_ISREG(sb.st_mode); - ifp = ofp = NULL; if ((ifp = fopen(in, "r")) == NULL) { cwarn("%s", in); return; } - - if (!isstdin) { - if (stat(in, &isb)) { /* DON'T FSTAT! */ - cwarn("%s", in); - goto err; - } - if (!S_ISREG(isb.st_mode)) - isreg = 0; - else - isreg = 1; - } else + if (stat(in, &isb)) { /* DON'T FSTAT! */ + cwarn("%s", in); + goto err; + } + if (!S_ISREG(isb.st_mode)) isreg = 0; if ((ofp = zopen(out, "w", bits)) == NULL) { @@ -268,7 +246,7 @@ compress(in, out, bits) } ofp = NULL; - if (isreg && oreg) { + if (!cat && isreg) { if (stat(out, &sb)) { cwarn("%s", out); goto err; @@ -276,7 +254,9 @@ compress(in, out, bits) if (!force && sb.st_size >= isb.st_size) { if (verbose) - (void)printf("%s: file would grow; left unmodified\n", in); + (void)fprintf(stderr, "%s: file would grow; left unmodified\n", + in); + eval = 2; if (unlink(out)) cwarn("%s", out); goto err; @@ -288,19 +268,19 @@ compress(in, out, bits) cwarn("%s", in); if (verbose) { - (void)printf("%s: ", out); + (void)fprintf(stderr, "%s: ", out); if (isb.st_size > sb.st_size) - (void)printf("%.0f%% compression\n", - ((double)sb.st_size / isb.st_size) * 100.0); + (void)fprintf(stderr, "%.0f%% compression\n", + ((float)sb.st_size / isb.st_size) * 100.0); else - (void)printf("%.0f%% expansion\n", - ((double)isb.st_size / sb.st_size) * 100.0); + (void)fprintf(stderr, "%.0f%% expansion\n", + ((float)isb.st_size / sb.st_size) * 100.0); } } return; err: if (ofp) { - if (oreg) + if (!cat && oreg) (void)unlink(out); (void)fclose(ofp); } @@ -309,46 +289,49 @@ err: if (ofp) { } void -decompress(in, out, bits) - char *in, *out; - int bits; +decompress(const char *in, const char *out, int bits) { - int nr; + size_t nr; struct stat sb; FILE *ifp, *ofp; int exists, isreg, oreg; - u_char buf[BUFSIZ]; - - if (!isstdout) { - exists = !stat(out, &sb); - if (!force && exists && S_ISREG(sb.st_mode) && !permission(out)) - return; - oreg = !exists || S_ISREG(sb.st_mode); - } else - oreg = 0; + u_char buf[1024]; - ifp = ofp = NULL; - if ((ofp = fopen(out, "w")) == NULL) { - cwarn("%s", out); + exists = !stat(out, &sb); + if (!force && exists && S_ISREG(sb.st_mode) && !cat && !permission(out)) { + cwarnx("%s already exists", out); return; } + isreg = oreg = !exists || S_ISREG(sb.st_mode); + ofp = NULL; if ((ifp = zopen(in, "r", bits)) == NULL) { + cwarn("%s", in); + return; + } + if (stat(in, &sb)) { cwarn("%s", in); goto err; } - if (!isstdin) { - if (stat(in, &sb)) { - cwarn("%s", in); - goto err; - } - if (!S_ISREG(sb.st_mode)) - isreg = 0; - else - isreg = 1; - } else + if (!S_ISREG(sb.st_mode)) isreg = 0; + /* + * Try to read the first few uncompressed bytes from the input file + * before blindly truncating the output file. + */ + if ((nr = fread(buf, 1, sizeof(buf), ifp)) == 0) { + cwarn("%s", in); + (void)fclose(ifp); + return; + } + if ((ofp = fopen(out, "w")) == NULL || + (nr != 0 && fwrite(buf, 1, nr, ofp) != nr)) { + cwarn("%s", out); + (void)fclose(ifp); + return; + } + while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0) if (fwrite(buf, 1, nr, ofp) != nr) { cwarn("%s", out); @@ -366,16 +349,27 @@ decompress(in, out, bits) goto err; } - if (isreg && oreg) { + if (!cat && isreg) { setfile(out, &sb); if (unlink(in)) cwarn("%s", in); + if (verbose) { + struct stat isb = sb; + stat(out, &sb); + (void)fprintf(stderr, "%s: ", out); + if (isb.st_size > sb.st_size) + (void)fprintf(stderr, "%.0f%% compression\n", + ((float)sb.st_size / isb.st_size) * 100.0); + else + (void)fprintf(stderr, "%.0f%% expansion\n", + ((float)isb.st_size / sb.st_size) * 100.0); + } } return; err: if (ofp) { - if (oreg) + if (!cat && oreg) (void)unlink(out); (void)fclose(ofp); } @@ -384,9 +378,7 @@ err: if (ofp) { } void -setfile(name, fs) - char *name; - struct stat *fs; +setfile(const char *name, struct stat *fs) { static struct timeval tv[2]; @@ -408,21 +400,15 @@ setfile(name, fs) cwarn("chown: %s", name); fs->st_mode &= ~(S_ISUID|S_ISGID); } - if (chmod(name, fs->st_mode)) - cwarn("chown: %s", name); + if (chmod(name, fs->st_mode) && errno != ENOTSUP) + cwarn("chmod: %s", name); - /* - * Restore the file's flags. However, do this only if the original - * file had any flags set; this avoids a warning on file-systems that - * do not support flags. - */ - if (fs->st_flags != 0 && chflags(name, fs->st_flags)) + if (chflags(name, fs->st_flags) && errno != ENOTSUP) cwarn("chflags: %s", name); } int -permission(fname) - char *fname; +permission(const char *fname) { int ch, first; @@ -436,55 +422,34 @@ permission(fname) } void -usage(iscompress) - int iscompress; +usage(int iscompress) { if (iscompress) (void)fprintf(stderr, "usage: compress [-cfv] [-b bits] [file ...]\n"); else (void)fprintf(stderr, - "usage: uncompress [-c] [-b bits] [file ...]\n"); + "usage: uncompress [-cfv] [-b bits] [file ...]\n"); exit(1); } void -#if __STDC__ cwarnx(const char *fmt, ...) -#else -cwarnx(fmt, va_alist) - int eval; - const char *fmt; - va_dcl -#endif { va_list ap; -#if __STDC__ + va_start(ap, fmt); -#else - va_start(ap); -#endif vwarnx(fmt, ap); va_end(ap); eval = 1; } void -#if __STDC__ cwarn(const char *fmt, ...) -#else -cwarn(fmt, va_alist) - int eval; - const char *fmt; - va_dcl -#endif { va_list ap; -#if __STDC__ + va_start(ap, fmt); -#else - va_start(ap); -#endif vwarn(fmt, ap); va_end(ap); eval = 1;