source: rtems/cpukit/zlib/gzlib.c @ b40c451

4.115
Last change on this file since b40c451 was b40c451, checked in by cvs2git <rtems-devel@…>, on 03/18/11 at 10:11:30

This commit was manufactured by cvs2svn to create branch 'zlib'.

Cherrypick from master 2011-03-18 10:11:29 UTC Joel Sherrill <joel.sherrill@…> '2010-03-22 Joel Sherrill <joel.sherrill@…>':

cpukit/zlib/doc/algorithm.txt
cpukit/zlib/gzclose.c
cpukit/zlib/gzguts.h
cpukit/zlib/gzlib.c
cpukit/zlib/gzread.c
cpukit/zlib/gzwrite.c

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