1 ff3adf60 2004-04-14 devnull #include <u.h>
2 ff3adf60 2004-04-14 devnull #include <libc.h>
3 ff3adf60 2004-04-14 devnull #include <bio.h>
4 ff3adf60 2004-04-14 devnull #include "bzlib.h"
6 ff3adf60 2004-04-14 devnull static Biobuf bin;
7 ff3adf60 2004-04-14 devnull static int debug;
8 ff3adf60 2004-04-14 devnull static int verbose;
9 ff3adf60 2004-04-14 devnull static char *delfile;
10 ff3adf60 2004-04-14 devnull static char *infile;
11 ff3adf60 2004-04-14 devnull static int bunzipf(char *file, int stdout);
12 ff3adf60 2004-04-14 devnull static int bunzip(int ofd, char *ofile, Biobuf *bin);
15 ff3adf60 2004-04-14 devnull usage(void)
17 ff3adf60 2004-04-14 devnull fprint(2, "usage: bunzip2 [-cvD] [file ...]\n");
18 ff3adf60 2004-04-14 devnull exits("usage");
22 ff3adf60 2004-04-14 devnull main(int argc, char **argv)
24 ff3adf60 2004-04-14 devnull int i, ok, stdout;
26 ff3adf60 2004-04-14 devnull stdout = 0;
27 ff3adf60 2004-04-14 devnull ARGBEGIN{
28 ff3adf60 2004-04-14 devnull case 'D':
31 ff3adf60 2004-04-14 devnull case 'c':
32 ff3adf60 2004-04-14 devnull stdout++;
34 ff3adf60 2004-04-14 devnull case 'v':
35 ff3adf60 2004-04-14 devnull verbose++;
39 ff3adf60 2004-04-14 devnull if(argc == 0){
40 ff3adf60 2004-04-14 devnull Binit(&bin, 0, OREAD);
41 ff3adf60 2004-04-14 devnull infile = "<stdin>";
42 ff3adf60 2004-04-14 devnull ok = bunzip(1, "<stdout>", &bin);
45 ff3adf60 2004-04-14 devnull for(i = 0; i < argc; i++)
46 ff3adf60 2004-04-14 devnull ok &= bunzipf(argv[i], stdout);
49 ff3adf60 2004-04-14 devnull exits(ok ? nil: "errors");
52 ff3adf60 2004-04-14 devnull static int
53 ff3adf60 2004-04-14 devnull bunzipf(char *file, int stdout)
55 ff3adf60 2004-04-14 devnull char ofile[64], *s;
56 ff3adf60 2004-04-14 devnull int ofd, ifd, ok;
58 ff3adf60 2004-04-14 devnull infile = file;
59 ff3adf60 2004-04-14 devnull ifd = open(file, OREAD);
60 ff3adf60 2004-04-14 devnull if(ifd < 0){
61 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: can't open %s: %r\n", file);
62 ff3adf60 2004-04-14 devnull return 0;
65 ff3adf60 2004-04-14 devnull Binit(&bin, ifd, OREAD);
66 ff3adf60 2004-04-14 devnull if(Bgetc(&bin) != 'B' || Bgetc(&bin) != 'Z' || Bgetc(&bin) != 'h'){
67 ff3adf60 2004-04-14 devnull fprint(2, "bunzip2: %s is not a bzip2 file\n", file);
68 ff3adf60 2004-04-14 devnull Bterm(&bin);
69 ff3adf60 2004-04-14 devnull close(ifd);
70 ff3adf60 2004-04-14 devnull return 0;
72 ff3adf60 2004-04-14 devnull Bungetc(&bin);
73 ff3adf60 2004-04-14 devnull Bungetc(&bin);
74 ff3adf60 2004-04-14 devnull Bungetc(&bin);
76 ff3adf60 2004-04-14 devnull if(stdout){
78 ff3adf60 2004-04-14 devnull strcpy(ofile, "<stdout>");
80 ff3adf60 2004-04-14 devnull s = strrchr(file, '/');
81 ff3adf60 2004-04-14 devnull if(s != nil)
84 ff3adf60 2004-04-14 devnull s = file;
85 ff3adf60 2004-04-14 devnull strecpy(ofile, ofile+sizeof ofile, s);
86 ff3adf60 2004-04-14 devnull s = strrchr(ofile, '.');
87 ff3adf60 2004-04-14 devnull if(s != nil && s != ofile && strcmp(s, ".bz2") == 0)
88 ff3adf60 2004-04-14 devnull *s = '\0';
89 ff3adf60 2004-04-14 devnull else if(s != nil && (strcmp(s, ".tbz") == 0 || strcmp(s, ".tbz2") == 0))
90 ff3adf60 2004-04-14 devnull strcpy(s, ".tar");
91 ff3adf60 2004-04-14 devnull else if(strcmp(file, ofile) == 0){
92 ff3adf60 2004-04-14 devnull fprint(2, "bunzip2: can't overwrite %s\n", file);
93 ff3adf60 2004-04-14 devnull Bterm(&bin);
94 ff3adf60 2004-04-14 devnull close(ifd);
95 ff3adf60 2004-04-14 devnull return 0;
98 ff3adf60 2004-04-14 devnull ofd = create(ofile, OWRITE, 0666);
99 ff3adf60 2004-04-14 devnull if(ofd < 0){
100 ff3adf60 2004-04-14 devnull fprint(2, "bunzip2: can't create %s: %r\n", ofile);
101 ff3adf60 2004-04-14 devnull Bterm(&bin);
102 ff3adf60 2004-04-14 devnull close(ifd);
103 ff3adf60 2004-04-14 devnull return 0;
105 ff3adf60 2004-04-14 devnull delfile = ofile;
108 ff3adf60 2004-04-14 devnull ok = bunzip(ofd, ofile, &bin);
109 ff3adf60 2004-04-14 devnull Bterm(&bin);
110 ff3adf60 2004-04-14 devnull close(ifd);
111 ff3adf60 2004-04-14 devnull if(!ok){
112 ff3adf60 2004-04-14 devnull fprint(2, "bunzip2: can't write %s: %r\n", ofile);
113 ff3adf60 2004-04-14 devnull if(delfile)
114 ff3adf60 2004-04-14 devnull remove(delfile);
116 ff3adf60 2004-04-14 devnull delfile = nil;
117 ff3adf60 2004-04-14 devnull if(!stdout && ofd >= 0)
118 ff3adf60 2004-04-14 devnull close(ofd);
119 ff3adf60 2004-04-14 devnull return ok;
122 ff3adf60 2004-04-14 devnull static int
123 ff3adf60 2004-04-14 devnull bunzip(int ofd, char *ofile, Biobuf *bin)
125 ff3adf60 2004-04-14 devnull int e, n, done, onemore;
126 ff3adf60 2004-04-14 devnull char buf[8192];
127 ff3adf60 2004-04-14 devnull char obuf[8192];
128 ff3adf60 2004-04-14 devnull Biobuf bout;
129 ff3adf60 2004-04-14 devnull bz_stream strm;
131 ff3adf60 2004-04-14 devnull USED(ofile);
133 ff3adf60 2004-04-14 devnull memset(&strm, 0, sizeof strm);
134 ff3adf60 2004-04-14 devnull BZ2_bzDecompressInit(&strm, verbose, 0);
136 ff3adf60 2004-04-14 devnull strm.next_in = buf;
137 ff3adf60 2004-04-14 devnull strm.avail_in = 0;
138 ff3adf60 2004-04-14 devnull strm.next_out = obuf;
139 ff3adf60 2004-04-14 devnull strm.avail_out = sizeof obuf;
141 ff3adf60 2004-04-14 devnull done = 0;
142 ff3adf60 2004-04-14 devnull Binit(&bout, ofd, OWRITE);
145 ff3adf60 2004-04-14 devnull * onemore is a crummy hack to go 'round the loop
146 ff3adf60 2004-04-14 devnull * once after we finish, to flush the output buffer.
148 ff3adf60 2004-04-14 devnull onemore = 1;
151 ff3adf60 2004-04-14 devnull if(!done && strm.avail_in < sizeof buf) {
152 ff3adf60 2004-04-14 devnull if(strm.avail_in)
153 ff3adf60 2004-04-14 devnull memmove(buf, strm.next_in, strm.avail_in);
155 ff3adf60 2004-04-14 devnull n = Bread(bin, buf+strm.avail_in, sizeof(buf)-strm.avail_in);
156 ff3adf60 2004-04-14 devnull if(n <= 0)
157 ff3adf60 2004-04-14 devnull done = 1;
159 ff3adf60 2004-04-14 devnull strm.avail_in += n;
160 ff3adf60 2004-04-14 devnull strm.next_in = buf;
162 ff3adf60 2004-04-14 devnull if(strm.avail_out < sizeof obuf) {
163 ff3adf60 2004-04-14 devnull Bwrite(&bout, obuf, sizeof(obuf)-strm.avail_out);
164 ff3adf60 2004-04-14 devnull strm.next_out = obuf;
165 ff3adf60 2004-04-14 devnull strm.avail_out = sizeof obuf;
167 ff3adf60 2004-04-14 devnull if(onemore == 0)
169 ff3adf60 2004-04-14 devnull if(strm.avail_in == 0 && strm.avail_out == sizeof obuf)
171 ff3adf60 2004-04-14 devnull } while((e=BZ2_bzDecompress(&strm)) == BZ_OK || onemore--);
173 ff3adf60 2004-04-14 devnull if(e != BZ_STREAM_END) {
174 ff3adf60 2004-04-14 devnull fprint(2, "bunzip2: decompress failed\n");
175 ff3adf60 2004-04-14 devnull return 0;
178 ff3adf60 2004-04-14 devnull if(BZ2_bzDecompressEnd(&strm) != BZ_OK) {
179 ff3adf60 2004-04-14 devnull fprint(2, "bunzip2: decompress end failed (can't happen)\n");
180 ff3adf60 2004-04-14 devnull return 0;
183 ff3adf60 2004-04-14 devnull Bterm(&bout);
185 ff3adf60 2004-04-14 devnull return 1;