~ubuntu-branches/ubuntu/raring/nss/raring-security

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/zlib/gzio.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-03-25 13:46:06 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20100325134606-bl6liuok2w9l7snv
Tags: 3.12.6-0ubuntu1
* New upstream release 3.12.6 RTM (NSS_3_12_6_RTM)
  - fixes CVE-2009-3555 aka US-CERT VU#120541
* Adjust patches to changed upstream code base
  - update debian/patches/38_kbsd.patch
  - update debian/patches/38_mips64_build.patch
  - update debian/patches/85_security_load.patch
* Remove patches that are merged upstream
  - delete debian/patches/91_nonexec_stack.patch
  - update debian/patches/series
* Bump nspr dependency to 4.8
  - update debian/control
* Add new symbols for 3.12.6
  - update debian/libnss3-1d.symbols

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: gzio.c,v 1.5 2009/11/07 01:13:10 wtchang%redhat.com Exp $ */
 
9
 
 
10
#include <stdio.h>
 
11
 
 
12
#include "zutil.h"
 
13
 
 
14
#ifdef NO_DEFLATE       /* for compatibility 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[46];      /* allow for up to 128-bit integers */
 
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 = (uInt)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 = (uInt)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
        start++;
 
419
        if (s->last) {
 
420
            s->z_err = Z_STREAM_END;
 
421
            return 1;
 
422
        }
 
423
    }
 
