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

« back to all changes in this revision

Viewing changes to mozilla/security/nss/cmd/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 2005/07/20 20:32:42 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
 
}