Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/3rdparty/zlib/gzlib.c
16337 views
1
/* gzlib.c -- zlib functions common to reading and writing gzip files
2
* Copyright (C) 2004-2017 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__) && !defined(__MINGW32__)
9
# define LSEEK _lseeki64
10
#else
11
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
12
# define LSEEK lseek64
13
#else
14
# define LSEEK lseek
15
#endif
16
#endif
17
18
/* Local functions */
19
local void gz_reset OF((gz_statep));
20
local gzFile gz_open OF((const void *, int, const char *));
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. */
33
char 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 */
75
local void gz_reset(state)
76
gz_statep state;
77
{
78
state->x.have = 0; /* no output data available */
79
if (state->mode == GZ_READ) { /* for reading ... */
80
state->eof = 0; /* not at end of file */
81
state->past = 0; /* have not read past end yet */
82
state->how = LOOK; /* look for gzip header */
83
}
84
state->seek = 0; /* no seek request pending */
85
gz_error(state, Z_OK, NULL); /* clear error */
86
state->x.pos = 0; /* no uncompressed data yet */
87
state->strm.avail_in = 0; /* no input data yet */
88
}
89
90
/* Open a gzip file either by name or file descriptor. */
91
local gzFile gz_open(path, fd, mode)
92
const void *path;
93
int fd;
94
const char *mode;
95
{
96
gz_statep state;
97
z_size_t len;
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;
109
110
/* allocate gzFile structure to return */
111
state = (gz_statep)malloc(sizeof(gz_state));
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;
122
state->direct = 0;
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;
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
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;
165
break;
166
case 'T':
167
state->direct = 1;
168
break;
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
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
190
/* save the path name for error messages */
191
#ifdef WIDECHAR
192
if (fd == -2) {
193
len = wcstombs(NULL, path, 0);
194
if (len == (z_size_t)-1)
195
len = 0;
196
}
197
else
198
#endif
199
len = strlen((const char *)path);
200
state->path = (char *)malloc(len + 1);
201
if (state->path == NULL) {
202
free(state);
203
return NULL;
204
}
205
#ifdef WIDECHAR
206
if (fd == -2)
207
if (len)
208
wcstombs(state->path, path, len + 1);
209
else
210
*(state->path) = 0;
211
else
212
#endif
213
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
214
(void)snprintf(state->path, len + 1, "%s", (const char *)path);
215
#else
216
strcpy(state->path, path);
217
#endif
218
219
/* compute the flags for open() */
220
oflag =
221
#ifdef O_LARGEFILE
222
O_LARGEFILE |
223
#endif
224
#ifdef O_BINARY
225
O_BINARY |
226
#endif
227
#ifdef O_CLOEXEC
228
(cloexec ? O_CLOEXEC : 0) |
229
#endif
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 : (
242
#ifdef WIDECHAR
243
fd == -2 ? _wopen(path, oflag, 0666) :
244
#endif
245
open((const char *)path, oflag, 0666));
246
if (state->fd == -1) {
247
free(state->path);
248
free(state);
249
return NULL;
250
}
251
if (state->mode == GZ_APPEND) {
252
LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
253
state->mode = GZ_WRITE; /* simplify later checks */
254
}
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 -- */
270
gzFile 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 -- */
278
gzFile 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 -- */
286
gzFile ZEXPORT gzdopen(fd, mode)
287
int fd;
288
const char *mode;
289
{
290
char *path; /* identifier for error messages */
291
gzFile gz;
292
293
if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
294
return NULL;
295
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
296
(void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
297
#else
298
sprintf(path, "<fd:%d>", fd); /* for debugging */
299
#endif
300
gz = gz_open(path, fd, mode);
301
free(path);
302
return gz;
303
}
304
305
/* -- see zlib.h -- */
306
#ifdef WIDECHAR
307
gzFile 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
315
/* -- see zlib.h -- */
316
int 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 */
334
if ((size << 1) < size)
335
return -1; /* need to be able to double it */
336
if (size < 2)
337
size = 2; /* need two bytes to check magic header */
338
state->want = size;
339
return 0;
340
}
341
342
/* -- see zlib.h -- */
343
int 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 */
354
if (state->mode != GZ_READ ||
355
(state->err != Z_OK && state->err != Z_BUF_ERROR))
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 -- */
366
z_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 */
383
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
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)
392
offset -= state->x.pos;
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 &&
399
state->x.pos + offset >= 0) {
400
ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
401
if (ret == -1)
402
return -1;
403
state->x.have = 0;
404
state->eof = 0;
405
state->past = 0;
406
state->seek = 0;
407
gz_error(state, Z_OK, NULL);
408
state->strm.avail_in = 0;
409
state->x.pos += offset;
410
return state->x.pos;
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;
417
offset += state->x.pos;
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) {
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;
431
offset -= n;
432
}
433
434
/* request skip (if not zero) */
435
if (offset) {
436
state->seek = 1;
437
state->skip = offset;
438
}
439
return state->x.pos + offset;
440
}
441
442
/* -- see zlib.h -- */
443
z_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 -- */
455
z_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 */
468
return state->x.pos + (state->seek ? state->skip : 0);
469
}
470
471
/* -- see zlib.h -- */
472
z_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 -- */
482
z_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 -- */
505
z_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 -- */
515
int 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 */
528
return state->mode == GZ_READ ? state->past : 0;
529
}
530
531
/* -- see zlib.h -- */
532
const 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;
548
return state->err == Z_MEM_ERROR ? "out of memory" :
549
(state->msg == NULL ? "" : state->msg);
550
}
551
552
/* -- see zlib.h -- */
553
void 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 */
566
if (state->mode == GZ_READ) {
567
state->eof = 0;
568
state->past = 0;
569
}
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. */
579
void 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
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
595
/* set error code, and if no message, then done */
596
state->err = err;
597
if (msg == NULL)
598
return;
599
600
/* for an out of memory error, return literal string when requested */
601
if (err == Z_MEM_ERROR)
602
return;
603
604
/* construct error message with path */
605
if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
606
NULL) {
607
state->err = Z_MEM_ERROR;
608
return;
609
}
610
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
611
(void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
612
"%s%s%s", state->path, ": ", msg);
613
#else
614
strcpy(state->msg, state->path);
615
strcat(state->msg, ": ");
616
strcat(state->msg, msg);
617
#endif
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 */
625
unsigned 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
638
639