Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/zstd/zlibWrapper/gzlib.c
48254 views
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
5
* Copyright (C) 2004-2017 Mark Adler
6
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
7
*/
8
9
#include "gzguts.h"
10
11
#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
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 */
22
local void gz_reset OF((gz_statep));
23
local 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. */
36
char 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 */
78
local 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. */
94
local gzFile gz_open(path, fd, mode)
95
const void *path;
96
int fd;
97
const char *mode;
98
{
99
gz_statep state;
100
z_size_t len;
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 */
114
state.state = (gz_state*)malloc(sizeof(gz_state));
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 */
194
#ifdef WIDECHAR
195
if (fd == -2) {
196
len = wcstombs(NULL, path, 0);
197
if (len == (z_size_t)-1)
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
}
208
#ifdef WIDECHAR
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)
217
(void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
218
#else
219
strcpy(state.state->path, (const char*)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 : (
245
#ifdef WIDECHAR
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
}
254
if (state.state->mode == GZ_APPEND) {
255
LSEEK(state.state->fd, 0, SEEK_END); /* so gzoffset() is correct */
256
state.state->mode = GZ_WRITE; /* simplify later checks */
257
}
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 */
269
return state.file;
270
}
271
272
/* -- see zlib.h -- */
273
gzFile 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 -- */
281
gzFile 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 -- */
289
gzFile 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)
299
(void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
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 -- */
309
#ifdef WIDECHAR
310
gzFile 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 -- */
319
int 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.file = 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 */
337
if ((size << 1) < size)
338
return -1; /* need to be able to double it */
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 -- */
346
int 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.file = 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 -- */
369
z_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.file = 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 -- */
446
z_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 -- */
458
z_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.file = 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 -- */
475
z_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 -- */
485
z_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.file = 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 -- */
508
z_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 -- */
518
int 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.file = 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 -- */
535
const 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.file = 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 -- */
556
void 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.file = 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
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
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. */
582
void 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
594
/* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */
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)
614
(void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
615
"%s%s%s", state.state->path, ": ", msg);
616
#else
617
strcpy(state.state->msg, state.state->path);
618
strcat(state.state->msg, ": ");
619
strcat(state.state->msg, msg);
620
#endif
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 */
628
unsigned 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
641
642