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 <flate.h>
5
#include "gzip.h"
6
 
7
static	int	gzipf(char*, int);
8
static	int	gzip(char*, long, int, Biobuf*);
9
static	int	crcread(void *fd, void *buf, int n);
10
static	int	gzwrite(void *bout, void *buf, int n);
11
 
12
static	Biobuf	bout;
13
static	ulong	crc;
14
static	ulong	*crctab;
15
static	int	debug;
16
static	int	eof;
17
static	int	level;
18
static	ulong	totr;
19
static	int	verbose;
20
 
21
void
22
usage(void)
23
{
24
	fprint(2, "usage: gzip [-vcD] [-1-9] [file ...]\n");
25
	exits("usage");
26
}
27
 
28
void
29
main(int argc, char *argv[])
30
{
31
	int i, ok, stdout;
32
 
33
	level = 6;
34
	stdout = 0;
35
	ARGBEGIN{
36
	case 'D':
37
		debug++;
38
		break;
39
	case 'v':
40
		verbose++;
41
		break;
42
	case 'c':
43
		stdout = 1;
44
		break;
45
	case '1': case '2': case '3': case '4':
46
	case '5': case '6': case '7': case '8': case '9':
47
		level = ARGC() - '0';
48
		break;
49
	default:
50
		usage();
51
		break;
52
	}ARGEND
53
 
54
	crctab = mkcrctab(GZCRCPOLY);
55
	ok = deflateinit();
56
	if(ok != FlateOk)
57
		sysfatal("deflateinit failed: %s", flateerr(ok));
58
 
59
	if(argc == 0){
60
		Binit(&bout, 1, OWRITE);
61
		ok = gzip(nil, time(0), 0, &bout);
62
		Bterm(&bout);
63
	}else{
64
		ok = 1;
65
		for(i = 0; i < argc; i++)
66
			ok &= gzipf(argv[i], stdout);
67
	}
68
	exits(ok ? nil: "errors");
69
}
70
 
71
static int
72
gzipf(char *file, int stdout)
73
{
74
	Dir *dir;
75
	char ofile[256], *f, *s;
76
	int ifd, ofd, ok;
77
 
78
	ifd = open(file, OREAD);
79
	if(ifd < 0){
80
		fprint(2, "gzip: can't open %s: %r\n", file);
81
		return 0;
82
	}
83
	dir = dirfstat(ifd);
84
	if(dir == nil){
85
		fprint(2, "gzip: can't stat %s: %r\n", file);
86
		close(ifd);
87
		return 0;
88
	}
89
	if(dir->mode & DMDIR){
90
		fprint(2, "gzip: can't compress a directory\n");
91
		close(ifd);
92
		free(dir);
93
		return 0;
94
	}
95
 
96
	if(stdout){
97
		ofd = 1;
98
		strcpy(ofile, "<stdout>");
99
	}else{
100
		f = strrchr(file, '/');
101
		if(f != nil)
102
			f++;
103
		else
104
			f = file;
105
		s = strrchr(f, '.');
106
		if(s != nil && s != ofile && strcmp(s, ".tar") == 0){
107
			*s = '\0';
108
			snprint(ofile, sizeof(ofile), "%s.tgz", f);
109
		}else
110
			snprint(ofile, sizeof(ofile), "%s.gz", f);
111
		ofd = create(ofile, OWRITE, 0666);
112
		if(ofd < 0){
113
			fprint(2, "gzip: can't open %s: %r\n", ofile);
114
			close(ifd);
115
			return 0;
116
		}
117
	}
118
 
119
	if(verbose)
120
		fprint(2, "compressing %s to %s\n", file, ofile);
121
 
122
	Binit(&bout, ofd, OWRITE);
123
	ok = gzip(file, dir->mtime, ifd, &bout);
124
	if(!ok || Bflush(&bout) < 0){
125
		fprint(2, "gzip: error writing %s: %r\n", ofile);
126
		if(!stdout)
127
			remove(ofile);
128
	}
129
	Bterm(&bout);
130
	free(dir);
131
	close(ifd);
132
	close(ofd);
133
	return ok;
134
}
135
 
136
static int
137
gzip(char *file, long mtime, int ifd, Biobuf *bout)
138
{
139
	int flags, err;
140
 
141
	flags = 0;
142
	Bputc(bout, GZMAGIC1);
143
	Bputc(bout, GZMAGIC2);
144
	Bputc(bout, GZDEFLATE);
145
 
146
	if(file != nil)
147
		flags |= GZFNAME;
148
	Bputc(bout, flags);
149
 
150
	Bputc(bout, mtime);
151
	Bputc(bout, mtime>>8);
152
	Bputc(bout, mtime>>16);
153
	Bputc(bout, mtime>>24);
154
 
155
	Bputc(bout, 0);
156
	Bputc(bout, GZOSINFERNO);
157
 
158
	if(flags & GZFNAME)
159
		Bwrite(bout, file, strlen(file)+1);
160
 
161
	crc = 0;
162
	eof = 0;
163
	totr = 0;
164
	err = deflate(bout, gzwrite, (void*)ifd, crcread, level, debug);
165
	if(err != FlateOk){
166
		fprint(2, "gzip: deflate failed: %s\n", flateerr(err));
167
		return 0;
168
	}
169
 
170
	Bputc(bout, crc);
171
	Bputc(bout, crc>>8);
172
	Bputc(bout, crc>>16);
173
	Bputc(bout, crc>>24);
174
 
175
	Bputc(bout, totr);
176
	Bputc(bout, totr>>8);
177
	Bputc(bout, totr>>16);
178
	Bputc(bout, totr>>24);
179
 
180
	return 1;
181
}
182
 
183
static int
184
crcread(void *fd, void *buf, int n)
185
{
186
	int nr, m;
187
 
188
	nr = 0;
189
	for(; !eof && n > 0; n -= m){
190
		m = read((int)(uintptr)fd, (char*)buf+nr, n);
191
		if(m <= 0){
192
			eof = 1;
193
			if(m < 0)
194
				return -1;
195
			break;
196
		}
197
		nr += m;
198
	}
199
	crc = blockcrc(crctab, crc, buf, nr);
200
	totr += nr;
201
	return nr;
202
}
203
 
204
static int
205
gzwrite(void *bout, void *buf, int n)
206
{
207
	if(n != Bwrite(bout, buf, n)){
208
		eof = 1;
209
		return -1;
210
	}
211
	return n;
212
}