424
 
 
425
    while (s->stream.avail_out != 0) {
 
426
 
 
427
        if (s->transparent) {
 
428
            /* Copy first the lookahead bytes: */
 
429
            uInt n = s->stream.avail_in;
 
430
            if (n > s->stream.avail_out) n = s->stream.avail_out;
 
431
            if (n > 0) {
 
432
                zmemcpy(s->stream.next_out, s->stream.next_in, n);
 
433
                next_out += n;
 
434
                s->stream.next_out = next_out;
 
435
                s->stream.next_in   += n;
 
436
                s->stream.avail_out -= n;
 
437
                s->stream.avail_in  -= n;
 
438
            }
 
439
            if (s->stream.avail_out > 0) {
 
440
                s->stream.avail_out -=
 
441
                    (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
 
442
            }
 
443
            len -= s->stream.avail_out;
 
444
            s->in  += len;
 
445
            s->out += len;
 
446
            if (len == 0) s->z_eof = 1;
 
447
            return (int)len;
 
448
        }
 
449
        if (s->stream.avail_in == 0 && !s->z_eof) {
 
450
 
 
451
            errno = 0;
 
452
            s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
 
453
            if (s->stream.avail_in == 0) {
 
454
                s->z_eof = 1;
 
455
                if (ferror(s->file)) {
 
456
                    s->z_err = Z_ERRNO;
 
457
                    break;
 
458
                }
 
459
            }
 
460
            s->stream.next_in = s->inbuf;
 
461
        }
 
462
        s->in += s->stream.avail_in;
 
463
        s->out += s->stream.avail_out;
 
464
        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
 
465
        s->in -= s->stream.avail_in;
 
466
        s->out -= s->stream.avail_out;
 
467
 
 
468
        if (s->z_err == Z_STREAM_END) {
 
469
            /* Check CRC and original size */
 
470
            s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
 
471
            start = s->stream.next_out;
 
472
 
 
473
            if (getLong(s) != s->crc) {
 
474
                s->z_err = Z_DATA_ERROR;
 
475
            } else {
 
476
                (void)getLong(s);
 
477
                /* The uncompressed length returned by above getlong() may be
 
478
                 * different from s->out in case of concatenated .gz files.
 
479
                 * Check for such files:
 
480
                 */
 
481
                check_header(s);
 
482
                if (s->z_err == Z_OK) {
 
483
                    inflateReset(&(s->stream));
 
484
                    s->crc = crc32(0L, Z_NULL, 0);
 
485
                }
 
486
            }
 
487
        }
 
488
        if (s->z_err != Z_OK || s->z_eof) break;
 
489
    }
 
490
    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
 
491
 
 
492
    if (len == s->stream.avail_out &&
 
493
        (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
 
494
        return -1;
 
495
    return (int)(len - s->stream.avail_out);
 
496
}
 
497
 
 
498
 
 
499
/* ===========================================================================
 
500
      Reads one byte from the compressed file. gzgetc returns this byte
 
501
   or -1 in case of end of file or error.
 
502
*/
 
503
int ZEXPORT gzgetc(file)
 
504
    gzFile file;
 
505
{
 
506
    unsigned char c;
 
507
 
 
508
    return gzread(file, &c, 1) == 1 ? c : -1;
 
509
}
 
510
 
 
511
 
 
512
/* ===========================================================================
 
513
      Push one byte back onto the stream.
 
514
*/
 
515
int ZEXPORT gzungetc(c, file)
 
516
    int c;
 
517
    gzFile file;
 
518
{
 
519
    gz_stream *s = (gz_stream*)file;
 
520
 
 
521
    if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
 
522
    s->back = c;
 
523
    s->out--;
 
524
    s->last = (s->z_err == Z_STREAM_END);
 
525
    if (s->last) s->z_err = Z_OK;
 
526
    s->z_eof = 0;
 
527
    return c;
 
528
}
 
529
 
 
530
 
 
531
/* ===========================================================================
 
532
      Reads bytes from the compressed file until len-1 characters are
 
533
   read, or a newline character is read and transferred to buf, or an
 
534
   end-of-file condition is encountered.  The string is then terminated
 
535
   with a null character.
 
536
      gzgets returns buf, or Z_NULL in case of error.
 
537
 
 
538
      The current implementation is not optimized at all.
 
539
*/
 
540
char * ZEXPORT gzgets(file, buf, len)
 
541
    gzFile file;
 
542
    char *buf;
 
543
    int len;
 
544
{
 
545
    char *b = buf;
 
546
    if (buf == Z_NULL || len <= 0) return Z_NULL;
 
547
 
 
548
    while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
 
549
    *buf = '\0';
 
550
    return b == buf && len > 0 ? Z_NULL : b;
 
551
}
 
552
 
 
553
 
 
554
#ifndef NO_GZCOMPRESS
 
555
/* ===========================================================================
 
556
     Writes the given number of uncompressed bytes into the compressed file.
 
557
   gzwrite returns the number of bytes actually written (0 in case of error).
 
558
*/
 
559
int ZEXPORT gzwrite (file, buf, len)
 
560
    gzFile file;
 
561
    voidpc buf;
 
562
    unsigned len;
 
563
{
 
564
    gz_stream *s = (gz_stream*)file;
 
565
 
 
566
    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
 
567
 
 
568
    s->stream.next_in = (Bytef*)buf;
 
569
    s->stream.avail_in = len;
 
570
 
 
571
    while (s->stream.avail_in != 0) {
 
572
 
 
573
        if (s->stream.avail_out == 0) {
 
574
 
 
575
            s->stream.next_out = s->outbuf;
 
576
            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
 
577
                s->z_err = Z_ERRNO;
 
578
                break;
 
579
            }
 
580
            s->stream.avail_out = Z_BUFSIZE;
 
581
        }
 
582
        s->in += s->stream.avail_in;
 
583
        s->out += s->stream.avail_out;
 
584
        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
 
585
        s->in -= s->stream.avail_in;
 
586
        s->out -= s->stream.avail_out;
 
587
        if (s->z_err != Z_OK) break;
 
588
    }
 
589
    s->crc = crc32(s->crc, (const Bytef *)buf, len);
 
590
 
 
591
    return (int)(len - s->stream.avail_in);
 
592
}
 
593
 
 
594
 
 
595
/* ===========================================================================
 
596
     Converts, formats, and writes the args to the compressed file under
 
597
   control of the format string, as in fprintf. gzprintf returns the number of
 
598
   uncompressed bytes actually written (0 in case of error).
 
599
*/
 
600
#ifdef STDC
 
601
#include <stdarg.h>
 
602
 
 
603
int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
 
604
{
 
605
    char buf[Z_PRINTF_BUFSIZE];
 
606
    va_list va;
 
607
    int len;
 
608
 
 
609
    buf[sizeof(buf) - 1] = 0;
 
610
    va_start(va, format);
 
611
#ifdef NO_vsnprintf
 
612
#  ifdef HAS_vsprintf_void
 
613
    (void)vsprintf(buf, format, va);
 
614
    va_end(va);
 
615
    for (len = 0; len < sizeof(buf); len++)
 
616
        if (buf[len] == 0) break;
 
617
#  else
 
618
    len = vsprintf(buf, format, va);
 
619
    va_end(va);
 
620
#  endif
 
621
#else
 
622
#  ifdef HAS_vsnprintf_void
 
623
    (void)vsnprintf(buf, sizeof(buf), format, va);
 
624
    va_end(va);
 
625
    len = strlen(buf);
 
626
#  else
 
627
    len = vsnprintf(buf, sizeof(buf), format, va);
 
628
    va_end(va);
 
629
#  endif
 
630
#endif
 
631
    if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
 
632
        return 0;
 
633
    return gzwrite(file, buf, (unsigned)len);
 
634
}
 
635
#else /* not ANSI C */
 
636
 
 
637
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
 
638
                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
 
639
    gzFile file;
 
640
    const char *format;
 
641
    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
 
642
        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
 
643
{
 
644
    char buf[Z_PRINTF_BUFSIZE];
 
645
    int len;
 
646
 
 
647
    buf[sizeof(buf) - 1] = 0;
 
648
#ifdef NO_snprintf
 
649
#  ifdef HAS_sprintf_void
 
650
    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
 
651
            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 
652
    for (len = 0; len < sizeof(buf); len++)
 
653
        if (buf[len] == 0) break;
 
654
#  else
 
655
    len = 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
#  endif
 
658
#else
 
659
#  ifdef HAS_snprintf_void
 
660
    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
    len = strlen(buf);
 
663
#  else
 
664
    len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
 
665
                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 
666
#  endif
 
667
#endif
 
668
    if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
 
669
        return 0;
 
670
    return gzwrite(file, buf, len);
 
671
}
 
672
#endif
 
673
 
 
674
/* ===========================================================================
 
675
      Writes c, converted to an unsigned char, into the compressed file.
 
676
   gzputc returns the value that was written, or -1 in case of error.
 
677
*/
 
678
int ZEXPORT gzputc(file, c)
 
679
    gzFile file;
 
680
    int c;
 
681
{
 
682
    unsigned char cc = (unsigned char) c; /* required for big endian systems */
 
683
 
 
684
    return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
 
685
}
 
686
 
 
687
 
 
688
/* ===========================================================================
 
689
      Writes the given null-terminated string to the compressed file, excluding
 
690
   the terminating null character.
 
691
      gzputs returns the number of characters written, or -1 in case of error.
 
692
*/
 
693
int ZEXPORT gzputs(file, s)
 
694
    gzFile file;
 
695
    const char *s;
 
696
{
 
697
    return gzwrite(file, (char*)s, (unsigned)strlen(s));
 
698
}
 
699
 
 
700
 
 
701
/* ===========================================================================
 
702
     Flushes all pending output into the compressed file. The parameter
 
703
   flush is as in the deflate() function.
 
704
*/
 
705
local int do_flush (file, flush)
 
706
    gzFile file;
 
707
    int flush;
 
708
{
 
709
    uInt len;
 
710
    int done = 0;
 
711
    gz_stream *s = (gz_stream*)file;
 
712
 
 
713
    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
 
714
 
 
715
    s->stream.avail_in = 0; /* should be zero already anyway */
 
716
 
 
717
    for (;;) {
 
718
        len = Z_BUFSIZE - s->stream.avail_out;
 
719
 
 
720
        if (len != 0) {
 
721
            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
 
722
                s->z_err = Z_ERRNO;
 
723
                return Z_ERRNO;
 
724
            }
 
725
            s->stream.next_out = s->outbuf;
 
726
            s->stream.avail_out = Z_BUFSIZE;
 
727
        }
 
728
        if (done) break;
 
729
        s->out += s->stream.avail_out;
 
730
        s->z_err = deflate(&(s->stream), flush);
 
731
        s->out -= s->stream.avail_out;
 
732
 
 
733
        /* Ignore the second of two consecutive flushes: */
 
734
        if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
 
735
 
 
736
        /* deflate has finished flushing only when it hasn't used up
 
737
         * all the available space in the output buffer:
 
738
         */
 
739
        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
 
740
 
 
741
        if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
 
742
    }
 
743
    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
 
744
}
 
