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