1 /* lib/font/fontfile/gunzip.c
2 written by Mark Eichin <eichin@kitten.gen.ma.us> September 1996.
3 intended for inclusion in X11 public releases. */
8 #include <X11/fonts/fontmisc.h>
9 #include <X11/fonts/bufio.h>
12 typedef struct _xzip_buf {
15 BufChar b[BUFFILESIZE];
16 BufChar b_in[BUFFILESIZE];
20 static int BufZipFileClose ( BufFilePtr f, int flag );
21 static int BufZipFileFill ( BufFilePtr f );
22 static int BufZipFileSkip ( BufFilePtr f, int c );
23 static int BufCheckZipHeader ( BufFilePtr f );
26 BufFilePushZIP (BufFilePtr f)
30 x = malloc (sizeof (xzip_buf));
32 /* these are just for raw calloc/free */
38 /* force inflateInit to allocate it's own history buffer */
39 x->z.next_in = Z_NULL;
40 x->z.next_out = Z_NULL;
41 x->z.avail_in = x->z.avail_out = 0;
43 /* using negative windowBits sets "nowrap" mode, which turns off
44 zlib header checking [undocumented, for gzip compatibility only?] */
45 x->zstat = inflateInit2(&(x->z), -MAX_WBITS);
46 if (x->zstat != Z_OK) {
51 /* now that the history buffer is allocated, we provide the data buffer */
53 x->z.avail_out = BUFFILESIZE;
54 x->z.next_out = x->b_in;
57 if (BufCheckZipHeader(x->f)) {
62 return BufFileCreate((char *)x,
70 BufZipFileClose(BufFilePtr f, int flag)
72 xzip_buf *x = (xzip_buf *)f->private;
74 BufFileClose (x->f, flag);
79 /* here's the real work.
80 -- we need to put stuff in f.buffer, update f.left and f.bufp,
81 then return the first byte (or BUFFILEEOF).
82 -- to do this, we need to get stuff into avail_in, and next_in,
83 and call inflate appropriately.
84 -- we may also need to add CRC maintenance - if inflate tells us
85 Z_STREAM_END, we then have 4bytes CRC and 4bytes length...
86 gzio.c:gzread shows most of the mechanism.
89 BufZipFileFill (BufFilePtr f)
91 xzip_buf *x = (xzip_buf *)f->private;
93 /* we only get called when left == 0... */
94 /* but just in case, deal */
99 /* did we run out last time? */
111 /* now we work to consume what we can */
112 /* let zlib know what we can handle */
113 x->z.next_out = x->b;
114 x->z.avail_out = BUFFILESIZE;
116 /* and try to consume all of it */
117 while (x->z.avail_out > 0) {
118 /* if we don't have anything to work from... */
119 if (x->z.avail_in == 0) {
120 /* ... fill the z buf from underlying file */
122 for (i = 0; i < sizeof(x->b_in); i++) {
123 c = BufFileGet(x->f);
124 if (c == BUFFILEEOF) break;
128 x->z.next_in = x->b_in;
130 /* so now we have some output space and some input data */
131 x->zstat = inflate(&(x->z), Z_NO_FLUSH);
132 /* the inflation output happens in the f buffer directly... */
133 if (x->zstat == Z_STREAM_END) {
134 /* deal with EOF, crc */
137 if (x->zstat != Z_OK) {
142 f->left = BUFFILESIZE - x->z.avail_out;
152 /* there should be a BufCommonSkip... */
154 BufZipFileSkip (BufFilePtr f, int c)
156 /* BufFileRawSkip returns the count unchanged.
157 BufCompressedSkip returns 0.
158 That means it probably never gets called... */
161 int get = BufFileGet(f);
162 if (get == BUFFILEEOF) return get;
167 /* now we need to duplicate check_header */
169 0x1f, 0x8b -- magic number
170 1 byte -- method (Z_DEFLATED)
171 1 byte -- flags (mask with RESERVED -> fail)
172 4 byte -- time (discard)
173 1 byte -- xflags (discard)
174 1 byte -- "os" code (discard)
175 [if flags & EXTRA_FIELD:
176 2 bytes -- LSBfirst length n
177 n bytes -- extra data (discard)]
178 [if flags & ORIG_NAME:
179 n bytes -- null terminated name (discard)]
181 n bytes -- null terminated comment (discard)]
182 [if flags & HEAD_CRC:
183 2 bytes -- crc of headers? (discard)]
186 /* gzip flag byte -- from gzio.c */
187 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
188 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
189 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
190 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
191 #define COMMENT 0x10 /* bit 4 set: file comment present */
192 #define RESERVED 0xE0 /* bits 5..7: reserved */
194 #define GET(f) do {c = BufFileGet(f); if (c == BUFFILEEOF) return c;} while(0)
196 BufCheckZipHeader(BufFilePtr f)
199 GET(f); if (c != 0x1f) return 1; /* magic 1 */
200 GET(f); if (c != 0x8b) return 2; /* magic 2 */
201 GET(f); if (c != Z_DEFLATED) return 3; /* method */
202 GET(f); if (c & RESERVED) return 4; /* reserved flags */
204 GET(f); GET(f); GET(f); GET(f); /* time */
206 GET(f); /* os code */
207 if (flags & EXTRA_FIELD) {
210 GET(f); len += (c<<8);
215 if (flags & ORIG_NAME) {
216 do { GET(f); } while (c != 0);
218 if (flags & COMMENT) {
219 do { GET(f); } while (c != 0);
221 if (flags & HEAD_CRC) {
222 GET(f); GET(f); /* header crc */