~ubuntu-branches/ubuntu/karmic/fltk1.1/karmic

« back to all changes in this revision

Viewing changes to zlib/gzio.c

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2005-05-22 13:57:06 UTC
  • mfrom: (2.1.1 hoary)
  • Revision ID: james.westby@ubuntu.com-20050522135706-mchag24yf42lu7bu
Tags: 1.1.6-5
* Revert previous change, which seems to have been ineffective for some
  reason, in favor of commenting out the problematic Makefile rule
  altogether.  (Closes: #310151.)
* debian/control: Go back to specifying the URL as part of the
  description rather than via a non-standard field that doesn't seem to
  have caught on.  (Closes: #310240.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gzio.c -- IO on .gz files
 
2
 * Copyright (C) 1995-2003 Jean-loup Gailly.
 
3
 * For conditions of distribution and use, see copyright notice in zlib.h
 
4
 *
 
5
 * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
 
6
 */
 
7
 
 
8
/* @(#) $Id: gzio.c,v 1.1.2.2 2004/09/08 16:04:43 easysw Exp $ */
 
9
 
 
10
#include <stdio.h>
 
11
 
 
12
#include "zutil.h"
 
13
 
 
14
#ifdef NO_DEFLATE       /* for compatiblity with old definition */
 
15
#  define NO_GZCOMPRESS
 
16
#endif
 
17
 
 
18
#ifndef NO_DUMMY_DECL
 
19
struct internal_state {int dummy;}; /* for buggy compilers */
 
20
#endif
 
21
 
 
22
#ifndef Z_BUFSIZE
 
23
#  ifdef MAXSEG_64K
 
24
#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
 
25
#  else
 
26
#    define Z_BUFSIZE 16384
 
27
#  endif
 
28
#endif
 
29
#ifndef Z_PRINTF_BUFSIZE
 
30
#  define Z_PRINTF_BUFSIZE 4096
 
31
#endif
 
32
 
 
33
#ifdef __MVS__
 
34
#  pragma map (fdopen , "\174\174FDOPEN")
 
35
   FILE *fdopen(int, const char *);
 
36
#endif
 
37
 
 
38
#ifndef STDC
 
39
extern voidp  malloc OF((uInt size));
 
40
extern void   free   OF((voidpf ptr));
 
41
#endif
 
42
 
 
43
#define ALLOC(size) malloc(size)
 
44
#define TRYFREE(p) {if (p) free(p);}
 
45
 
 
46
static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
 
47
 
 
48
/* gzip flag byte */
 
49
#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
 
50
#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
 
51
#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
 
52
#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
 
53
#define COMMENT      0x10 /* bit 4 set: file comment present */
 
54
#define RESERVED     0xE0 /* bits 5..7: reserved */
 
55
 
 
56
typedef struct gz_stream {
 
57
    z_stream stream;
 
58
    int      z_err;   /* error code for last stream operation */
 
59
    int      z_eof;   /* set if end of input file */
 
60
    FILE     *file;   /* .gz file */
 
61
    Byte     *inbuf;  /* input buffer */
 
62
    Byte     *outbuf; /* output buffer */
 
63
    uLong    crc;     /* crc32 of uncompressed data */
 
64
    char     *msg;    /* error message */
 
65
    char     *path;   /* path name for debugging only */
 
66
    int      transparent; /* 1 if input file is not a .gz file */
 
67
    char     mode;    /* 'w' or 'r' */
 
68
    z_off_t  start;   /* start of compressed data in file (header skipped) */
 
69
    z_off_t  in;      /* bytes into deflate or inflate */
 
70
    z_off_t  out;     /* bytes out of deflate or inflate */
 
71
    int      back;    /* one character push-back */
 
72
    int      last;    /* true if push-back is last character */
 
73
} gz_stream;
 
74
 
 
75
 
 
76
local gzFile gz_open      OF((const char *path, const char *mode, int  fd));
 
77
local int do_flush        OF((gzFile file, int flush));
 
78
local int    get_byte     OF((gz_stream *s));
 
79
local void   check_header OF((gz_stream *s));
 
80
local int    destroy      OF((gz_stream *s));
 
81
local void   putLong      OF((FILE *file, uLong x));
 
82
local uLong  getLong      OF((gz_stream *s));
 
83
 
 
84
/* ===========================================================================
 
85
     Opens a gzip (.gz) file for reading or writing. The mode parameter
 
86
   is as in fopen ("rb" or "wb"). The file is given either by file descriptor
 
87
   or path name (if fd == -1).
 
88
     gz_open returns NULL if the file could not be opened or if there was
 
89
   insufficient memory to allocate the (de)compression state; errno
 
90
   can be checked to distinguish the two cases (if errno is zero, the
 
91
   zlib error is Z_MEM_ERROR).
 
92
*/
 
93
local gzFile gz_open (path, mode, fd)
 
94
    const char *path;
 
95
    const char *mode;
 
96
    int  fd;
 
97
{
 
98
    int err;
 
99
    int level = Z_DEFAULT_COMPRESSION; /* compression level */
 
100
    int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
 
101
    char *p = (char*)mode;
 
102
    gz_stream *s;
 
103
    char fmode[80]; /* copy of mode, without the compression level */
 
104
    char *m = fmode;
 
105
 
 
106
    if (!path || !mode) return Z_NULL;
 
107
 
 
108
    s = (gz_stream *)ALLOC(sizeof(gz_stream));
 
109
    if (!s) return Z_NULL;
 
110
 
 
111
    s->stream.zalloc = (alloc_func)0;
 
112
    s->stream.zfree = (free_func)0;
 
113
    s->stream.opaque = (voidpf)0;
 
114
    s->stream.next_in = s->inbuf = Z_NULL;
 
115
    s->stream.next_out = s->outbuf = Z_NULL;
 
116
    s->stream.avail_in = s->stream.avail_out = 0;
 
117
    s->file = NULL;
 
118
    s->z_err = Z_OK;
 
119
    s->z_eof = 0;
 
120
    s->in = 0;
 
121
    s->out = 0;
 
122
    s->back = EOF;
 
123
    s->crc = crc32(0L, Z_NULL, 0);
 
124
    s->msg = NULL;
 
125
    s->transparent = 0;
 
126
 
 
127
    s->path = (char*)ALLOC(strlen(path)+1);
 
128
    if (s->path == NULL) {
 
129
        return destroy(s), (gzFile)Z_NULL;
 
130
    }
 
131
    strcpy(s->path, path); /* do this early for debugging */
 
132
 
 
133
    s->mode = '\0';
 
134
    do {
 
135
        if (*p == 'r') s->mode = 'r';
 
136
        if (*p == 'w' || *p == 'a') s->mode = 'w';
 
137
        if (*p >= '0' && *p <= '9') {
 
138
            level = *p - '0';
 
139
        } else if (*p == 'f') {
 
140
          strategy = Z_FILTERED;
 
141
        } else if (*p == 'h') {
 
142
          strategy = Z_HUFFMAN_ONLY;
 
143
        } else if (*p == 'R') {
 
144
          strategy = Z_RLE;
 
145
        } else {
 
146
            *m++ = *p; /* copy the mode */
 
147
        }
 
148
    } while (*p++ && m != fmode + sizeof(fmode));
 
149
    if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
 
150
 
 
151
    if (s->mode == 'w') {
 
152
#ifdef NO_GZCOMPRESS
 
153
        err = Z_STREAM_ERROR;
 
154
#else
 
155
        err = deflateInit2(&(s->stream), level,
 
156
                           Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
 
157
        /* windowBits is passed < 0 to suppress zlib header */
 
158
 
 
159
        s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
 
160
#endif
 
161
        if (err != Z_OK || s->outbuf == Z_NULL) {
 
162
            return destroy(s), (gzFile)Z_NULL;
 
163
        }
 
164
    } else {
 
165
        s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
 
166
 
 
167
        err = inflateInit2(&(s->stream), -MAX_WBITS);
 
168
        /* windowBits is passed < 0 to tell that there is no zlib header.
 
169
         * Note that in this case inflate *requires* an extra "dummy" byte
 
170
         * after the compressed stream in order to complete decompression and
 
171
         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
 
172
         * present after the compressed stream.
 
173
         */
 
174
        if (err != Z_OK || s->inbuf == Z_NULL) {
 
175
            return destroy(s), (gzFile)Z_NULL;
 
176
        }
 
177
    }
 
178
    s->stream.avail_out = Z_BUFSIZE;
 
179
 
 
180
    errno = 0;
 
181
    s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
 
182
 
 
183
    if (s->file == NULL) {
 
184
        return destroy(s), (gzFile)Z_NULL;
 
185
    }
 
186
    if (s->mode == 'w') {
 
187
        /* Write a very simple .gz header:
 
188
         */
 
189
        fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
 
190
             Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
 
191
        s->start = 10L;
 
192
        /* We use 10L instead of ftell(s->file) to because ftell causes an
 
193
         * fflush on some systems. This version of the library doesn't use
 
194
         * start anyway in write mode, so this initialization is not
 
195
         * necessary.
 
196
         */
 
197
    } else {
 
198
        check_header(s); /* skip the .gz header */
 
199
        s->start = ftell(s->file) - s->stream.avail_in;
 
200
    }
 
201
 
 
202
    return (gzFile)s;
 
203
}
 
204
 
 
205
/* ===========================================================================
 
206
     Opens a gzip (.gz) file for reading or writing.
 
207
*/
 
208
gzFile ZEXPORT gzopen (path, mode)
 
209
    const char *path;
 
210
    const char *mode;
 
211
{
 
212
    return gz_open (path, mode, -1);
 
213
}
 
214
 
 
215
/* ===========================================================================
 
216
     Associate a gzFile with the file descriptor fd. fd is not dup'ed here
 
217
   to mimic the behavio(u)r of fdopen.
 
218
*/
 
219
gzFile ZEXPORT gzdopen (fd, mode)
 
220
    int fd;
 
221
    const char *mode;
 
222
{
 
223
    char name[20];
 
224
 
 
225
    if (fd < 0) return (gzFile)Z_NULL;
 
226
    sprintf(name, "<fd:%d>", fd); /* for debugging */
 
227
 
 
228
    return gz_open (name, mode, fd);
 
229
}
 
230
 
 
231
/* ===========================================================================
 
232
 * Update the compression level and strategy
 
233
 */
 
234
int ZEXPORT gzsetparams (file, level, strategy)
 
235
    gzFile file;
 
236
    int level;
 
237
    int strategy;
 
238
{
 
239
    gz_stream *s = (gz_stream*)file;
 
240
 
 
241
    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
 
242
 
 
243
    /* Make room to allow flushing */
 
244
    if (s->stream.avail_out == 0) {
 
245
 
 
246
        s->stream.next_out = s->outbuf;
 
247
        if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
 
248
            s->z_err = Z_ERRNO;
 
249
        }
 
250
        s->stream.avail_out = Z_BUFSIZE;
 
251
    }
 
252
 
 
253
    return deflateParams (&(s->stream), level, strategy);
 
254
}
 
255
 
 
256
/* ===========================================================================
 
257
     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
 
258
   for end of file.
 
259
   IN assertion: the stream s has been sucessfully opened for reading.
 
260
*/
 
261
local int get_byte(s)
 
262
    gz_stream *s;
 
263
{
 
264
    if (s->z_eof) return EOF;
 
265
    if (s->stream.avail_in == 0) {
 
266
        errno = 0;
 
267
        s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
 
268
        if (s->stream.avail_in == 0) {
 
269
            s->z_eof = 1;
 
270
            if (ferror(s->file)) s->z_err = Z_ERRNO;
 
271
            return EOF;
 
272
        }
 
273
        s->stream.next_in = s->inbuf;
 
274
    }
 
275
    s->stream.avail_in--;
 
276
    return *(s->stream.next_in)++;
 
277
}
 
278
 
 
279
/* ===========================================================================
 
280
      Check the gzip header of a gz_stream opened for reading. Set the stream
 
281
    mode to transparent if the gzip magic header is not present; set s->err
 
282
    to Z_DATA_ERROR if the magic header is present but the rest of the header
 
283
    is incorrect.
 
284
    IN assertion: the stream s has already been created sucessfully;
 
285
       s->stream.avail_in is zero for the first time, but may be non-zero
 
286
       for concatenated .gz files.
 
287
*/
 
288
local void check_header(s)
 
289
    gz_stream *s;
 
290
{
 
291
    int method; /* method byte */
 
292
    int flags;  /* flags byte */
 
293
    uInt len;
 
294
    int c;
 
295
 
 
296
    /* Assure two bytes in the buffer so we can peek ahead -- handle case
 
297
       where first byte of header is at the end of the buffer after the last
 
298
       gzip segment */
 
299
    len = s->stream.avail_in;
 
300
    if (len < 2) {
 
301
        if (len) s->inbuf[0] = s->stream.next_in[0];
 
302
        errno = 0;
 
303
        len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
 
304
        if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
 
305
        s->stream.avail_in += len;
 
306
        s->stream.next_in = s->inbuf;
 
307
        if (s->stream.avail_in < 2) {
 
308
            s->transparent = s->stream.avail_in;
 
309
            return;
 
310
        }
 
311
    }
 
312
 
 
313
    /* Peek ahead to check the gzip magic header */
 
314
    if (s->stream.next_in[0] != gz_magic[0] ||
 
315
        s->stream.next_in[1] != gz_magic[1]) {
 
316
        s->transparent = 1;
 
317
        return;
 
318
    }
 
319
    s->stream.avail_in -= 2;
 
320
    s->stream.next_in += 2;
 
321
 
 
322
    /* Check the rest of the gzip header */
 
323
    method = get_byte(s);
 
324
    flags = get_byte(s);
 
325
    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
 
326
        s->z_err = Z_DATA_ERROR;
 
327
        return;
 
328
    }
 
329
 
 
330
    /* Discard time, xflags and OS code: */
 
331
    for (len = 0; len < 6; len++) (void)get_byte(s);
 
332
 
 
333
    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
 
334
        len  =  (uInt)get_byte(s);
 
335
        len += ((uInt)get_byte(s))<<8;
 
336
        /* len is garbage if EOF but the loop below will quit anyway */
 
337
        while (len-- != 0 && get_byte(s) != EOF) ;
 
338
    }
 
339
    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
 
340
        while ((c = get_byte(s)) != 0 && c != EOF) ;
 
341
    }
 
