mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-27 11:52:03 +00:00
186 lines
3.4 KiB
C
186 lines
3.4 KiB
C
#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;
|
|
}
|