diff options
author | rsc <devnull@localhost> | 2004-04-14 20:09:21 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-04-14 20:09:21 +0000 |
commit | ff3adf608207084d1454acddfdb8904bb139c5e4 (patch) | |
tree | 5910aeb723542a38d374f84c575e94ddfd935eb9 /src/cmd/gzip/gzip.c | |
parent | 4314729ddef28cb619ce97d50f0968ca24c93803 (diff) | |
download | plan9port-ff3adf608207084d1454acddfdb8904bb139c5e4.tar.gz plan9port-ff3adf608207084d1454acddfdb8904bb139c5e4.tar.bz2 plan9port-ff3adf608207084d1454acddfdb8904bb139c5e4.zip |
add gzip, bzip2
'
Diffstat (limited to 'src/cmd/gzip/gzip.c')
-rw-r--r-- | src/cmd/gzip/gzip.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/cmd/gzip/gzip.c b/src/cmd/gzip/gzip.c new file mode 100644 index 00000000..10954d3a --- /dev/null +++ b/src/cmd/gzip/gzip.c @@ -0,0 +1,212 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <flate.h> +#include "gzip.h" + +static int gzipf(char*, int); +static int gzip(char*, long, int, Biobuf*); +static int crcread(void *fd, void *buf, int n); +static int gzwrite(void *bout, void *buf, int n); + +static Biobuf bout; +static ulong crc; +static ulong *crctab; +static int debug; +static int eof; +static int level; +static ulong totr; +static int verbose; + +void +usage(void) +{ + fprint(2, "usage: gzip [-vcD] [-1-9] [file ...]\n"); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + int i, ok, stdout; + + level = 6; + stdout = 0; + ARGBEGIN{ + case 'D': + debug++; + break; + case 'v': + verbose++; + break; + case 'c': + stdout = 1; + break; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + level = ARGC() - '0'; + break; + default: + usage(); + break; + }ARGEND + + crctab = mkcrctab(GZCRCPOLY); + ok = deflateinit(); + if(ok != FlateOk) + sysfatal("deflateinit failed: %s\n", flateerr(ok)); + + if(argc == 0){ + Binit(&bout, 1, OWRITE); + ok = gzip(nil, time(0), 0, &bout); + Bterm(&bout); + }else{ + ok = 1; + for(i = 0; i < argc; i++) + ok &= gzipf(argv[i], stdout); + } + exits(ok ? nil: "errors"); +} + +static int +gzipf(char *file, int stdout) +{ + Dir *dir; + char ofile[256], *f, *s; + int ifd, ofd, ok; + + ifd = open(file, OREAD); + if(ifd < 0){ + fprint(2, "gzip: can't open %s: %r\n", file); + return 0; + } + dir = dirfstat(ifd); + if(dir == nil){ + fprint(2, "gzip: can't stat %s: %r\n", file); + close(ifd); + return 0; + } + if(dir->mode & DMDIR){ + fprint(2, "gzip: can't compress a directory\n"); + close(ifd); + free(dir); + return 0; + } + + if(stdout){ + ofd = 1; + strcpy(ofile, "<stdout>"); + }else{ + f = strrchr(file, '/'); + if(f != nil) + f++; + else + f = file; + s = strrchr(f, '.'); + if(s != nil && s != ofile && strcmp(s, ".tar") == 0){ + *s = '\0'; + snprint(ofile, sizeof(ofile), "%s.tgz", f); + }else + snprint(ofile, sizeof(ofile), "%s.gz", f); + ofd = create(ofile, OWRITE, 0666); + if(ofd < 0){ + fprint(2, "gzip: can't open %s: %r\n", ofile); + close(ifd); + return 0; + } + } + + if(verbose) + fprint(2, "compressing %s to %s\n", file, ofile); + + Binit(&bout, ofd, OWRITE); + ok = gzip(file, dir->mtime, ifd, &bout); + if(!ok || Bflush(&bout) < 0){ + fprint(2, "gzip: error writing %s: %r\n", ofile); + if(!stdout) + remove(ofile); + } + Bterm(&bout); + free(dir); + close(ifd); + close(ofd); + return ok; +} + +static int +gzip(char *file, long mtime, int ifd, Biobuf *bout) +{ + int flags, err; + + flags = 0; + Bputc(bout, GZMAGIC1); + Bputc(bout, GZMAGIC2); + Bputc(bout, GZDEFLATE); + + if(file != nil) + flags |= GZFNAME; + Bputc(bout, flags); + + Bputc(bout, mtime); + Bputc(bout, mtime>>8); + Bputc(bout, mtime>>16); + Bputc(bout, mtime>>24); + + Bputc(bout, 0); + Bputc(bout, GZOSINFERNO); + + if(flags & GZFNAME) + Bwrite(bout, file, strlen(file)+1); + + crc = 0; + eof = 0; + totr = 0; + err = deflate(bout, gzwrite, (void*)ifd, crcread, level, debug); + if(err != FlateOk){ + fprint(2, "gzip: deflate failed: %s\n", flateerr(err)); + return 0; + } + + Bputc(bout, crc); + Bputc(bout, crc>>8); + Bputc(bout, crc>>16); + Bputc(bout, crc>>24); + + Bputc(bout, totr); + Bputc(bout, totr>>8); + Bputc(bout, totr>>16); + Bputc(bout, totr>>24); + + return 1; +} + +static int +crcread(void *fd, void *buf, int n) +{ + int nr, m; + + nr = 0; + for(; !eof && n > 0; n -= m){ + m = read((int)fd, (char*)buf+nr, n); + if(m <= 0){ + eof = 1; + if(m < 0) + return -1; + break; + } + nr += m; + } + crc = blockcrc(crctab, crc, buf, nr); + totr += nr; + return nr; +} + +static int +gzwrite(void *bout, void *buf, int n) +{ + if(n != Bwrite(bout, buf, n)){ + eof = 1; + return -1; + } + return n; +} |