745
 
 
746
int ZEXPORT gzflush (file, flush)
 
747
     gzFile file;
 
748
     int flush;
 
749
{
 
750
    gz_stream *s = (gz_stream*)file;
 
751
    int err = do_flush (file, flush);
 
752
 
 
753
    if (err) return err;
 
754
    fflush(s->file);
 
755
    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
 
756
}
 
757
#endif /* NO_GZCOMPRESS */
 
758
 
 
759
/* ===========================================================================
 
760
      Sets the starting position for the next gzread or gzwrite on the given
 
761
   compressed file. The offset represents a number of bytes in the
 
762
      gzseek returns the resulting offset location as measured in bytes from
 
763
   the beginning of the uncompressed stream, or -1 in case of error.
 
764
      SEEK_END is not implemented, returns error.
 
765
      In this version of the library, gzseek can be extremely slow.
 
766
*/
 
767
z_off_t ZEXPORT gzseek (file, offset, whence)
 
768
    gzFile file;
 
769
    z_off_t offset;
 
770
    int whence;
 
771
{
 
772
    gz_stream *s = (gz_stream*)file;
 
773
 
 
774
    if (s == NULL || whence == SEEK_END ||
 
775
        s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
 
776
        return -1L;
 
777
    }
 
778
 
 
779
    if (s->mode == 'w') {
 
780
#ifdef NO_GZCOMPRESS
 
781
        return -1L;
 
782
#else
 
783
        if (whence == SEEK_SET) {
 
784
            offset -= s->in;
 
785
        }
 
786
        if (offset < 0) return -1L;
 
787
 
 
788
        /* At this point, offset is the number of zero bytes to write. */
 
789
        if (s->inbuf == Z_NULL) {
 
790
            s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
 
791
            if (s->inbuf == Z_NULL) return -1L;
 
792
            zmemzero(s->inbuf, Z_BUFSIZE);
 
793
        }
 
794
        while (offset > 0)  {
 
795
            uInt size = Z_BUFSIZE;
 
796
            if (offset < Z_BUFSIZE) size = (uInt)offset;
 
797
 
 
798
            size = gzwrite(file, s->inbuf, size);
 
799
            if (size == 0) return -1L;
 
800
 
 
801
            offset -= size;
 
802
        }
 
803
        return s->in;
 
804
#endif
 
805
    }
 
806
    /* Rest of function is for reading only */
 
807
 
 
808
    /* compute absolute position */
 
809
    if (whence == SEEK_CUR) {
 
810
        offset += s->out;
 
811
    }
 
812
    if (offset < 0) return -1L;
 
813
 
 
814
    if (s->transparent) {
 
815
        /* map to fseek */
 
816
        s->back = EOF;
 
817
        s->stream.avail_in = 0;
 
818
        s->stream.next_in = s->inbuf;
 
819
        if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
 
820
 
 
821
        s->in = s->out = offset;
 
822
        return offset;
 
823
    }
 
824
 
 
825
    /* For a negative seek, rewind and use positive seek */
 
826
    if (offset >= s->out) {
 
827
        offset -= s->out;
 
828
    } else if (gzrewind(file) < 0) {
 
829
        return -1L;
 
830
    }
 
831
    /* offset is now the number of bytes to skip. */
 
832
 
 
833
    if (offset != 0 && s->outbuf == Z_NULL) {
 
834
        s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
 
835
        if (s->outbuf == Z_NULL) return -1L;
 
836
    }
 
837
    if (offset && s->back != EOF) {
 
838
        s->back = EOF;
 
839
        s->out++;
 
840
        offset--;
 
841
        if (s->last) s->z_err = Z_STREAM_END;
 
842
    }
 
843
    while (offset > 0)  {
 
844
        int size = Z_BUFSIZE;
 
845
        if (offset < Z_BUFSIZE) size = (int)offset;
 
846
 
 
847
        size = gzread(file, s->outbuf, (uInt)size);
 
848
        if (size <= 0) return -1L;
 
849
        offset -= size;
 
850
    }
 
851
    return s->out;
 
852
}
 
