123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- #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;
- }
|