source: svn/newcon3bcm2_21bu/dst/dlib/src/ZLIB/gzio.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

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