PageRenderTime 42ms CodeModel.GetById 13ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/ZLib/gzlib.c

https://bitbucket.org/cabalistic/ogredeps/
C | 574 lines | 418 code | 72 blank | 84 comment | 153 complexity | 7237497e306b58e8cfce97525dee7f98 MD5 | raw file
  1/* gzlib.c -- zlib functions common to reading and writing gzip files
  2 * Copyright (C) 2004, 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#if defined(_WIN32) && !defined(__BORLANDC__)
 18#  define LSEEK _lseeki64
 19#else
 20#  include <unistd.h>
 21#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
 22#  define LSEEK lseek64
 23#else
 24#  define LSEEK lseek
 25#endif
 26#endif
 27
 28/* Local functions */
 29local void gz_reset OF((gz_statep));
 30local gzFile gz_open OF((const char *, int, const char *));
 31
 32#if defined UNDER_CE
 33
 34/* Map the Windows error number in ERROR to a locale-dependent error message
 35   string and return a pointer to it.  Typically, the values for ERROR come
 36   from GetLastError.
 37
 38   The string pointed to shall not be modified by the application, but may be
 39   overwritten by a subsequent call to gz_strwinerror
 40
 41   The gz_strwinerror function does not change the current setting of
 42   GetLastError. */
 43char ZLIB_INTERNAL *gz_strwinerror (error)
 44     DWORD error;
 45{
 46    static char buf[1024];
 47
 48    wchar_t *msgbuf;
 49    DWORD lasterr = GetLastError();
 50    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
 51        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
 52        NULL,
 53        error,
 54        0, /* Default language */
 55        (LPVOID)&msgbuf,
 56        0,
 57        NULL);
 58    if (chars != 0) {
 59        /* If there is an \r\n appended, zap it.  */
 60        if (chars >= 2
 61            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
 62            chars -= 2;
 63            msgbuf[chars] = 0;
 64        }
 65
 66        if (chars > sizeof (buf) - 1) {
 67            chars = sizeof (buf) - 1;
 68            msgbuf[chars] = 0;
 69        }
 70
 71        wcstombs(buf, msgbuf, chars + 1);
 72        LocalFree(msgbuf);
 73    }
 74    else {
 75        sprintf(buf, "unknown win32 error (%ld)", error);
 76    }
 77
 78    SetLastError(lasterr);
 79    return buf;
 80}
 81
 82#endif /* UNDER_CE */
 83
 84/* Reset gzip file state */
 85local void gz_reset(state)
 86    gz_statep state;
 87{
 88    state->x.have = 0;              /* no output data available */
 89    if (state->mode == GZ_READ) {   /* for reading ... */
 90        state->eof = 0;             /* not at end of file */
 91        state->past = 0;            /* have not read past end yet */
 92        state->how = LOOK;          /* look for gzip header */
 93    }
 94    state->seek = 0;                /* no seek request pending */
 95    gz_error(state, Z_OK, NULL);    /* clear error */
 96    state->x.pos = 0;               /* no uncompressed data yet */
 97    state->strm.avail_in = 0;       /* no input data yet */
 98}
 99