342
    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
 
343
        while ((c = get_byte(s)) != 0 && c != EOF) ;
 
344
    }
 
345
    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
 
346
        for (len = 0; len < 2; len++) (void)get_byte(s);
 
347
    }
 
348
    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
 
349
}
 
350
 
 
351
 /* ===========================================================================
 
352
 * Cleanup then free the given gz_stream. Return a zlib error code.
 
353
   Try freeing in the reverse order of allocations.
 
354
 */
 
355
local int destroy (s)
 
356
    gz_stream *s;
 
357
{
 
358
    int err = Z_OK;
 
359
 
 
360
    if (!s) return Z_STREAM_ERROR;
 
361
 
 
362
    TRYFREE(s->msg);
 
363
 
 
364
    if (s->stream.state != NULL) {
 
365
        if (s->mode == 'w') {
 
366
#ifdef NO_GZCOMPRESS
 
367
            err = Z_STREAM_ERROR;
 
368
#else
 
369
            err = deflateEnd(&(s->stream));
 
370
#endif
 
371
        } else if (s->mode == 'r') {
 
372
            err = inflateEnd(&(s->stream));
 
373
        }
 
374
    }
 
375
    if (s->file != NULL && fclose(s->file)) {
 
376
#ifdef ESPIPE
 
377
        if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
 
378
#endif
 
379
            err = Z_ERRNO;
 
380
    }
 
381
    if (s->z_err < 0) err = s->z_err;
 
382
 
 
383
    TRYFREE(s->inbuf);
 
384
    TRYFREE(s->outbuf);
 
385
    TRYFREE(s->path);
 
386
    TRYFREE(s);
 
387
    return err;
 
388
}
 