853
 
 
854
/* ===========================================================================
 
855
     Rewinds input file.
 
856
*/
 
857
int ZEXPORT gzrewind (file)
 
858
    gzFile file;
 
859
{
 
860
    gz_stream *s = (gz_stream*)file;
 
861
 
 
862
    if (s == NULL || s->mode != 'r') return -1;
 
863
 
 
864
    s->z_err = Z_OK;
 
865
    s->z_eof = 0;
 
866
    s->back = EOF;
 
867
    s->stream.avail_in = 0;
 
868
    s->stream.next_in = s->inbuf;
 
869
    s->crc = crc32(0L, Z_NULL, 0);
 
870
    if (!s->transparent) (void)inflateReset(&s->stream);
 
871
    s->in = 0;
 
872
    s->out = 0;
 
873
    return fseek(s->file, s->start, SEEK_SET);
 
874
}
 
875
 
 
876
/* ===========================================================================
 
877
     Returns the starting position for the next gzread or gzwrite on the
 
878
   given compressed file. This position represents a number of bytes in the
 
879
   uncompressed data stream.
 
880
*/
 
881
z_off_t ZEXPORT gztell (file)
 
882
    gzFile file;
 
883
{
 
884
    return gzseek(file, 0L, SEEK_CUR);
 
885
}
 
