PageRenderTime 63ms CodeModel.GetById 18ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/ZLib/gzread.c

https://bitbucket.org/cabalistic/ogredeps/
C | 597 lines | 407 code | 70 blank | 120 comment | 180 complexity | 5c10ec9c91d0380b93f8b1a82c3e0405 MD5 | raw file
  1/* gzread.c -- zlib functions for reading gzip files
  2 * Copyright (C) 2004, 2005, 2010, 2011 Mark Adler
  3 * For conditions of distribution and use, see copyright notice in zlib.h
  4 */
  5
  6#include "gzguts.h"
  7
  8/** added by FreeImage */
  9#ifdef _MSC_VER
 10#include <io.h>	/* read, close */
 11/**
 12disable warning "The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name"
 13*/
 14#pragma warning(disable : 4996)
 15#endif /* _MSC_VER */
 16
 17#ifndef _WIN32
 18#  include <unistd.h>
 19#endif
 20
 21/* Local functions */
 22local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
 23local int gz_avail OF((gz_statep));
 24local int gz_look OF((gz_statep));
 25local int gz_decomp OF((gz_statep));
 26local int gz_fetch OF((gz_statep));
 27local int gz_skip OF((gz_statep, z_off64_t));
 28
 29/* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
 30   state->fd, and update state->eof, state->err, and state->msg as appropriate.
 31   This function needs to loop on read(), since read() is not guaranteed to
 32   read the number of bytes requested, depending on the type of descriptor. */
 33local int gz_load(state, buf, len, have)
 34    gz_statep state;
 35    unsigned char *buf;
 36    unsigned len;
 37    unsigned *have;
 38{
 39    int ret;
 40
 41    *have = 0;
 42    do {
 43        ret = read(state->fd, buf + *have, len - *have);
 44        if (ret <= 0)
 45            break;
 46        *have += ret;
 47    } while (*have < len);
 48    if (ret < 0) {
 49        gz_error(state, Z_ERRNO, zstrerror());
 50        return -1;
 51    }
 52    if (ret == 0)
 53        state->eof = 1;
 54    return 0;
 55}
 56
 57/* Load up input buffer and set eof flag if last data loaded -- return -1 on
 58   error, 0 otherwise.  Note that the eof flag is set when the end of the input
 59   file is reached, even though there may be unused data in the buffer.  Once
 60   that data has been used, no more attempts will be made to read the file.
 61   If strm->avail_in != 0, then the current data is moved to the beginning of
 62   the input buffer, and then the remainder of the buffer is loaded with the
 63   available data from the input file. */
 64local int gz_avail(state)
 65    gz_statep state;
 66{
 67    unsigned got;
 68    z_streamp strm = &(state->strm);
 69
 70    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
 71        return -1;
 72    if (state->eof == 0) {
 73        if (strm->avail_in)
 74            memmove(state->in, strm->next_in, strm->avail_in);
 75        if (gz_load(state, state->in + strm->avail_in,
 76                    state->size - strm->avail_in, &got) == -1)
 77            return -1;
 78        strm->avail_in += got;
 79        strm->next_in = state->in;
 80    }
 81    return 0;
 82}
 83
 84/* Look for gzip header, set up for inflate or copy.  state->x.have must be 0.
 85   If this is the first time in, allocate required memory.  state->how will be
 86   left unchanged if there is no more input data available, will be set to COPY
 87   if there is no gzip header and direct copying will be performed, or it will
 88   be set to GZIP for decompression.  If direct copying, then leftover input
 89   data from the input buffer will be copied to the output buffer.  In that
 90   case, all further file reads will be directly to either the output buffer or
 91   a user buffer.  If decompressing, the inflate state will be initialized.
 92   gz_look() will return 0 on success or -1 on failure. */
 93local int gz_look(state)
 94    gz_statep state;
 95{
 96    z_streamp strm = &(state->strm);
 97
 98    /* allocate read buffers and inflate memory */
 99    if (state->size == 0) {
100        /* allocate buffers */
101        state->in = malloc(state->want);
102        state->out = malloc(state->want << 1);
103        if (state->in == NULL || state->out == NULL) {
104            if (state->out != NULL)
105                free(state->out);
106            if (state->in != NULL)
107                free(state->in);
108            gz_error(state, Z_MEM_ERROR, "out of memory");
109            return -1;
110        }
111        state->size = state->want;
112
113        /* allocate inflate memory */
114        state->strm.zalloc = Z_NULL;
115        state->strm.zfree = Z_NULL;
116        state->strm.opaque = Z_NULL;
117        state->strm.avail_in = 0;
118        state->strm.next_in = Z_NULL;
119        if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) {    /* gunzip */
120            free(state->out);
121            free(state->in);
122            state->size = 0;
123            gz_error(state, Z_MEM_ERROR, "out of memory");
124            return -1;
125        }
126    }
127
128    /* get at least the magic bytes in the input buffer */
129    if (strm->avail_in < 2) {
130        if (gz_avail(state) == -1)
131            return -1;
132        if (strm->avail_in == 0)
133            return 0;
134    }
135
136    /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
137       a logical dilemma here when considering the case of a partially written
138       gzip file, to wit, if a single 31 byte is written, then we cannot tell
139       whether this is a single-byte file, or just a partially written gzip
140       file -- for here we assume that if a gzip file is being written, then
141       the header will be written in a single operation, so that reading a
142       single byte is sufficient indication that it is not a gzip file) */
143    if (strm->avail_in > 1 &&
144            strm->next_in[0] == 31 && strm->next_in[1] == 139) {
145        inflateReset(strm);
146        state->how = GZIP;
147        state->direct = 0;
148        return 0;
149    }
150
151    /* no gzip header -- if we were decoding gzip before, then this is trailing
152       garbage.  Ignore the trailing garbage and finish. */
153    if (state->direct == 0) {
154        strm->avail_in = 0;
155        state->eof = 1;
156        state->x.have = 0;
157        return 0;
158    }
159
160    /* doing raw i/o, copy any leftover input to output -- this assumes that
161       the output buffer is larger than the input buffer, which also assures
162       space for gzungetc() */
163    state->x.next = state->out;
164    if (strm->avail_in) {
165        memcpy(state->x.next, strm->next_in, strm->avail_in);
166        state->x.have = strm->avail_in;
167        strm->avail_in = 0;
168    }
169    state->how = COPY;
170    state->direct = 1;
171    return 0;
172}
173
174/* Decompress from input to the provided next_out and avail_out in the state.
175   On return, state->x.have and state->x.next point to the just decompressed
176   data.  If the gzip stream completes, state->how is reset to LOOK to look for
177   the next gzip stream or raw data, once state->x.have is depleted.  Returns 0
178   on success, -1 on failure. */
179local int gz_decomp(state)
180    gz_statep state;
181{
182    int ret = Z_OK;
183    unsigned had;
184    z_streamp strm = &(state->strm);
185
186    /* fill output buffer up to end of deflate stream */
187    had = strm->avail_out;
188    do {
189        /* get more input for inflate() */
190        if (strm->avail_in == 0 && gz_avail(state) == -1)
191            return -1;
192        if (strm->avail_in == 0) {
193            gz_error(state, Z_BUF_ERROR, "unexpected end of file");
194            break;
195        }
196
197        /* decompress and handle errors */
198        ret = inflate(strm, Z_NO_FLUSH);
199        if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
200            gz_error(state, Z_STREAM_ERROR,
201                     "internal error: inflate stream corrupt");
202            return -1;
203        }
204        if (ret == Z_MEM_ERROR) {
205            gz_error(state, Z_MEM_ERROR, "out of memory");
206            return -1;
207        }
208        if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
209            gz_error(state, Z_DATA_ERROR,
210                     strm->msg == NULL ? "compressed data error" : strm->msg);
211            return -1;
212        }
213    } while (strm->avail_out && ret != Z_STREAM_END);
214
215    /* update available output */
216    state->x.have = had - strm->avail_out;
217    state->x.next = strm->next_out - state->x.have;
218
219    /* if the gzip stream completed successfully, look for another */
220    if (ret == Z_STREAM_END)
221        state->how = LOOK;
222
223    /* good decompression */
224    return 0;
225}
226
227/* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
228   Data is either copied from the input file or decompressed from the input
229   file depending on state->how.  If state->how is LOOK, then a gzip header is
230   looked for to determine whether to copy or decompress.  Returns -1 on error,
231   otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the
232   end of the input file has been reached and all data has been processed.  */
233local int gz_fetch(state)
234    gz_statep state;
235{
236    z_streamp strm = &(state->strm);
237
238    do {
239        switch(state->how) {
240        case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */
241            if (gz_look(state) == -1)
242                return -1;
243            if (state->how == LOOK)
244                return 0;
245            break;
246        case COPY:      /* -> COPY */
247            if (gz_load(state, state->out, state->size << 1, &(state->x.have))
248                    == -1)
249                return -1;
250            state->x.next = state->out;
251            return 0;
252        case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */
253            strm->avail_out = state->size << 1;
254            strm->next_out = state->out;
255            if (gz_decomp(state) == -1)
256                return -1;
257        }
258    } while (state->x.have == 0 && (!state->eof || strm->avail_in));
259    return 0;
260}
261
262/* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
263local int gz_skip(state, len)
264    gz_statep state;
265    z_off64_t len;
266{
267    unsigned n;
268
269    /* skip over len bytes or reach end-of-file, whichever comes first */
270    while (len)
271        /* skip over whatever is in output buffer */
272        if (state->x.have) {
273            n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
274                (unsigned)len : state->x.have;
275            state->x.have -= n;
276            state->x.next += n;
277            state->x.pos += n;
278            len -= n;
279        }
280
281        /* output buffer empty -- return if we're at the end of the input */
282        else if (state->eof && state->strm.avail_in == 0)
283            break;
284
285        /* need more data to skip -- load up output buffer */
286        else {
287            /* get more output, looking for header if required */
288            if (gz_fetch(state) == -1)
289                return -1;
290        }
291    return 0;
292}
293
294/* -- see zlib.h -- */
295int ZEXPORT gzread(file, buf, len)
296    gzFile file;
297    voidp buf;
298    unsigned len;
299{
300    unsigned got, n;
301    gz_statep state;
302    z_streamp strm;
303
304    /* get internal structure */
305    if (file == NULL)
306        return -1;
307    state = (gz_statep)file;
308    strm = &(state->strm);
309
310    /* check that we're reading and that there's no (serious) error */
311    if (state->mode != GZ_READ ||
312            (state->err != Z_OK && state->err != Z_BUF_ERROR))
313        return -1;
314
315    /* since an int is returned, make sure len fits in one, otherwise return
316       with an error (this avoids the flaw in the interface) */
317    if ((int)len < 0) {
318        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
319        return -1;
320    }
321
322    /* if len is zero, avoid unnecessary operations */
323    if (len == 0)
324        return 0;
325
326    /* process a skip request */
327    if (state->seek) {
328        state->seek = 0;
329        if (gz_skip(state, state->skip) == -1)
330            return -1;
331    }
332
333    /* get len bytes to buf, or less than len if at the end */
334    got = 0;
335    do {
336        /* first just try copying data from the output buffer */
337        if (state->x.have) {
338            n = state->x.have > len ? len : state->x.have;
339            memcpy(buf, state->x.next, n);
340            state->x.next += n;
341            state->x.have -= n;
342        }
343
344        /* output buffer empty -- return if we're at the end of the input */
345        else if (state->eof && strm->avail_in == 0) {
346            state->past = 1;        /* tried to read past end */
347            break;
348        }
349
350        /* need output data -- for small len or new stream load up our output
351           buffer */
352        else if (state->how == LOOK || len < (state->size << 1)) {
353            /* get more output, looking for header if required */
354            if (gz_fetch(state) == -1)
355                return -1;
356            continue;       /* no progress yet -- go back to memcpy() above */
357            /* the copy above assures that we will leave with space in the
358               output buffer, allowing at least one gzungetc() to succeed */
359        }
360
361        /* large len -- read directly into user buffer */
362        else if (state->how == COPY) {      /* read directly */
363            if (gz_load(state, buf, len, &n) == -1)
364                return -1;
365        }
366
367        /* large len -- decompress directly into user buffer */
368        else {  /* state->how == GZIP */
369            strm->avail_out = len;
370            strm->next_out = buf;
371            if (gz_decomp(state) == -1)
372                return -1;
373            n = state->x.have;
374            state->x.have = 0;
375        }
376
377        /* update progress */
378        len -= n;
379        buf = (char *)buf + n;
380        got += n;
381        state->x.pos += n;
382    } while (len);
383
384    /* return number of bytes read into user buffer (will fit in int) */
385    return (int)got;
386}
387
388/* -- see zlib.h -- */
389int ZEXPORT gzgetc_(file)
390    gzFile file;
391{
392    int ret;
393    unsigned char buf[1];
394    gz_statep state;
395
396    /* get internal structure */
397    if (file == NULL)
398        return -1;
399    state = (gz_statep)file;
400
401    /* check that we're reading and that there's no (serious) error */
402    if (state->mode != GZ_READ ||
403        (state->err != Z_OK && state->err != Z_BUF_ERROR))
404        return -1;
405
406    /* try output buffer (no need to check for skip request) */
407    if (state->x.have) {
408        state->x.have--;
409        state->x.pos++;
410        return *(state->x.next)++;
411    }
412
413    /* nothing there -- try gzread() */
414    ret = gzread(file, buf, 1);
415    return ret < 1 ? -1 : buf[0];
416}
417
418#undef gzgetc
419int ZEXPORT gzgetc(file)
420gzFile file;
421{
422    return gzgetc_(file);
423}    
424
425/* -- see zlib.h -- */
426int ZEXPORT gzungetc(c, file)
427    int c;
428    gzFile file;
429{
430    gz_statep state;
431
432    /* get internal structure */
433    if (file == NULL)
434        return -1;
435    state = (gz_statep)file;
436
437    /* check that we're reading and that there's no (serious) error */
438    if (state->mode != GZ_READ ||
439        (state->err != Z_OK && state->err != Z_BUF_ERROR))
440        return -1;
441
442    /* process a skip request */
443    if (state->seek) {
444        state->seek = 0;
445        if (gz_skip(state, state->skip) == -1)
446            return -1;
447    }
448
449    /* can't push EOF */
450    if (c < 0)
451        return -1;
452
453    /* if output buffer empty, put byte at end (allows more pushing) */
454    if (state->x.have == 0) {
455        state->x.have = 1;
456        state->x.next = state->out + (state->size << 1) - 1;
457        state->x.next[0] = c;
458        state->x.pos--;
459        state->past = 0;
460        return c;
461    }
462
463    /* if no room, give up (must have already done a gzungetc()) */
464    if (state->x.have == (state->size << 1)) {
465        gz_error(state, Z_DATA_ERROR, "out of room to push characters");
466        return -1;
467    }
468
469    /* slide output data if needed and insert byte before existing data */
470    if (state->x.next == state->out) {
471        unsigned char *src = state->out + state->x.have;
472        unsigned char *dest = state->out + (state->size << 1);
473        while (src > state->out)
474            *--dest = *--src;
475        state->x.next = dest;
476    }
477    state->x.have++;
478    state->x.next--;
479    state->x.next[0] = c;
480    state->x.pos--;
481    state->past = 0;
482    return c;
483}
484
485/* -- see zlib.h -- */
486char * ZEXPORT gzgets(file, buf, len)
487    gzFile file;
488    char *buf;
489    int len;
490{
491    unsigned left, n;
492    char *str;
493    unsigned char *eol;
494    gz_statep state;
495
496    /* check parameters and get internal structure */
497    if (file == NULL || buf == NULL || len < 1)
498        return NULL;
499    state = (gz_statep)file;
500
501    /* check that we're reading and that there's no (serious) error */
502    if (state->mode != GZ_READ ||
503        (state->err != Z_OK && state->err != Z_BUF_ERROR))
504        return NULL;
505
506    /* process a skip request */
507    if (state->seek) {
508        state->seek = 0;
509        if (gz_skip(state, state->skip) == -1)
510            return NULL;
511    }
512
513    /* copy output bytes up to new line or len - 1, whichever comes first --
514       append a terminating zero to the string (we don't check for a zero in
515       the contents, let the user worry about that) */
516    str = buf;
517    left = (unsigned)len - 1;
518    if (left) do {
519        /* assure that something is in the output buffer */
520        if (state->x.have == 0 && gz_fetch(state) == -1)
521            return NULL;                /* error */
522        if (state->x.have == 0) {       /* end of file */
523            state->past = 1;            /* read past end */
524            break;                      /* return what we have */
525        }
526
527        /* look for end-of-line in current output buffer */
528        n = state->x.have > left ? left : state->x.have;
529        eol = memchr(state->x.next, '\n', n);
530        if (eol != NULL)
531            n = (unsigned)(eol - state->x.next) + 1;
532
533        /* copy through end-of-line, or remainder if not found */
534        memcpy(buf, state->x.next, n);
535        state->x.have -= n;
536        state->x.next += n;
537        state->x.pos += n;
538        left -= n;
539        buf += n;
540    } while (left && eol == NULL);
541
542    /* return terminated string, or if nothing, end of file */
543    if (buf == str)
544        return NULL;
545    buf[0] = 0;
546    return str;
547}
548
549/* -- see zlib.h -- */
550int ZEXPORT gzdirect(file)
551    gzFile file;
552{
553    gz_statep state;
554
555    /* get internal structure */
556    if (file == NULL)
557        return 0;
558    state = (gz_statep)file;
559
560    /* if the state is not known, but we can find out, then do so (this is
561       mainly for right after a gzopen() or gzdopen()) */
562    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
563        (void)gz_look(state);
564
565    /* return 1 if transparent, 0 if processing a gzip stream */
566    return state->direct;
567}
568
569/* -- see zlib.h -- */
570int ZEXPORT gzclose_r(file)
571    gzFile file;
572{
573    int ret, err;
574    gz_statep state;
575
576    /* get internal structure */
577    if (file == NULL)
578        return Z_STREAM_ERROR;
579    state = (gz_statep)file;
580
581    /* check that we're reading */
582    if (state->mode != GZ_READ)
583        return Z_STREAM_ERROR;
584
585    /* free memory and close file */
586    if (state->size) {
587        inflateEnd(&(state->strm));
588        free(state->out);
589        free(state->in);
590    }
591    err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
592    gz_error(state, Z_OK, NULL);
593    free(state->path);
594    ret = close(state->fd);
595    free(state);
596    return ret ? Z_ERRNO : err;
597}