389
 
 
390
/* ===========================================================================
 
391
     Reads the given number of uncompressed bytes from the compressed file.
 
392
   gzread returns the number of bytes actually read (0 for end of file).
 
393
*/
 
394
int ZEXPORT gzread (file, buf, len)
 
395
    gzFile file;
 
396
    voidp buf;
 
397
    unsigned len;
 
398
{
 
399
    gz_stream *s = (gz_stream*)file;
 
400
    Bytef *start = (Bytef*)buf; /* starting point for crc computation */
 
401
    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
 
402
 
 
403
    if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
 
404
 
 
405
    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
 
406
    if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
 
407
 
 
408
    next_out = (Byte*)buf;
 
409
    s->stream.next_out = (Bytef*)buf;
 
410
    s->stream.avail_out = len;
 
411
 
 
412
    if (s->stream.avail_out && s->back != EOF) {
 
413
        *next_out++ = s->back;
 
414
        s->stream.next_out++;
 
415
        s->stream.avail_out--;
 
416
        s->back = EOF;
 
417
        s->out++;
 
418
        if (s->last) {
 
419
            s->z_err = Z_STREAM_END;
 
420
            return 1;
 
421
        }
 
422
    }
 
423
 
 
424
    while (s->stream.avail_out != 0) {
 
425
 
 
426
        if (s->transparent) {
 
427
            /* Copy first the lookahead bytes: */
 
428
            uInt n = s->stream.avail_in;
 
429
            if (n > s->stream.avail_out) n = s->stream.avail_out;
 
430
            if (n > 0) {
 
431
                zmemcpy(s->stream.next_out, s->stream.next_in, n);
 
432
                next_out += n;
 
433
                s->stream.next_out = next_out;
 
434
                s->stream.next_in   += n;
 
435
                s->stream.avail_out -= n;
 
436
                s->stream.avail_in  -= n;
 
437
            }
 
438
            if (s->stream.avail_out > 0) {
 
439
                s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
 
440
                                             s->file);
 
441
            }
 
442
            len -= s->stream.avail_out;
 
443
            s->in  += len;
 
444
            s->out += len;
 
445
            if (len == 0) s->z_eof = 1;
 
446
            return (int)len;
 
447
        }
 
448
        if (s->stream.avail_in == 0 && !s->z_eof) {
 
449
 
 
450
            errno = 0;
 
451
            s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
 
452
            if (s->stream.avail_in == 0) {
 
453
                s->z_eof = 1;
 
454
                if (ferror(s->file)) {
 
455
                    s->z_err = Z_ERRNO;
 
456
                    break;
 
457
                }
 
458
            }
 
459
            s->stream.next_in = s->inbuf;
 
460
        }
 
461
        s->in += s->stream.avail_in;
 
462
        s->out += s->stream.avail_out;
 
463
        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
 
464
        s->in -= s->stream.avail_in;
 
465
        s->out -= s->stream.avail_out;
 
466
 
 
467
        if (s->z_err == Z_STREAM_END) {
 
468
            /* Check CRC and original size */
 
469
            s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
 
470
            start = s->stream.next_out;
 
471
 
 
472
            if (getLong(s) != s->crc) {
 
473
                s->z_err = Z_DATA_ERROR;
 
474
            } else {
 
475
                (void)getLong(s);
 
476
                /* The uncompressed length returned by above getlong() may be
 
477
                 * different from s->out in case of concatenated .gz files.
 
478
                 * Check for such files:
 
479
                 */
 
480
                check_header(s);
 
481
                if (s->z_err == Z_OK) {
 
482
                    inflateReset(&(s->stream));
 
483
                    s->crc = crc32(0L, Z_NULL, 0);
 
484
                }
 
485
            }
 
486
        }
 
487
        if (s->z_err != Z_OK || s->z_eof) break;
 
488
    }
 
