diff options
-rw-r--r-- | toys/pending/gzip.c | 106 |
1 files changed, 38 insertions, 68 deletions
diff --git a/toys/pending/gzip.c b/toys/pending/gzip.c index 72e8fe4c..f6d797b5 100644 --- a/toys/pending/gzip.c +++ b/toys/pending/gzip.c @@ -3,8 +3,10 @@ * Copyright 2017 The Android Open Source Project * * GZIP RFC: http://www.ietf.org/rfc/rfc1952.txt + * + * todo: qtv --rsyncable -// Existing implementations allow all options for all commands. +// gzip.net version allows all options for all commands. USE_GZIP(NEWTOY(gzip, "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN)) USE_GUNZIP(NEWTOY(gunzip, "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN)) USE_ZCAT(NEWTOY(zcat, "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN)) @@ -50,7 +52,6 @@ config ZCAT Decompress files to stdout. Like `gzip -dc`. - -c Output to stdout (default) -f Force: allow read from tty */ @@ -71,32 +72,36 @@ static void fix_time(const char *path, struct stat *sb) if (utimensat(AT_FDCWD, path, times, 0)) perror_exit("utimensat"); } -static void gzerror_msg(gzFile f, char *what) +static int do_zlib(int in_fd, int out_fd) { - int err; - const char *msg = gzerror(f, &err); - - ((err == Z_ERRNO) ? perror_msg : error_msg)("%s: %s", what, msg); -} + int len, err = 0, dd = toys.optflags&FLAG_d; + char *b = "r"; + gzFile gz; + if (!dd) { + sprintf(b = toybuf, "w%d", TT.level); + if (out_fd == 1) out_fd = xdup(out_fd); + } + if (!(gz = gzdopen(dd ? in_fd : out_fd, b))) perror_exit("gzdopen"); + if (dd) { + while ((len = gzread(gz, toybuf, sizeof(toybuf))) > 0) + if (len != writeall(out_fd, toybuf, len)) break; + } else { + while ((len = read(in_fd, toybuf, sizeof(toybuf))) > 0) + if (len != gzwrite(gz, toybuf, len)) break; + } -static int zlib_inflate(int in_fd, int out_fd) -{ - int len, err = 0; - gzFile in; + err = !!len; + if (len>0 || err == Z_ERRNO) perror_msg(dd ? "write" : "read"); + if (len<0) + error_msg("%s%s: %s", "gz", dd ? "read" : "write", gzerror(gz, &len)); - if (!(in = gzdopen(in_fd, "r"))) perror_exit("gzdopen"); - while ((len = gzread(in, toybuf, sizeof(toybuf))) > 0) - if (len != writeall(out_fd, toybuf, len)) break; - if (len) err = 1; - if (len>0) perror_msg("write"); - if (len<0) gzerror_msg(in, "gzread"); - if (gzclose(in) != Z_OK) perror_msg("gzclose"), err++; + if (gzclose(gz) != Z_OK) perror_msg("gzclose"), err++; return err; } -static void do_gunzip(int in_fd, char *arg) +static void do_gzip(int in_fd, char *arg) { struct stat sb; int len, out_fd = 0; @@ -113,25 +118,29 @@ static void do_gunzip(int in_fd, char *arg) // Are we reading file.gz to write to file? if (!out_fd) { - // "gunzip x.gz" will decompress "x.gz" to "x". - if ((len = strlen(arg))<4 || strcmp(arg+len-3, ".gz")) { - error_msg("no .gz: %s", arg); - return; - } if (fstat(in_fd, &sb)) { perror_msg("%s", arg); return; } - out_name = xstrdup(arg); - out_name[len-3] = 0; + if (!(toys.optflags&FLAG_d)) out_name = xmprintf("%s%s", arg, ".gz"); + else { + // "gunzip x.gz" will decompress "x.gz" to "x". + if ((len = strlen(arg))<4 || strcmp(arg+len-3, ".gz")) { + error_msg("no .gz: %s", arg); + return; + } + out_name = xstrdup(arg); + out_name[len-3] = 0; + } + out_fd = xcreate(out_name, O_CREAT|O_WRONLY|WARN_ONLY|(O_EXCL*!(toys.optflags&FLAG_f)), sb.st_mode); if (out_fd == -1) return; } // if (CFG_TOYBOX_LIBZ) - if (zlib_inflate(in_fd, out_fd) && out_name) arg = out_name; + if (do_zlib(in_fd, out_fd) && out_name) arg = out_name; if (out_fd != 1) close(out_fd); if (out_name) { @@ -141,52 +150,13 @@ static void do_gunzip(int in_fd, char *arg) } } -static void do_gzip(int in_fd, char *in_name) -{ - size_t len; - char *out_name; - FILE *in = xfdopen(in_fd, "r"); - gzFile out; - struct stat sb; - int both_files, out_fd; - - out_name = (toys.optflags&FLAG_c) ? strdup("-") : xmprintf("%s.gz", in_name); - both_files = strcmp(in_name, "-") && strcmp(out_name, "-"); - if (both_files) xstat(in_name, &sb); - - if (!strcmp(out_name, "-")) out_fd = dup(1); - else { - out_fd = open(out_name, O_CREAT|O_WRONLY|((toys.optflags&FLAG_f)?0:O_EXCL), - both_files?sb.st_mode:0); - } - if (out_fd == -1) perror_exit("open %s", out_name); - - snprintf(toybuf, sizeof(toybuf), "w%d", TT.level); - out = gzdopen(out_fd, toybuf); - if (out == NULL) perror_exit("gzdopen %s", out_name); - - while ((len = fread(toybuf, 1, sizeof(toybuf), in)) > 0) { - if (gzwrite(out, toybuf, len) != (int) len) { - gzerror_msg(out, "gzwrite"); - return; - } - } - if (ferror(in)) perror_exit("fread"); - if (fclose(in)) perror_exit("fclose"); - if (gzclose(out) != Z_OK) error_exit("gzclose"); - - if (both_files) fix_time(out_name, &sb); - if (!(toys.optflags&(FLAG_c|FLAG_k))) unlink(in_name); - free(out_name); -} - void gzip_main(void) { for (TT.level = 0; TT.level<9; TT.level++) if ((toys.optflags>>TT.level)&1) break; if (!(TT.level = 9-TT.level)) TT.level = 6; - loopfiles(toys.optargs, (toys.optflags&FLAG_d) ? do_gunzip : do_gzip); + loopfiles(toys.optargs, do_gzip); } void gunzip_main(void) |