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