489
    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
 
490
 
 
491
    return (int)(len - s->stream.avail_out);
 
492
}
 
493
 
 
494
 
 
495
/* ===========================================================================
 
496
      Reads one byte from the compressed file. gzgetc returns this byte
 
497
   or -1 in case of end of file or error.
 
498
*/
 
499
int ZEXPORT gzgetc(file)
 
500
    gzFile file;
 
501
{
 
502
    unsigned char c;
 
503
 
 
504
    return gzread(file, &c, 1) == 1 ? c : -1;
 
505
}
 
506
 
 
507
 
 
508
/* ===========================================================================
 
509
      Push one byte back onto the stream.
 
510
*/
 
511
int ZEXPORT gzungetc(c, file)
 
512
    int c;
 
513
    gzFile file;
 
514
{
 
515
    gz_stream *s = (gz_stream*)file;
 
516
 
 
517
    if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
 
518
    s->back = c;
 
519
    s->out--;
 
520
    s->last = (s->z_err == Z_STREAM_END);
 
521
    if (s->last) s->z_err = Z_OK;
 
522
    s->z_eof = 0;
 
523
    return c;
 
524
}
 
525
 
 
526
 
 
527
/* ===========================================================================
 
528
      Reads bytes from the compressed file until len-1 characters are
 
529
   read, or a newline character is read and transferred to buf, or an
 
530
   end-of-file condition is encountered.  The string is then terminated
 
531
   with a null character.
 
532
      gzgets returns buf, or Z_NULL in case of error.
 
533
 
 
534
      The current implementation is not optimized at all.
 
535
*/
 