886
 
 
887
/* ===========================================================================
 
888
     Returns 1 when EOF has previously been detected reading the given
 
889
   input stream, otherwise zero.
 
890
*/
 
891
int ZEXPORT gzeof (file)
 
892
    gzFile file;
 
893
{
 
894
    gz_stream *s = (gz_stream*)file;
 
895
 
 
896
    /* With concatenated compressed files that can have embedded
 
897
     * crc trailers, z_eof is no longer the only/best indicator of EOF
 
898
     * on a gz_stream. Handle end-of-stream error explicitly here.
 
899
     */
 
900
    if (s == NULL || s->mode != 'r') return 0;
 
901
    if (s->z_eof) return 1;
 
902
    return s->z_err == Z_STREAM_END;
 
903
}
 
904
 
 
905
/* ===========================================================================
 
906
     Returns 1 if reading and doing so transparently, otherwise zero.
 
907
*/
 
908
int ZEXPORT gzdirect (file)
 
909
    gzFile file;
 
910
{
 
911
    gz_stream *s = (gz_stream*)file;
 
912
 
 
913
    if (s == NULL || s->mode != 'r') return 0;
 
914
    return s->transparent;
 
915
}
 
916
 
 
917
/* ===========================================================================
 
918
   Outputs a long in LSB order to the given file
 
919
*/
 
920
local void putLong (file, x)
 
921
    FILE *file;
 
922
    uLong x;
 
