123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "bzlib.h"
- static int bzipf(char*, int);
- static int bzip(char*, long, int, Biobuf*);
- static Biobuf bout;
- static int level;
- static int debug;
- static int verbose;
- static void
- usage(void)
- {
- fprint(2, "usage: bzip2 [-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++;
- 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
- if(argc == 0){
- Binit(&bout, 1, OWRITE);
- ok = bzip(nil, time(0), 0, &bout);
- Bterm(&bout);
- }else{
- ok = 1;
- for(i = 0; i < argc; i++)
- ok &= bzipf(argv[i], stdout);
- }
- exits(ok ? nil: "errors");
- }
- static int
- bzipf(char *file, int stdout)
- {
- Dir *dir;
- char ofile[128], *f, *s;
- int ifd, ofd, ok;
- ifd = open(file, OREAD);
- if(ifd < 0){
- fprint(2, "bzip2: can't open %s: %r\n", file);
- return 0;
- }
- dir = dirfstat(ifd);
- if(dir == nil){
- fprint(2, "bzip2: can't stat %s: %r\n", file);
- close(ifd);
- return 0;
- }
- if(dir->mode & DMDIR){
- fprint(2, "bzip2: 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.tbz", f);
- }else
- snprint(ofile, sizeof(ofile), "%s.bz2", f);
- ofd = create(ofile, OWRITE, 0666);
- if(ofd < 0){
- fprint(2, "bzip2: can't open %s: %r\n", ofile);
- free(dir);
- close(ifd);
- return 0;
- }
- }
- if(verbose)
- fprint(2, "compressing %s to %s\n", file, ofile);
- Binit(&bout, ofd, OWRITE);
- ok = bzip(file, dir->mtime, ifd, &bout);
- if(!ok || Bflush(&bout) < 0){
- fprint(2, "bzip2: error writing %s: %r\n", ofile);
- if(!stdout)
- remove(ofile);
- }
- Bterm(&bout);
- free(dir);
- close(ifd);
- close(ofd);
- return ok;
- }
- static int
- bzip(char *file, long mtime, int ifd, Biobuf *bout)
- {
- int e, n, done, onemore;
- char buf[8192];
- char obuf[8192];
- Biobuf bin;
- bz_stream strm;
- USED(file);
- USED(mtime);
- memset(&strm, 0, sizeof strm);
- BZ2_bzCompressInit(&strm, level, verbose, 0);
- strm.next_in = buf;
- strm.avail_in = 0;
- strm.next_out = obuf;
- strm.avail_out = sizeof obuf;
- done = 0;
- Binit(&bin, ifd, OREAD);
- /*
- * onemore is a crummy hack to go 'round the loop
- * once after we finish, to flush the output buffer.
- */
- onemore = 1;
- SET(e);
- do {
- if(!done && strm.avail_in < sizeof buf) {
- if(strm.avail_in)
- memmove(buf, strm.next_in, strm.avail_in);
-
- n = Bread(&bin, buf+strm.avail_in, sizeof(buf)-strm.avail_in);
- if(n <= 0)
- done = 1;
- else
- strm.avail_in += n;
- strm.next_in = buf;
- }
- if(strm.avail_out < sizeof obuf) {
- Bwrite(bout, obuf, sizeof(obuf)-strm.avail_out);
- strm.next_out = obuf;
- strm.avail_out = sizeof obuf;
- }
- if(onemore == 0)
- break;
- } while((e=BZ2_bzCompress(&strm, done ? BZ_FINISH : BZ_RUN)) == BZ_RUN_OK || e == BZ_FINISH_OK || onemore--);
- if(e != BZ_STREAM_END) {
- fprint(2, "bzip2: compress failed\n");
- return 0;
- }
- if(BZ2_bzCompressEnd(&strm) != BZ_OK) {
- fprint(2, "bzip2: compress end failed (can't happen)\n");
- return 0;
- }
- Bterm(&bin);
- return 1;
- }
|