536
char * ZEXPORT gzgets(file, buf, len)
 
537
    gzFile file;
 
538
    char *buf;
 
539
    int len;
 
540
{
 
541
    char *b = buf;
 
542
    if (buf == Z_NULL || len <= 0) return Z_NULL;
 
543
 
 
544
    while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
 
545
    *buf = '\0';
 
546
    return b == buf && len > 0 ? Z_NULL : b;
 
547
}
 
548
 
 
549
 
 
550
#ifndef NO_GZCOMPRESS
 
551
/* ===========================================================================
 
552
     Writes the given number of uncompressed bytes into the compressed file.
 
553
   gzwrite returns the number of bytes actually written (0 in case of error).
 
554
*/
 
555
int ZEXPORT gzwrite (file, buf, len)
 
556
    gzFile file;
 
557
    voidpc buf;
 
558
    unsigned len;
 
559
{
 
560
    gz_stream *s = (gz_stream*)file;
 
561
 
 
562
    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
 
563
 
 
564
    s->stream.next_in = (Bytef*)buf;
 
565
    s->stream.avail_in = len;
 
566
 
 
567
    while (s->stream.avail_in != 0) {
 
568
 
 
569
        if (s->stream.avail_out == 0) {
 
570
 
 
571
            s->stream.next_out = s->outbuf;
 
572
            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
 
573
                s->z_err = Z_ERRNO;
 
574
                break;
 
575
            }
 
576
            s->stream.avail_out = Z_BUFSIZE;
 
577
        }
 
578
        s->in += s->stream.avail_in;
 
579
        s->out += s->stream.avail_out;
 
580
        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
 
581
        s->in -= s->stream.avail_in;
 
582
        s->out -= s->stream.avail_out;
 
583
        if (s->z_err != Z_OK) break;
 
584
    }
 
585
    s->crc = crc32(s->crc, (const Bytef *)buf, len);
 
586
 
 
587
    return (int)(len - s->stream.avail_in);
 
588
}
 
589
 
 
590
 
 
591
/* ===========================================================================
 
592
     Converts, formats, and writes the args to the compressed file under
 
593
   control of the format string, as in fprintf. gzprintf returns the number of
 
594
   uncompressed bytes actually written (0 in case of error).
 
595
*/
 
596
#ifdef STDC
 
597
#include <stdarg.h>
 
598
 
 
599
int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
 