923
{
 
924
    int n;
 
925
    for (n = 0; n < 4; n++) {
 
926
        fputc((int)(x & 0xff), file);
 
927
        x >>= 8;
 
928
    }
 
929
}
 
930
 
 
931
/* ===========================================================================
 
932
   Reads a long in LSB order from the given gz_stream. Sets z_err in case
 
933
   of error.
 
934
*/
 
935
local uLong getLong (s)
 
936
    gz_stream *s;
 
937
{
 
938
    uLong x = (uLong)get_byte(s);
 
939
    int c;
 
940
 
 
941
    x += ((uLong)get_byte(s))<<8;
 
942
    x += ((uLong)get_byte(s))<<16;
 
943
    c = get_byte(s);
 
944
    if (c == EOF) s->z_err = Z_DATA_ERROR;
 
945
    x += ((uLong)c)<<24;
 
946
    return x;
 
947
}
 
948
 
 
949
/* ===========================================================================
 
950
     Flushes all pending output if necessary, closes the compressed file
 
951
   and deallocates all the (de)compression state.
 
952
*/
 
953
int ZEXPORT gzclose (file)
 
954
    gzFile file;
 
955
{
 
956
    gz_stream *s = (gz_stream*)file;
 
957
 
 
958
    if (s == NULL) return Z_STREAM_ERROR;
 
959
 
 
960
    if (s->mode == 'w') {
 
961
#ifdef NO_GZCOMPRESS
 
962
        return Z_STREAM_ERROR;
 
963
#else
 
964
        if (do_flush (file, Z_FINISH) != Z_OK)
 
965
            return destroy((gz_stream*)file);
 
966
 
 
967
        putLong (s->file, s->crc);
 
968
        putLong (s->file, (uLong)(s->in & 0xffffffff));
 
969
#endif
 
970
    }
 
971
    return destroy((gz_stream*)file);
 
972
}
 
973
 
 
974
#ifdef STDC
 
975
#  define zstrerror(errnum) strerror(errnum)
 
976
#else
 
977
#  define zstrerror(errnum) ""
 
978
#endif
 
979
 
 
980
/* ===========================================================================
 
981
     Returns the error message for the last error which occurred on the
 
982
   given compressed file. errnum is set to zlib error number. If an
 
983
   error occurred in the file system and not in the compression library,
 
984
   errnum is set to Z_ERRNO and the application may consult errno
 
985
   to get the exact error code.
 
986
*/
 
987
const char * ZEXPORT gzerror (file, errnum)
 
988
    gzFile file;
 
989
    int *errnum;
 
990
{
 
991
    char *m;
 
992
    gz_stream *s = (gz_stream*)file;
 
993
 
 
994
    if (s == NULL) {
 
995
        *errnum = Z_STREAM_ERROR;
 
996
        return (const char*)ERR_MSG(Z_STREAM_ERROR);
 
997
    }
 
998
    *errnum = s->z_err;
 
999
    if (*errnum == Z_OK) return (const char*)"";
 
1000
 
 
1001
    m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
 
1002
 
 
1003
    if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
 
1004
 
 
1005
    TRYFREE(s->msg);
 
1006
    s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
 
1007
    if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
 
1008
    strcpy(s->msg, s->path);
 
1009
    strcat(s->msg, ": ");
 
1010
    strcat(s->msg, m);
 
1011
    return (const char*)s->msg;
 
1012
}
 
1013
 
 
1014
/* ===========================================================================
 
1015
     Clear the error and end-of-file flags, and do the same for the real file.
 
1016
*/
 
1017
void ZEXPORT gzclearerr (file)
 
1018
    gzFile file;
 
1019
{
 
1020
    gz_stream *s = (gz_stream*)file;
 
1021
 
 
1022
    if (s == NULL) return;
 
1023
    if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
 
1024
    s->z_eof = 0;
 
1025
    clearerr(s->file);
 
1026
}