100/* Open a gzip file either by name or file descriptor. */
101local gzFile gz_open(path, fd, mode)
102    const char *path;
103    int fd;
104    const char *mode;
105{
106    gz_statep state;
107
108    /* check input */
109    if (path == NULL)
110        return NULL;
111
112    /* allocate gzFile structure to return */
113    state = malloc(sizeof(gz_state));
114    if (state == NULL)
115        return NULL;
116    state->size = 0;            /* no buffers allocated yet */
117    state->want = GZBUFSIZE;    /* requested buffer size */
118    state->msg = NULL;          /* no error message yet */
119
120    /* interpret mode */
121    state->mode = GZ_NONE;
122    state->level = Z_DEFAULT_COMPRESSION;
123    state->strategy = Z_DEFAULT_STRATEGY;
124    state->direct = 0;
125    while (*mode) {
126        if (*mode >= '0' && *mode <= '9')
127            state->level = *mode - '0';
128        else
129            switch (*mode) {
130            case 'r':
131                state->mode = GZ_READ;
132                break;
133#ifndef NO_GZCOMPRESS
134            case 'w':
135                state->mode = GZ_WRITE;
136                break;
137            case 'a':
138                state->mode = GZ_APPEND;
139                break;
140#endif
141            case '+':       /* can't read and write at the same time */
142                free(state);
143                return NULL;
144            case 'b':       /* ignore -- will request binary anyway */
145                break;
146            case 'f':
147                state->strategy = Z_FILTERED;
148                break;
149            case 'h':
150                state->strategy = Z_HUFFMAN_ONLY;
151                break;
152            case 'R':
153                state->strategy = Z_RLE;
154                break;
155            case 'F':
156                state->strategy = Z_FIXED;
157            case 'T':
158                state->direct = 1;
159            default:        /* could consider as an error, but just ignore */
160                ;
161            }
162        mode++;
163    }
164
165    /* must provide an "r", "w", or "a" */
166    if (state->mode == GZ_NONE) {
167        free(state);
168        return NULL;
169    }
170
171    /* can't force transparent read */
172    if (state->mode == GZ_READ) {
173        if (state->direct) {
174            free(state);
175            return NULL;
176        }
177        state->direct = 1;      /* for empty file */
178    }
179
180    /* save the path name for error messages */
181    state->path = malloc(strlen(path) + 1);
182    if (state->path == NULL) {
183        free(state);
184        return NULL;
185    }
186    strcpy(state->path, path);
187
188    /* open the file with the appropriate mode (or just use fd) */
189    state->fd = fd != -1 ? fd :
190        open(path,
191#ifdef O_LARGEFILE
192            O_LARGEFILE |
193#endif
194#ifdef O_BINARY
195            O_BINARY |
196#endif
197            (state->mode == GZ_READ ?
198                O_RDONLY :
199                (O_WRONLY | O_CREAT | (
200                    state->mode == GZ_WRITE ?
201                        O_TRUNC :
202                        O_APPEND))),
203            0666);
204    if (state->fd == -1) {
205        free(state->path);
206        free(state);
207        return NULL;
208    }
209    if (state->mode == GZ_APPEND)
210        state->mode = GZ_WRITE;         /* simplify later checks */
211
212    /* save the current position for rewinding (only if reading) */
213    if (state->mode == GZ_READ) {
214        state->start = LSEEK(state->fd, 0, SEEK_CUR);
215        if (state->start == -1) state->start = 0;
216    }
217
218    /* initialize stream */
219    gz_reset(state);
220
221    /* return stream */
222    return (gzFile)state;
223}
224
225/* -- see zlib.h -- */
226gzFile ZEXPORT gzopen(path, mode)
227    const char *path;
228    const char *mode;
229{
230    return gz_open(path, -1, mode);
231}
232
233/* -- see zlib.h -- */
234gzFile ZEXPORT gzopen64(path, mode)
235    const char *path;
236    const char *mode;
237{
238    return gz_open(path, -1, mode);
239}
240
241/* -- see zlib.h -- */
242gzFile ZEXPORT gzdopen(fd, mode)
243    int fd;
244    const char *mode;
245{
246    char *path;         /* identifier for error messages */
247    gzFile gz;
248
249    if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
250        return NULL;
251    sprintf(path, "<fd:%d>", fd);   /* for debugging */
252    gz = gz_open(path, fd, mode);
253    free(path);
254    return gz;
255}
256
257/* -- see zlib.h -- */
258int ZEXPORT gzbuffer(file, size)
259    gzFile file;
260    unsigned size;
261{
262    gz_statep state;
263
264    /* get internal structure and check integrity */
265    if (file == NULL)
266        return -1;
267    state = (gz_statep)file;
268    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
269        return -1;
270
271    /* make sure we haven't already allocated memory */
272    if (state->size != 0)
273        return -1;
274
275    /* check and set requested size */
276    if (size < 2)
277        size = 2;               /* need two bytes to check magic header */
278    state->want = size;
279    return 0;
280}
281
282/* -- see zlib.h -- */
283int ZEXPORT gzrewind(file)
284    gzFile file;
285{
286    gz_statep state;
287
288    /* get internal structure */
289    if (file == NULL)
290        return -1;
291    state = (gz_statep)file;
292
293    /* check that we're reading and that there's no error */
294    if (state->mode != GZ_READ ||
295            (state->err != Z_OK && state->err != Z_BUF_ERROR))
296        return -1;
297
298    /* back up and start over */
299    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
300        return -1;
301    gz_reset(state);
302    return 0;
303}
304
305/* -- see zlib.h -- */
306z_off64_t ZEXPORT gzseek64(file, offset, whence)
307    gzFile file;
308    z_off64_t offset;
309    int whence;
310{
311    unsigned n;
312    z_off64_t ret;
313    gz_statep state;
314
315    /* get internal structure and check integrity */
316    if (file == NULL)
317        return -1;
318    state = (gz_statep)file;
319    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
320        return -1;
321
322    /* check that there's no error */
323    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
324        return -1;
325
326    /* can only seek from start or relative to current position */
327    if (whence != SEEK_SET && whence != SEEK_CUR)
328        return -1;
329
330    /* normalize offset to a SEEK_CUR specification */
331    if (whence == SEEK_SET)
332        offset -= state->x.pos;
333    else if (state->seek)
334        offset += state->skip;
335    state->seek = 0;
336
337    /* if within raw area while reading, just go there */
338    if (state->mode == GZ_READ && state->how == COPY &&
339            state->x.pos + offset >= 0) {
340        ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
341        if (ret == -1)
342            return -1;
343        state->x.have = 0;
344        state->eof = 0;
345        state->past = 0;
346        state->seek = 0;
347        gz_error(state, Z_OK, NULL);
348        state->strm.avail_in = 0;
349        state->x.pos += offset;
350        return state->x.pos;
351    }
352
353    /* calculate skip amount, rewinding if needed for back seek when reading */
354    if (offset < 0) {
355        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
356            return -1;
357        offset += state->x.pos;
358        if (offset < 0)                     /* before start of file! */
359            return -1;
360        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
361            return -1;
362    }
363
364    /* if reading, skip what's in output buffer (one less gzgetc() check) */
365    if (state->mode == GZ_READ) {
366        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
367            (unsigned)offset : state->x.have;
368        state->x.have -= n;
369        state->x.next += n;
370        state->x.pos += n;
371        offset -= n;
372    }
373
374    /* request skip (if not zero) */
375    if (offset) {
376        state->seek = 1;
377        state->skip = offset;
378    }
379    return state->x.pos + offset;
380}
381
382/* -- see zlib.h -- */
383z_off_t ZEXPORT gzseek(file, offset, whence)
384    gzFile file;
385    z_off_t offset;
386    int whence;
387{
388    z_off64_t ret;
389
390    ret = gzseek64(file, (z_off64_t)offset, whence);
391    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
392}
393
394/* -- see zlib.h -- */
395z_off64_t ZEXPORT gztell64(file)
396    gzFile file;
397{
398    gz_statep state;
399
400    /* get internal structure and check integrity */
401    if (file == NULL)
402        return -1;
403    state = (gz_statep)file;
404    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
405        return -1;
406
407    /* return position */
408    return state->x.pos + (state->seek ? state->skip : 0);
409}
410
411/* -- see zlib.h -- */
412z_off_t ZEXPORT gztell(file)
413    gzFile file;
414{
415    z_off64_t ret;
416
417    ret = gztell64(file);
418    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
419}
420
421/* -- see zlib.h -- */
422z_off64_t ZEXPORT gzoffset64(file)
423    gzFile file;
424{
425    z_off64_t offset;
426    gz_statep state;
427
428    /* get internal structure and check integrity */
429    if (file == NULL)
430        return -1;
431    state = (gz_statep)file;
432    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
433        return -1;
434
435    /* compute and return effective offset in file */
436    offset = LSEEK(state->fd, 0, SEEK_CUR);
437    if (offset == -1)
438        return -1;
439    if (state->mode == GZ_READ)             /* reading */
440        offset -= state->strm.avail_in;     /* don't count buffered input */
441    return offset;
442}
443
444/* -- see zlib.h -- */
445z_off_t ZEXPORT gzoffset(file)
446    gzFile file;
447{
448    z_off64_t ret;
449
450    ret = gzoffset64(file);
451    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
452}
453
454/* -- see zlib.h -- */
455int ZEXPORT gzeof(file)
456    gzFile file;
457{
458    gz_statep state;
459
460    /* get internal structure and check integrity */
461    if (file == NULL)
462        return 0;
463    state = (gz_statep)file;
464    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
465        return 0;
466
467    /* return end-of-file state */
468    return state->mode == GZ_READ ? state->past : 0;
469}
470
471/* -- see zlib.h -- */
472const char * ZEXPORT gzerror(file, errnum)
473    gzFile file;
474    int *errnum;
475{
476    gz_statep state;
477
478    /* get internal structure and check integrity */
479    if (file == NULL)
480        return NULL;
481    state = (gz_statep)file;
482    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
483        return NULL;
484
485    /* return error information */
486    if (errnum != NULL)
487        *errnum = state->err;
488    return state->msg == NULL ? "" : state->msg;
489}
490
491/* -- see zlib.h -- */
492void ZEXPORT gzclearerr(file)
493    gzFile file;
494{
495    gz_statep state;
496
497    /* get internal structure and check integrity */
498    if (file == NULL)
499        return;
500    state = (gz_statep)file;
501    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
502        return;
503
504    /* clear error and end-of-file */
505    if (state->mode == GZ_READ) {
506        state->eof = 0;
507        state->past = 0;
508    }
509    gz_error(state, Z_OK, NULL);
510}
511
512/* Create an error message in allocated memory and set state->err and
513   state->msg accordingly.  Free any previous error message already there.  Do
514   not try to free or allocate space if the error is Z_MEM_ERROR (out of
515   memory).  Simply save the error message as a static string.  If there is an
516   allocation failure constructing the error message, then convert the error to
517   out of memory. */
518void ZLIB_INTERNAL gz_error(state, err, msg)
519    gz_statep state;
520    int err;
521    const char *msg;
522{
523    /* free previously allocated message and clear */
524    if (state->msg != NULL) {
525        if (state->err != Z_MEM_ERROR)
526            free(state->msg);
527        state->msg = NULL;
528    }
529
530    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
531    if (err != Z_OK && err != Z_BUF_ERROR)
532        state->x.have = 0;
533
534    /* set error code, and if no message, then done */
535    state->err = err;
536    if (msg == NULL)
537        return;
538
539    /* for an out of memory error, save as static string */
540    if (err == Z_MEM_ERROR) {
541        state->msg = (char *)msg;
542        return;
543    }
544
545    /* construct error message with path */
546    if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
547        state->err = Z_MEM_ERROR;
548        state->msg = (char *)"out of memory";
549        return;
550    }
551    strcpy(state->msg, state->path);
552    strcat(state->msg, ": ");
553    strcat(state->msg, msg);
554    return;
555}
556
557#ifndef INT_MAX
558/* portably return maximum value for an int (when limits.h presumed not
559   available) -- we need to do this to cover cases where 2's complement not
560   used, since C standard permits 1's complement and sign-bit representations,
561   otherwise we could just use ((unsigned)-1) >> 1 */
562unsigned ZLIB_INTERNAL gz_intmax()
563{
564    unsigned p, q;
565
566    p = 1;
567    do {
568        q = p;
569        p <<= 1;
570        p++;
571    } while (p > q);
572    return q >> 1;
573}
574#endif