~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to zlib/gzio.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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