600
{
 
601
    char buf[Z_PRINTF_BUFSIZE];
 
602
    va_list va;
 
603
    int len;
 
604
 
 
605
    buf[sizeof(buf) - 1] = 0;
 
606
    va_start(va, format);
 
607
#ifdef NO_vsnprintf
 
608
#  ifdef HAS_vsprintf_void
 
609
    (void)vsprintf(buf, format, va);
 
610
    va_end(va);
 
611
    for (len = 0; len < sizeof(buf); len++)
 
612
        if (buf[len] == 0) break;
 
613
#  else
 
614
    len = vsprintf(buf, format, va);
 
615
    va_end(va);
 
616
#  endif
 
617
#else
 
618
#  ifdef HAS_vsnprintf_void
 
619
    (void)vsnprintf(buf, sizeof(buf), format, va);
 
620
    va_end(va);
 
621
    len = strlen(buf);
 
622
#  else
 
623
    len = vsnprintf(buf, sizeof(buf), format, va);
 
624
    va_end(va);
 
625
#  endif
 
626
#endif
 
627
    if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
 
628
        return 0;
 
629
    return gzwrite(file, buf, (unsigned)len);
 
630
}
 
631
#else /* not ANSI C */
 
632
 
 
633
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
 
634
                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
 
635
    gzFile file;
 
636
    const char *format;
 
637
    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
 
638
        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
 
639
{
 
640
    char buf[Z_PRINTF_BUFSIZE];
 
641
    int len;
 
642
 
 
643
    buf[sizeof(buf) - 1] = 0;
 
644
#ifdef NO_snprintf
 
645
#  ifdef HAS_sprintf_void
 
646
    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
 
647
            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 
648
    for (len = 0; len < sizeof(buf); len++)
 
649
        if (buf[len] == 0) break;
 
650
#  else
 
651
    len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
 
652
                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 
653
#  endif
 
654
#else
 
655
#  ifdef HAS_snprintf_void
 
656
    snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
 
657
             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 
658
    len = strlen(buf);
 
659
#  else
 
660
    len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
 
661
                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 
662
#  endif
 
663
#endif
 
664
    if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
 
665
        return 0;
 
666
    return gzwrite(file, buf, len);
 
667
}
 
668
#endif
 
669
 
 
670
/* ===========================================================================
 
671
      Writes c, converted to an unsigned char, into the compressed file.
 
672
   gzputc returns the value that was written, or -1 in case of error.
 
673
*/
 
674
int ZEXPORT gzputc(file, c)
 
675
    gzFile file;
 
676
    int c;
 
677
{
 
678
    unsigned char cc = (unsigned char) c; /* required for big endian systems */
 
679
 
 
680
    return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
 
681
}
 
682
 
 
683
 
 
684
/* ===========================================================================
 
685
      Writes the given null-terminated string to the compressed file, excluding
 
686
   the terminating null character.
 
687
      gzputs returns the number of characters written, or -1 in case of error.
 
688
*/
 
689
int ZEXPORT gzputs(file, s)
 
690
    gzFile file;
 
691
    const char *s;
 
692
{
 
693
    return gzwrite(file, (char*)s, (unsigned)strlen(s));
 
694
}
 
695
 
 
696
 
 
697
/* ===========================================================================
 
698
     Flushes all pending output into the compressed file. The parameter
 
699
   flush is as in the deflate() function.
 
700
*/
 
701
local int do_flush (file, flush)
 
702
    gzFile file;
 
703
    int flush;
 
704
{
 
705
    uInt len;
 
706
    int done = 0;
 
707
    gz_stream *s = (gz_stream*)file;
 
708
 
 
709
    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
 
710
 
 
711
    s->stream.avail_in = 0; /* should be zero already anyway */
 
712
 
 
713
    for (;;) {
 
714
        len = Z_BUFSIZE - s->stream.avail_out;
 
715
 
 
716
        if (len != 0) {
 
717
            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
 
718
                s->z_err = Z_ERRNO;
 
719
                return Z_ERRNO;
 
720
            }
 
721
            s->stream.next_out = s->outbuf;
 
722
            s->stream.avail_out = Z_BUFSIZE;
 
723
        }
 
724
        if (done) break;
 
725
        s->out += s->stream.avail_out;
 
726
        s->z_err = deflate(&(s->stream), flush);
 
727
        s->out -= s->stream.avail_out;
 
728
 
 
729
        /* Ignore the second of two consecutive flushes: */
 
730
        if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
 
731
 
 
732
        /* deflate has finished flushing only when it hasn't used up
 
733
         * all the available space in the output buffer:
 
734
         */
 
735
        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
 
736
 
 
737
        if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
 
738
    }
 
739
    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
 
740
}
 
741
 
 
742
int ZEXPORT gzflush (file, flush)
 
743
     gzFile file;
 
744
     int flush;
 
745
{
 
746
    gz_stream *s = (gz_stream*)file;
 
747
    int err = do_flush (file, flush);
 
748
 
 
749
    if (err) return err;
 
750
    fflush(s->file);
 
751
    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
 
752
}
 
