/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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); voidusage(void){ fprint(2, "usage: bunzip2 [-cvD] [file ...]\n"); exits("usage");} voidmain(int argc, char **argv){ int i, ok, stdout; stdout = 0; ARGBEGIN{ case 'D': debug++; break; case 'c': stdout++; break; case 'v': verbose++; break; default: usage(); }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 intbunzipf(char *file, int stdout){ char ofile[64], *s; int ofd, ifd, ok; infile = file; ifd = open(file, OREAD); if(ifd < 0){ fprint(2, "bunzip2: 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 intbunzip(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;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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;
default:
usage();
}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, "bunzip2: 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;
}