1 /* $XConsortium: gunzip.c /main/1 1996/11/03 19:33:23 kaleb $ */
2 /* lib/font/fontfile/gunzip.c
3 written by Mark Eichin <eichin@kitten.gen.ma.us> September 1996.
4 intended for inclusion in X11 public releases. */
10 typedef struct _xzip_buf {
13 BufChar b[BUFFILESIZE];
14 BufChar b_in[BUFFILESIZE];
18 static int BufZipFileSkip(); /* f, count */
19 static int BufZipFileFill(); /* read: f; write: char, f */
20 static int BufZipFileClose(); /* f, flag */
21 static int BufCheckZipHeader(); /* f */
29 x = (xzip_buf *) xalloc (sizeof (xzip_buf));
31 /* these are just for raw calloc/free */
37 /* force inflateInit to allocate it's own history buffer */
38 x->z.next_in = Z_NULL;
39 x->z.next_out = Z_NULL;
40 x->z.avail_in = x->z.avail_out = 0;
42 /* using negative windowBits sets "nowrap" mode, which turns off
43 zlib header checking [undocumented, for gzip compatibility only?] */
44 x->zstat = inflateInit2(&(x->z), -MAX_WBITS);
45 if (x->zstat != Z_OK) {
50 /* now that the history buffer is allocated, we provide the data buffer */
52 x->z.avail_out = BUFFILESIZE;
53 x->z.next_out = x->b_in;
56 if (BufCheckZipHeader(x->f)) {
61 return BufFileCreate(x,
67 static int BufZipFileClose(f, flag)
71 xzip_buf *x = (xzip_buf *)f->private;
73 BufFileClose (x->f, flag);
78 /* here's the real work.
79 -- we need to put stuff in f.buffer, update f.left and f.bufp,
80 then return the first byte (or BUFFILEEOF).
81 -- to do this, we need to get stuff into avail_in, and next_in,
82 and call inflate appropriately.
83 -- we may also need to add CRC maintenance - if inflate tells us
84 Z_STREAM_END, we then have 4bytes CRC and 4bytes length...
85 gzio.c:gzread shows most of the mechanism.
87 static int BufZipFileFill (f)
90 xzip_buf *x = (xzip_buf *)f->private;
92 /* we only get called when left == 0... */
93 /* but just in case, deal */
98 /* did we run out last time? */
109 /* now we work to consume what we can */
110 /* let zlib know what we can handle */
111 x->z.next_out = x->b;
112 x->z.avail_out = BUFFILESIZE;
114 /* and try to consume all of it */
115 while (x->z.avail_out > 0) {
116 /* if we don't have anything to work from... */
117 if (x->z.avail_in == 0) {
118 /* ... fill the z buf from underlying file */
120 for (i = 0; i < sizeof(x->b_in); i++) {
121 c = BufFileGet(x->f);
122 if (c == BUFFILEEOF) break;
126 x->z.next_in = x->b_in;
128 /* so now we have some output space and some input data */
129 x->zstat = inflate(&(x->z), Z_NO_FLUSH);
130 /* the inflation output happens in the f buffer directly... */
131 if (x->zstat == Z_STREAM_END) {
132 /* deal with EOF, crc */
135 if (x->zstat != Z_OK) {
140 f->left = BUFFILESIZE - x->z.avail_out;
150 /* there should be a BufCommonSkip... */
151 static int BufZipFileSkip (f, c)
155 /* BufFileRawSkip returns the count unchanged.
156 BufCompressedSkip returns 0.
157 That means it probably never gets called... */
160 int get = BufFileGet(f);
161 if (get == BUFFILEEOF) return get;
166 /* now we need to duplicate check_header */
168 0x1f, 0x8b -- magic number
169 1 byte -- method (Z_DEFLATED)
170 1 byte -- flags (mask with RESERVED -> fail)
171 4 byte -- time (discard)
172 1 byte -- xflags (discard)
173 1 byte -- "os" code (discard)
174 [if flags & EXTRA_FIELD:
175 2 bytes -- LSBfirst length n
176 n bytes -- extra data (discard)]
177 [if flags & ORIG_NAME:
178 n bytes -- null terminated name (discard)]
180 n bytes -- null terminated comment (discard)]
181 [if flags & HEAD_CRC:
182 2 bytes -- crc of headers? (discard)]
185 /* gzip flag byte -- from gzio.c */
186 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
187 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
188 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
189 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
190 #define COMMENT 0x10 /* bit 4 set: file comment present */
191 #define RESERVED 0xE0 /* bits 5..7: reserved */
193 #define GET(f) do {c = BufFileGet(f); if (c == BUFFILEEOF) return c;} while(0)
194 static int BufCheckZipHeader(f)
198 GET(f); if (c != 0x1f) return 1; /* magic 1 */
199 GET(f); if (c != 0x8b) return 2; /* magic 2 */
200 GET(f); if (c != Z_DEFLATED) return 3; /* method */
201 GET(f); if (c & RESERVED) return 4; /* reserved flags */
203 GET(f); GET(f); GET(f); GET(f); /* time */
205 GET(f); /* os code */
206 if (flags & EXTRA_FIELD) {
209 GET(f); len += (c<<8);
214 if (flags & ORIG_NAME) {
215 do { GET(f); } while (c != 0);
217 if (flags & COMMENT) {
218 do { GET(f); } while (c != 0);
220 if (flags & HEAD_CRC) {
221 GET(f); GET(f); /* header crc */