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