123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "bzlib.h"
- static Biobuf bin;
- static int debug;
- static int verbose;
- static char *delfile;
- static char *infile;
- static int bunzipf(char *file, int stdout);
- static int bunzip(int ofd, char *ofile, Biobuf *bin);
- void
- usage(void)
- {
- fprint(2, "usage: bunzip2 [-cvD] [file ...]\n");
- exits("usage");
- }
- void
- main(int argc, char **argv)
- {
- int i, ok, stdout;
- stdout = 0;
- ARGBEGIN{
- case 'D':
- debug++;
- break;
- case 'c':
- stdout++;
- break;
- case 'v':
- verbose++;
- break;
- }ARGEND
- if(argc == 0){
- Binit(&bin, 0, OREAD);
- infile = "<stdin>";
- ok = bunzip(1, "<stdout>", &bin);
- }else{
- ok = 1;
- for(i = 0; i < argc; i++)
- ok &= bunzipf(argv[i], stdout);
- }
- exits(ok ? nil: "errors");
- }
- static int
- bunzipf(char *file, int stdout)
- {
- char ofile[64], *s;
- int ofd, ifd, ok;
- infile = file;
- ifd = open(file, OREAD);
- if(ifd < 0){
- fprint(2, "gunzip: can't open %s: %r\n", file);
- return 0;
- }
- Binit(&bin, ifd, OREAD);
- if(Bgetc(&bin) != 'B' || Bgetc(&bin) != 'Z' || Bgetc(&bin) != 'h'){
- fprint(2, "bunzip2: %s is not a bzip2 file\n", file);
- Bterm(&bin);
- close(ifd);
- return 0;
- }
- Bungetc(&bin);
- Bungetc(&bin);
- Bungetc(&bin);
- if(stdout){
- ofd = 1;
- strcpy(ofile, "<stdout>");
- }else{
- s = strrchr(file, '/');
- if(s != nil)
- s++;
- else
- s = file;
- strecpy(ofile, ofile+sizeof ofile, s);
- s = strrchr(ofile, '.');
- if(s != nil && s != ofile && strcmp(s, ".bz2") == 0)
- *s = '\0';
- else if(s != nil && (strcmp(s, ".tbz") == 0 || strcmp(s, ".tbz2") == 0))
- strcpy(s, ".tar");
- else if(strcmp(file, ofile) == 0){
- fprint(2, "bunzip2: can't overwrite %s\n", file);
- Bterm(&bin);
- close(ifd);
- return 0;
- }
- ofd = create(ofile, OWRITE, 0666);
- if(ofd < 0){
- fprint(2, "bunzip2: can't create %s: %r\n", ofile);
- Bterm(&bin);
- close(ifd);
- return 0;
- }
- delfile = ofile;
- }
- ok = bunzip(ofd, ofile, &bin);
- Bterm(&bin);
- close(ifd);
- if(!ok){
- fprint(2, "bunzip2: can't write %s: %r\n", ofile);
- if(delfile)
- remove(delfile);
- }
- delfile = nil;
- if(!stdout && ofd >= 0)
- close(ofd);
- return ok;
- }
- static int
- bunzip(int ofd, char *ofile, Biobuf *bin)
- {
- int e, n, done, onemore;
- char buf[8192];
- char obuf[8192];
- Biobuf bout;
- bz_stream strm;
- USED(ofile);
- memset(&strm, 0, sizeof strm);
- BZ2_bzDecompressInit(&strm, verbose, 0);
- strm.next_in = buf;
- strm.avail_in = 0;
- strm.next_out = obuf;
- strm.avail_out = sizeof obuf;
- done = 0;
- Binit(&bout, ofd, OWRITE);
- /*
- * 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;
- if(strm.avail_in == 0 && strm.avail_out == sizeof obuf)
- break;
- } while((e=BZ2_bzDecompress(&strm)) == BZ_OK || onemore--);
- if(e != BZ_STREAM_END) {
- fprint(2, "bunzip2: decompress failed\n");
- return 0;
- }
- if(BZ2_bzDecompressEnd(&strm) != BZ_OK) {
- fprint(2, "bunzip2: decompress end failed (can't happen)\n");
- return 0;
- }
- Bterm(&bout);
- return 1;
- }
|