753
#endif /* NO_GZCOMPRESS */
 
754
 
 
755
/* ===========================================================================
 
756
      Sets the starting position for the next gzread or gzwrite on the given
 
757
   compressed file. The offset represents a number of bytes in the
 
758
      gzseek returns the resulting offset location as measured in bytes from
 
759
   the beginning of the uncompressed stream, or -1 in case of error.
 
760
      SEEK_END is not implemented, returns error.
 
761
      In this version of the library, gzseek can be extremely slow.
 
762
*/
 
763
z_off_t ZEXPORT gzseek (file, offset, whence)
 
764
    gzFile file;
 
765
    z_off_t offset;
 
766
    int whence;
 
767
{
 
768
    gz_stream *s = (gz_stream*)file;
 
769
 
 
770
    if (s == NULL || whence == SEEK_END ||
 
771
        s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
 
772
        return -1L;
 
773
    }
 
774
 
 
775
    if (s->mode == 'w') {
 
776
#ifdef NO_GZCOMPRESS
 
777
        return -1L;
 
778
#else
 
779
        if (whence == SEEK_SET) {
 
780
            offset -= s->in;
 
781
        }
 
782
        if (offset < 0) return -1L;
 
783
 
 
784
        /* At this point, offset is the number of zero bytes to write. */
 
785
        if (s->inbuf == Z_NULL) {
 
786
            s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
 
787
            if (s->inbuf == Z_NULL) return -1L;
 
788
            zmemzero(s->inbuf, Z_BUFSIZE);
 
789
        }
 
790
        while (offset > 0)  {
 
791
            uInt size = Z_BUFSIZE;
 
792
            if (offset < Z_BUFSIZE) size = (uInt)offset;
 
793
 
 
794
            size = gzwrite(file, s->inbuf, size);
 
795
            if (size == 0) return -1L;
 
796
 
 
797
            offset -= size;
 
798
        }
 
799
        return s->in;
 
800
#endif
 
801
    }
 
802
    /* Rest of function is for reading only */
 
803
 
 
804
    /* compute absolute position */
 
805
    if (whence == SEEK_CUR) {
 
806
        offset += s->out;
 
807
    }
 
808
    if (offset < 0) return -1L;
 
809
 
 
810
    if (s->transparent) {
 
811
        /* map to fseek */
 
812
        s->back = EOF;
 
813
        s->stream.avail_in = 0;
 
814
        s->stream.next_in = s->inbuf;
 
815
        if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
 
816
 
 
817
        s->in = s->out = offset;
 
818
        return offset;
 
819
    }
 
820
 
 
821
    /* For a negative seek, rewind and use positive seek */
 
822
    if (offset >= s->out) {
 
823
        offset -= s->out;
 
824
    } else if (gzrewind(file) < 0) {
 
825
        return -1L;
 
826
    }
 
827
    /* offset is now the number of bytes to skip. */
 
828
 
 
829
    if (offset != 0 && s->outbuf == Z_NULL) {
 
830
        s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
 
831
        if (s->outbuf == Z_NULL) return -1L;
 
832
    }
 
833
    if (offset && s->back != EOF) {
 
834
        s->back = EOF;
 
835
        s->out++;
 
836
        offset--;
 
837
        if (s->last) s->z_err = Z_STREAM_END;
 
838
    }
 
839
    while (offset > 0)  {
 
840
        int size = Z_BUFSIZE;
 
841
        if (offset < Z_BUFSIZE) size = (int)offset;
 
842
 
 
843
        size = gzread(file, s->outbuf, (uInt)size);
 
844
        if (size <= 0) return -1L;
 
845
        offset -= size;
 
846
    }
 
847
    return s->out;
 
848
}
 
849
 
 
850
/* ===========================================================================
 
851
     Rewinds input file.
 
852
*/
 
853
int ZEXPORT gzrewind (file)
 
854
    gzFile file;
 
855
{
 
856
    gz_stream *s = (gz_stream*)file;
 
857
 
 
858
    if (s == NULL || s->mode != 'r') return -1;
 
859
 
 
860
    s->z_err = Z_OK;
 
861
    s->z_eof = 0;
 
862
    s->back = EOF;
 
863
    s->stream.avail_in = 0;
 
864
    s->stream.next_in = s->inbuf;
 
865
    s->crc = crc32(0L, Z_NULL, 0);
 
866
    if (!s->transparent) (void)inflateReset(&s->stream);
 
867
    s->in = 0;
 
868
    s->out = 0;
 
869
    return fseek(s->file, s->start, SEEK_SET);
 
870
}
 
871
 
 
872
/* ===========================================================================
 
873
     Returns the starting position for the next gzread or gzwrite on the
 
874
   given compressed file. This position represents a number of bytes in the
 
875
   uncompressed data stream.
 
876
*/
 
