Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmzlib/gzread.c
3150 views
1
/* gzread.c -- zlib functions for reading 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
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
9
state->fd, and update state->eof, state->err, and state->msg as appropriate.
10
This function needs to loop on read(), since read() is not guaranteed to
11
read the number of bytes requested, depending on the type of descriptor. */
12
local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
13
unsigned *have) {
14
int ret;
15
unsigned get, max = ((unsigned)-1 >> 2) + 1;
16
17
*have = 0;
18
do {
19
get = len - *have;
20
if (get > max)
21
get = max;
22
ret = read(state->fd, buf + *have, get);
23
if (ret <= 0)
24
break;
25
*have += (unsigned)ret;
26
} while (*have < len);
27
if (ret < 0) {
28
gz_error(state, Z_ERRNO, zstrerror());
29
return -1;
30
}
31
if (ret == 0)
32
state->eof = 1;
33
return 0;
34
}
35
36
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
37
error, 0 otherwise. Note that the eof flag is set when the end of the input
38
file is reached, even though there may be unused data in the buffer. Once
39
that data has been used, no more attempts will be made to read the file.
40
If strm->avail_in != 0, then the current data is moved to the beginning of
41
the input buffer, and then the remainder of the buffer is loaded with the
42
available data from the input file. */
43
local int gz_avail(gz_statep state) {
44
unsigned got;
45
z_streamp strm = &(state->strm);
46
47
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
48
return -1;
49
if (state->eof == 0) {
50
if (strm->avail_in) { /* copy what's there to the start */
51
unsigned char *p = state->in;
52
unsigned const char *q = strm->next_in;
53
unsigned n = strm->avail_in;
54
do {
55
*p++ = *q++;
56
} while (--n);
57
}
58
if (gz_load(state, state->in + strm->avail_in,
59
state->size - strm->avail_in, &got) == -1)
60
return -1;
61
strm->avail_in += got;
62
strm->next_in = state->in;
63
}
64
return 0;
65
}
66
67
/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
68
If this is the first time in, allocate required memory. state->how will be
69
left unchanged if there is no more input data available, will be set to COPY
70
if there is no gzip header and direct copying will be performed, or it will
71
be set to GZIP for decompression. If direct copying, then leftover input
72
data from the input buffer will be copied to the output buffer. In that
73
case, all further file reads will be directly to either the output buffer or
74
a user buffer. If decompressing, the inflate state will be initialized.
75
gz_look() will return 0 on success or -1 on failure. */
76
local int gz_look(gz_statep state) {
77
z_streamp strm = &(state->strm);
78
79
/* allocate read buffers and inflate memory */
80
if (state->size == 0) {
81
/* allocate buffers */
82
state->in = (unsigned char *)malloc(state->want);
83
state->out = (unsigned char *)malloc(state->want << 1);
84
if (state->in == NULL || state->out == NULL) {
85
free(state->out);
86
free(state->in);
87
gz_error(state, Z_MEM_ERROR, "out of memory");
88
return -1;
89
}
90
state->size = state->want;
91
92
/* allocate inflate memory */
93
state->strm.zalloc = Z_NULL;
94
state->strm.zfree = Z_NULL;
95
state->strm.opaque = Z_NULL;
96
state->strm.avail_in = 0;
97
state->strm.next_in = Z_NULL;
98
if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
99
free(state->out);
100
free(state->in);
101
state->size = 0;
102
gz_error(state, Z_MEM_ERROR, "out of memory");
103
return -1;
104
}
105
}
106
107
/* get at least the magic bytes in the input buffer */
108
if (strm->avail_in < 2) {
109
if (gz_avail(state) == -1)
110
return -1;
111
if (strm->avail_in == 0)
112
return 0;
113
}
114
115
/* look for gzip magic bytes -- if there, do gzip decoding (note: there is
116
a logical dilemma here when considering the case of a partially written
117
gzip file, to wit, if a single 31 byte is written, then we cannot tell
118
whether this is a single-byte file, or just a partially written gzip
119
file -- for here we assume that if a gzip file is being written, then
120
the header will be written in a single operation, so that reading a
121
single byte is sufficient indication that it is not a gzip file) */
122
if (strm->avail_in > 1 &&
123
strm->next_in[0] == 31 && strm->next_in[1] == 139) {
124
inflateReset(strm);
125
state->how = GZIP;
126
state->direct = 0;
127
return 0;
128
}
129
130
/* no gzip header -- if we were decoding gzip before, then this is trailing
131
garbage. Ignore the trailing garbage and finish. */
132
if (state->direct == 0) {
133
strm->avail_in = 0;
134
state->eof = 1;
135
state->x.have = 0;
136
return 0;
137
}
138
139
/* doing raw i/o, copy any leftover input to output -- this assumes that
140
the output buffer is larger than the input buffer, which also assures
141
space for gzungetc() */
142
state->x.next = state->out;
143
memcpy(state->x.next, strm->next_in, strm->avail_in);
144
state->x.have = strm->avail_in;
145
strm->avail_in = 0;
146
state->how = COPY;
147
state->direct = 1;
148
return 0;
149
}
150
151
/* Decompress from input to the provided next_out and avail_out in the state.
152
On return, state->x.have and state->x.next point to the just decompressed
153
data. If the gzip stream completes, state->how is reset to LOOK to look for
154
the next gzip stream or raw data, once state->x.have is depleted. Returns 0
155
on success, -1 on failure. */
156
local int gz_decomp(gz_statep state) {
157
int ret = Z_OK;
158
unsigned had;
159
z_streamp strm = &(state->strm);
160
161
/* fill output buffer up to end of deflate stream */
162
had = strm->avail_out;
163
do {
164
/* get more input for inflate() */
165
if (strm->avail_in == 0 && gz_avail(state) == -1)
166
return -1;
167
if (strm->avail_in == 0) {
168
gz_error(state, Z_BUF_ERROR, "unexpected end of file");
169
break;
170
}
171
172
/* decompress and handle errors */
173
ret = inflate(strm, Z_NO_FLUSH);
174
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
175
gz_error(state, Z_STREAM_ERROR,
176
"internal error: inflate stream corrupt");
177
return -1;
178
}
179
if (ret == Z_MEM_ERROR) {
180
gz_error(state, Z_MEM_ERROR, "out of memory");
181
return -1;
182
}
183
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
184
gz_error(state, Z_DATA_ERROR,
185
strm->msg == NULL ? "compressed data error" : strm->msg);
186
return -1;
187
}
188
} while (strm->avail_out && ret != Z_STREAM_END);
189
190
/* update available output */
191
state->x.have = had - strm->avail_out;
192
state->x.next = strm->next_out - state->x.have;
193
194
/* if the gzip stream completed successfully, look for another */
195
if (ret == Z_STREAM_END)
196
state->how = LOOK;
197
198
/* good decompression */
199
return 0;
200
}
201
202
/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
203
Data is either copied from the input file or decompressed from the input
204
file depending on state->how. If state->how is LOOK, then a gzip header is
205
looked for to determine whether to copy or decompress. Returns -1 on error,
206
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
207
end of the input file has been reached and all data has been processed. */
208
local int gz_fetch(gz_statep state) {
209
z_streamp strm = &(state->strm);
210
211
do {
212
switch(state->how) {
213
case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
214
if (gz_look(state) == -1)
215
return -1;
216
if (state->how == LOOK)
217
return 0;
218
break;
219
case COPY: /* -> COPY */
220
if (gz_load(state, state->out, state->size << 1, &(state->x.have))
221
== -1)
222
return -1;
223
state->x.next = state->out;
224
return 0;
225
case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
226
strm->avail_out = state->size << 1;
227
strm->next_out = state->out;
228
if (gz_decomp(state) == -1)
229
return -1;
230
}
231
} while (state->x.have == 0 && (!state->eof || strm->avail_in));
232
return 0;
233
}
234
235
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
236
local int gz_skip(gz_statep state, z_off64_t len) {
237
unsigned n;
238
239
/* skip over len bytes or reach end-of-file, whichever comes first */
240
while (len)
241
/* skip over whatever is in output buffer */
242
if (state->x.have) {
243
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
244
(unsigned)len : state->x.have;
245
state->x.have -= n;
246
state->x.next += n;
247
state->x.pos += n;
248
len -= n;
249
}
250
251
/* output buffer empty -- return if we're at the end of the input */
252
else if (state->eof && state->strm.avail_in == 0)
253
break;
254
255
/* need more data to skip -- load up output buffer */
256
else {
257
/* get more output, looking for header if required */
258
if (gz_fetch(state) == -1)
259
return -1;
260
}
261
return 0;
262
}
263
264
/* Read len bytes into buf from file, or less than len up to the end of the
265
input. Return the number of bytes read. If zero is returned, either the
266
end of file was reached, or there was an error. state->err must be
267
consulted in that case to determine which. */
268
local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
269
z_size_t got;
270
unsigned n;
271
272
/* if len is zero, avoid unnecessary operations */
273
if (len == 0)
274
return 0;
275
276
/* process a skip request */
277
if (state->seek) {
278
state->seek = 0;
279
if (gz_skip(state, state->skip) == -1)
280
return 0;
281
}
282
283
/* get len bytes to buf, or less than len if at the end */
284
got = 0;
285
do {
286
/* set n to the maximum amount of len that fits in an unsigned int */
287
n = (unsigned)-1;
288
if (n > len)
289
n = (unsigned)len;
290
291
/* first just try copying data from the output buffer */
292
if (state->x.have) {
293
if (state->x.have < n)
294
n = state->x.have;
295
memcpy(buf, state->x.next, n);
296
state->x.next += n;
297
state->x.have -= n;
298
}
299
300
/* output buffer empty -- return if we're at the end of the input */
301
else if (state->eof && state->strm.avail_in == 0) {
302
state->past = 1; /* tried to read past end */
303
break;
304
}
305
306
/* need output data -- for small len or new stream load up our output
307
buffer */
308
else if (state->how == LOOK || n < (state->size << 1)) {
309
/* get more output, looking for header if required */
310
if (gz_fetch(state) == -1)
311
return 0;
312
continue; /* no progress yet -- go back to copy above */
313
/* the copy above assures that we will leave with space in the
314
output buffer, allowing at least one gzungetc() to succeed */
315
}
316
317
/* large len -- read directly into user buffer */
318
else if (state->how == COPY) { /* read directly */
319
if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
320
return 0;
321
}
322
323
/* large len -- decompress directly into user buffer */
324
else { /* state->how == GZIP */
325
state->strm.avail_out = n;
326
state->strm.next_out = (unsigned char *)buf;
327
if (gz_decomp(state) == -1)
328
return 0;
329
n = state->x.have;
330
state->x.have = 0;
331
}
332
333
/* update progress */
334
len -= n;
335
buf = (char *)buf + n;
336
got += n;
337
state->x.pos += n;
338
} while (len);
339
340
/* return number of bytes read into user buffer */
341
return got;
342
}
343
344
/* -- see zlib.h -- */
345
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
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 (serious) error */
354
if (state->mode != GZ_READ ||
355
(state->err != Z_OK && state->err != Z_BUF_ERROR))
356
return -1;
357
358
/* since an int is returned, make sure len fits in one, otherwise return
359
with an error (this avoids a flaw in the interface) */
360
if ((int)len < 0) {
361
gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
362
return -1;
363
}
364
365
/* read len or fewer bytes to buf */
366
len = (unsigned)gz_read(state, buf, len);
367
368
/* check for an error */
369
if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
370
return -1;
371
372
/* return the number of bytes read (this is assured to fit in an int) */
373
return (int)len;
374
}
375
376
/* -- see zlib.h -- */
377
z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) {
378
z_size_t len;
379
gz_statep state;
380
381
/* get internal structure */
382
if (file == NULL)
383
return 0;
384
state = (gz_statep)file;
385
386
/* check that we're reading and that there's no (serious) error */
387
if (state->mode != GZ_READ ||
388
(state->err != Z_OK && state->err != Z_BUF_ERROR))
389
return 0;
390
391
/* compute bytes to read -- error on overflow */
392
len = nitems * size;
393
if (size && len / size != nitems) {
394
gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
395
return 0;
396
}
397
398
#ifdef __clang_analyzer__
399
/* clang-analyzer does not see size==0 through len==0 below. */
400
if (!size)
401
return 0;
402
#endif
403
404
/* read len or fewer bytes to buf, return the number of full items read */
405
return len ? gz_read(state, buf, len) / size : 0;
406
}
407
408
/* -- see zlib.h -- */
409
#ifdef Z_PREFIX_SET
410
# undef z_gzgetc
411
#elif 1 /* Hook for mangling inside CMake. */
412
# undef cm_zlib_gzgetc
413
#else
414
# undef gzgetc
415
#endif
416
int ZEXPORT gzgetc(gzFile file) {
417
unsigned char buf[1];
418
gz_statep state;
419
420
/* get internal structure */
421
if (file == NULL)
422
return -1;
423
state = (gz_statep)file;
424
425
/* check that we're reading and that there's no (serious) error */
426
if (state->mode != GZ_READ ||
427
(state->err != Z_OK && state->err != Z_BUF_ERROR))
428
return -1;
429
430
/* try output buffer (no need to check for skip request) */
431
if (state->x.have) {
432
state->x.have--;
433
state->x.pos++;
434
return *(state->x.next)++;
435
}
436
437
/* nothing there -- try gz_read() */
438
return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
439
}
440
441
int ZEXPORT gzgetc_(gzFile file) {
442
return gzgetc(file);
443
}
444
445
/* -- see zlib.h -- */
446
int ZEXPORT gzungetc(int c, gzFile file) {
447
gz_statep state;
448
449
/* get internal structure */
450
if (file == NULL)
451
return -1;
452
state = (gz_statep)file;
453
454
/* in case this was just opened, set up the input buffer */
455
if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
456
(void)gz_look(state);
457
458
/* check that we're reading and that there's no (serious) error */
459
if (state->mode != GZ_READ ||
460
(state->err != Z_OK && state->err != Z_BUF_ERROR))
461
return -1;
462
463
/* process a skip request */
464
if (state->seek) {
465
state->seek = 0;
466
if (gz_skip(state, state->skip) == -1)
467
return -1;
468
}
469
470
/* can't push EOF */
471
if (c < 0)
472
return -1;
473
474
/* if output buffer empty, put byte at end (allows more pushing) */
475
if (state->x.have == 0) {
476
state->x.have = 1;
477
state->x.next = state->out + (state->size << 1) - 1;
478
state->x.next[0] = (unsigned char)c;
479
state->x.pos--;
480
state->past = 0;
481
return c;
482
}
483
484
/* if no room, give up (must have already done a gzungetc()) */
485
if (state->x.have == (state->size << 1)) {
486
gz_error(state, Z_DATA_ERROR, "out of room to push characters");
487
return -1;
488
}
489
490
/* slide output data if needed and insert byte before existing data */
491
if (state->x.next == state->out) {
492
unsigned char *src = state->out + state->x.have;
493
unsigned char *dest = state->out + (state->size << 1);
494
while (src > state->out)
495
*--dest = *--src;
496
state->x.next = dest;
497
}
498
state->x.have++;
499
state->x.next--;
500
state->x.next[0] = (unsigned char)c;
501
state->x.pos--;
502
state->past = 0;
503
return c;
504
}
505
506
/* -- see zlib.h -- */
507
char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
508
unsigned left, n;
509
char *str;
510
unsigned char *eol;
511
gz_statep state;
512
513
/* check parameters and get internal structure */
514
if (file == NULL || buf == NULL || len < 1)
515
return NULL;
516
state = (gz_statep)file;
517
518
/* check that we're reading and that there's no (serious) error */
519
if (state->mode != GZ_READ ||
520
(state->err != Z_OK && state->err != Z_BUF_ERROR))
521
return NULL;
522
523
/* process a skip request */
524
if (state->seek) {
525
state->seek = 0;
526
if (gz_skip(state, state->skip) == -1)
527
return NULL;
528
}
529
530
/* copy output bytes up to new line or len - 1, whichever comes first --
531
append a terminating zero to the string (we don't check for a zero in
532
the contents, let the user worry about that) */
533
str = buf;
534
left = (unsigned)len - 1;
535
if (left) do {
536
/* assure that something is in the output buffer */
537
if (state->x.have == 0 && gz_fetch(state) == -1)
538
return NULL; /* error */
539
if (state->x.have == 0) { /* end of file */
540
state->past = 1; /* read past end */
541
break; /* return what we have */
542
}
543
544
/* look for end-of-line in current output buffer */
545
n = state->x.have > left ? left : state->x.have;
546
eol = (unsigned char *)memchr(state->x.next, '\n', n);
547
if (eol != NULL)
548
n = (unsigned)(eol - state->x.next) + 1;
549
550
/* copy through end-of-line, or remainder if not found */
551
memcpy(buf, state->x.next, n);
552
state->x.have -= n;
553
state->x.next += n;
554
state->x.pos += n;
555
left -= n;
556
buf += n;
557
} while (left && eol == NULL);
558
559
/* return terminated string, or if nothing, end of file */
560
if (buf == str)
561
return NULL;
562
buf[0] = 0;
563
return str;
564
}
565
566
/* -- see zlib.h -- */
567
int ZEXPORT gzdirect(gzFile file) {
568
gz_statep state;
569
570
/* get internal structure */
571
if (file == NULL)
572
return 0;
573
state = (gz_statep)file;
574
575
/* if the state is not known, but we can find out, then do so (this is
576
mainly for right after a gzopen() or gzdopen()) */
577
if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
578
(void)gz_look(state);
579
580
/* return 1 if transparent, 0 if processing a gzip stream */
581
return state->direct;
582
}
583
584
/* -- see zlib.h -- */
585
int ZEXPORT gzclose_r(gzFile file) {
586
int ret, err;
587
gz_statep state;
588
589
/* get internal structure */
590
if (file == NULL)
591
return Z_STREAM_ERROR;
592
state = (gz_statep)file;
593
594
/* check that we're reading */
595
if (state->mode != GZ_READ)
596
return Z_STREAM_ERROR;
597
598
/* free memory and close file */
599
if (state->size) {
600
inflateEnd(&(state->strm));
601
free(state->out);
602
free(state->in);
603
}
604
err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
605
gz_error(state, Z_OK, NULL);
606
free(state->path);
607
ret = close(state->fd);
608
free(state);
609
return ret ? Z_ERRNO : err;
610
}
611
612