Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include "bzlib.h"
5
 
6
static	int	bzipf(char*, int);
7
static	int	bzip(char*, long, int, Biobuf*);
8
 
9
static	Biobuf	bout;
10
static	int	level;
11
static	int	debug;
12
static	int	verbose;
13
 
14
 
15
static void
16
usage(void)
17
{
18
	fprint(2, "usage: bzip2 [-vcD] [-1-9] [file ...]\n");
19
	exits("usage");
20
}
21
 
22
void
23
main(int argc, char **argv)
24
{
25
	int i, ok, stdout;
26
 
27
	level = 6;
28
	stdout = 0;
29
	ARGBEGIN{
30
	case 'D':
31
		debug++;
32
		break;
33
	case 'v':
34
		verbose++;
35
		break;
36
	case 'c':
37
		stdout++;
38
		break;
39
	case '1': case '2': case '3': case '4':
40
	case '5': case '6': case '7': case '8': case '9':
41
		level = ARGC() - '0';
42
		break;
43
	default:
44
		usage();
45
		break;
46
	}ARGEND
47
 
48
	if(argc == 0){
49
		Binit(&bout, 1, OWRITE);
50
		ok = bzip(nil, time(0), 0, &bout);
51
		Bterm(&bout);
52
	}else{
53
		ok = 1;
54
		for(i = 0; i < argc; i++)
55
			ok &= bzipf(argv[i], stdout);
56
	}
57
	exits(ok ? nil: "errors");
58
}
59
 
60
static int
61
bzipf(char *file, int stdout)
62
{
63
	Dir *dir;
64
	char ofile[128], *f, *s;
65
	int ifd, ofd, ok;
66
 
67
	ifd = open(file, OREAD);
68
	if(ifd < 0){
69
		fprint(2, "bzip2: can't open %s: %r\n", file);
70
		return 0;
71
	}
72
	dir = dirfstat(ifd);
73
	if(dir == nil){
74
		fprint(2, "bzip2: can't stat %s: %r\n", file);
75
		close(ifd);
76
		return 0;
77
	}
78
	if(dir->mode & DMDIR){
79
		fprint(2, "bzip2: can't compress a directory\n");
80
		close(ifd);
81
		free(dir);
82
		return 0;
83
	}
84
 
85
	if(stdout){
86
		ofd = 1;
87
		strcpy(ofile, "<stdout>");
88
	}else{
89
		f = strrchr(file, '/');
90
		if(f != nil)
91
			f++;
92
		else
93
			f = file;
94
		s = strrchr(f, '.');
95
		if(s != nil && s != ofile && strcmp(s, ".tar") == 0){
96
			*s = '\0';
97
			snprint(ofile, sizeof(ofile), "%s.tbz", f);
98
		}else
99
			snprint(ofile, sizeof(ofile), "%s.bz2", f);
100
		ofd = create(ofile, OWRITE, 0666);
101
		if(ofd < 0){
102
			fprint(2, "bzip2: can't open %s: %r\n", ofile);
103
			free(dir);
104
			close(ifd);
105
			return 0;
106
		}
107
	}
108
 
109
	if(verbose)
110
		fprint(2, "compressing %s to %s\n", file, ofile);
111
 
112
	Binit(&bout, ofd, OWRITE);
113
	ok = bzip(file, dir->mtime, ifd, &bout);
114
	if(!ok || Bflush(&bout) < 0){
115
		fprint(2, "bzip2: error writing %s: %r\n", ofile);
116
		if(!stdout)
117
			remove(ofile);
118
	}
119
	Bterm(&bout);
120
	free(dir);
121
	close(ifd);
122
	close(ofd);
123
	return ok;
124
}
125
 
126
static int
127
bzip(char *file, long mtime, int ifd, Biobuf *bout)
128
{
129
	int e, n, done, onemore;
130
	char buf[8192];
131
	char obuf[8192];
132
	Biobuf bin;
133
	bz_stream strm;
134
 
135
	USED(file);
136
	USED(mtime);
137
 
138
	memset(&strm, 0, sizeof strm);
139
	BZ2_bzCompressInit(&strm, level, verbose, 0);
140
 
141
	strm.next_in = buf;
142
	strm.avail_in = 0;
143
	strm.next_out = obuf;
144
	strm.avail_out = sizeof obuf;
145
 
146
	done = 0;
147
	Binit(&bin, ifd, OREAD);
148
 
149
	/*
150
	 * onemore is a crummy hack to go 'round the loop
151
	 * once after we finish, to flush the output buffer.
152
	 */
153
	onemore = 1;
154
	SET(e);
155
	do {
156
		if(!done && strm.avail_in < sizeof buf) {
157
			if(strm.avail_in)
158
				memmove(buf, strm.next_in, strm.avail_in);
159
 
160
			n = Bread(&bin, buf+strm.avail_in, sizeof(buf)-strm.avail_in);
161
			if(n <= 0)
162
				done = 1;
163
			else
164
				strm.avail_in += n;
165
			strm.next_in = buf;
166
		}
167
		if(strm.avail_out < sizeof obuf) {
168
			Bwrite(bout, obuf, sizeof(obuf)-strm.avail_out);
169
			strm.next_out = obuf;
170
			strm.avail_out = sizeof obuf;
171
		}
172
 
173
		if(onemore == 0)
174
			break;
175
	} while((e=BZ2_bzCompress(&strm, done ? BZ_FINISH : BZ_RUN)) == BZ_RUN_OK || e == BZ_FINISH_OK || onemore--);
176
 
177
	if(e != BZ_STREAM_END) {
178
		fprint(2, "bzip2: compress failed\n");
179
		return 0;
180
	}
181
 
182
	if(BZ2_bzCompressEnd(&strm) != BZ_OK) {
183
		fprint(2, "bzip2: compress end failed (can't happen)\n");
184
		return 0;
185
	}
186
 
187
	Bterm(&bin);
188
 
189
	return 1;
190
}