877
z_off_t ZEXPORT gztell (file)
 
878
    gzFile file;
 
879
{
 
880
    return gzseek(file, 0L, SEEK_CUR);
 
881
}
 
882
 
 
883
/* ===========================================================================
 
884
     Returns 1 when EOF has previously been detected reading the given
 
885
   input stream, otherwise zero.
 
886
*/
 
887
int ZEXPORT gzeof (file)
 
888
    gzFile file;
 
889
{
 
890
    gz_stream *s = (gz_stream*)file;
 
891
 
 
892
    /* With concatenated compressed files that can have embedded
 
893
     * crc trailers, z_eof is no longer the only/best indicator of EOF
 
894
     * on a gz_stream. Handle end-of-stream error explicitly here.
 
895
     */
 
896
    if (s == NULL || s->mode != 'r') return 0;
 
897
    if (s->z_eof) return 1;
 
898
    return s->z_err == Z_STREAM_END;
 
899
}
 
900
 
 
901
/* ===========================================================================
 
902
   Outputs a long in LSB order to the given file
 
903
*/
 
904
local void putLong (file, x)
 
905
    FILE *file;
 
906
    uLong x;
 
907
{
 
908
    int n;
 
909
    for (n = 0; n < 4; n++) {
 
910
        fputc((int)(x & 0xff), file);
 
911
        x >>= 8;
 
912
    }
 
913
}
 
914
 
 
915
/* ===========================================================================
 
916
   Reads a long in LSB order from the given gz_stream. Sets z_err in case
 
917
   of error.
 
918
*/
 
919
local uLong getLong (s)
 
920
    gz_stream *s;
 
921
{
 
922
    uLong x = (uLong)get_byte(s);
 
923
    int c;
 
924
 
 
925
    x += ((uLong)get_byte(s))<<8;
 
926
    x += ((uLong)get_byte(s))<<16;
 
927
    c = get_byte(s);
 
928
    if (c == EOF) s->z_err = Z_DATA_ERROR;
 
929
    x += ((uLong)c)<<24;
 
930
    return x;
 
931
}
 
932
 
 
933
/* ===========================================================================
 
934
     Flushes all pending output if necessary, closes the compressed file
 
935
   and deallocates all the (de)compression state.
 
936
*/
 
937
int ZEXPORT gzclose (file)
 
938
    gzFile file;
 
939
{
 
940
    int err;
 
941
    gz_stream *s = (gz_stream*)file;
 
942
 
 
943
    if (s == NULL) return Z_STREAM_ERROR;
 
944
 
 
945
    if (s->mode == 'w') {
 
946
#ifdef NO_GZCOMPRESS
 
947
        return Z_STREAM_ERROR;
 
948
#else
 
949
        err = do_flush (file, Z_FINISH);
 
950
        if (err != Z_OK) return destroy((gz_stream*)file);
 
951
 
 
952
        putLong (s->file, s->crc);
 
953
        putLong (s->file, (uLong)(s->in & 0xffffffff));
 
954
#endif
 
955
    }
 
956
    return destroy((gz_stream*)file);
 
957
}
 
958
 
 
959
/* ===========================================================================
 
960
     Returns the error message for the last error which occured on the
 
961
   given compressed file. errnum is set to zlib error number. If an
 
962
   error occured in the file system and not in the compression library,
 
963
   errnum is set to Z_ERRNO and the application may consult errno
 
964
   to get the exact error code.
 
965
*/
 
966
const char * ZEXPORT gzerror (file, errnum)
 
967
    gzFile file;
 
968
    int *errnum;
 
969
{
 
970
    char *m;
 
971
    gz_stream *s = (gz_stream*)file;
 
972
 
 
973
    if (s == NULL) {
 
974
        *errnum = Z_STREAM_ERROR;
 
975
        return (const char*)ERR_MSG(Z_STREAM_ERROR);
 
976
    }
 
977
    *errnum = s->z_err;
 
978
    if (*errnum == Z_OK) return (const char*)"";
 
979
 
 
980
    m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
 
981
 
 
982
    if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
 
983
 
 
984
    TRYFREE(s->msg);
 
985
    s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
 
986
    if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
 
987
    strcpy(s->msg, s->path);
 
988
    strcat(s->msg, ": ");
 
989
    strcat(s->msg, m);
 
990
    return (const char*)s->msg;
 
991
}
 
992
 
 
993
/* ===========================================================================
 
994
     Clear the error and end-of-file flags, and do the same for the real file.
 
995
*/
 
996
void ZEXPORT gzclearerr (file)
 
997
    gzFile file;
 
998
{
 
999
    gz_stream *s = (gz_stream*)file;
 
1000
 
 
1001
    if (s == NULL) return;
 
1002
    if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
 
1003
    s->z_eof = 0;
 
1004
    clearerr(s->file);
 
1005
}