Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libz/gzio.c
1808 views
1
/* gzio.c -- IO on .gz files
2
* Copyright (C) 1995-2005 Jean-loup Gailly.
3
* For conditions of distribution and use, see copyright notice in zlib.h
4
*
5
* Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
6
*/
7
8
/* @(#) $Id$ */
9
10
#if _PACKAGE_ast
11
#include <ast.h>
12
#endif
13
14
#include <stdio.h>
15
16
#include "zutil.h"
17
18
#ifdef NO_DEFLATE /* for compatibility with old definition */
19
# define NO_GZCOMPRESS
20
#endif
21
22
#ifndef NO_DUMMY_DECL
23
struct internal_state {int dummy;}; /* for buggy compilers */
24
#endif
25
26
#ifndef Z_BUFSIZE
27
# ifdef MAXSEG_64K
28
# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
29
# else
30
# define Z_BUFSIZE 16384
31
# endif
32
#endif
33
#ifndef Z_PRINTF_BUFSIZE
34
# define Z_PRINTF_BUFSIZE 4096
35
#endif
36
37
#ifdef __MVS__
38
# pragma map (fdopen , "\174\174FDOPEN")
39
FILE *fdopen(int, const char *);
40
#endif
41
42
#if !_PACKAGE_ast
43
#ifndef ZLIB_STDC
44
extern voidp malloc OF((uInt size));
45
extern void free OF((voidpf ptr));
46
#endif
47
#endif
48
49
#define ALLOC(size) malloc(size)
50
#define TRYFREE(p) {if (p) free(p);}
51
52
static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
53
54
/* gzip flag byte */
55
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
56
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
57
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
58
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
59
#define COMMENT 0x10 /* bit 4 set: file comment present */
60
#define RESERVED 0xE0 /* bits 5..7: reserved */
61
62
typedef struct gz_stream {
63
z_stream stream;
64
int z_err; /* error code for last stream operation */
65
int z_eof; /* set if end of input file */
66
FILE *file; /* .gz file */
67
Byte *inbuf; /* input buffer */
68
Byte *outbuf; /* output buffer */
69
uLong crc; /* crc32 of uncompressed data */
70
char *msg; /* error message */
71
char *path; /* path name for debugging only */
72
int transparent; /* 1 if input file is not a .gz file */
73
#if _PACKAGE_ast
74
int fatal; /* fatal stream error => all other ops fail */
75
int nocrc; /* 1 to skip 'r' crc checks */
76
int noclose; /* 1 to skip destroy fclose */
77
int verified;/* 2-byte magic read and verified ('v') */
78
#endif
79
char mode; /* 'w' or 'r' */
80
z_off_t start; /* start of compressed data in file (header skipped) */
81
z_off_t in; /* bytes into deflate or inflate */
82
z_off_t out; /* bytes out of deflate or inflate */
83
int back; /* one character push-back */
84
int last; /* true if push-back is last character */
85
} gz_stream;
86
87
88
local gzFile gz_open OF((const char *path, const char *mode, FILE* fp, void* buf, unsigned len));
89
local int do_flush OF((gzFile file, int flush));
90
local int get_byte OF((gz_stream *s));
91
local void check_header OF((gz_stream *s));
92
local int destroy OF((gz_stream *s));
93
local void putLong OF((FILE *file, uLong x));
94
local uLong getLong OF((gz_stream *s));
95
96
/* ===========================================================================
97
Opens a gzip (.gz) file for reading or writing. The mode parameter
98
is as in fopen ("rb" or "wb"). The file is given either by FILE pointer
99
or path name (if fp == 0).
100
gz_open returns NULL if the file could not be opened or if there was
101
insufficient memory to allocate the (de)compression state; errno
102
can be checked to distinguish the two cases (if errno is zero, the
103
zlib error is Z_MEM_ERROR).
104
*/
105
local gzFile gz_open (path, mode, fp, buf, len)
106
const char *path;
107
const char *mode;
108
FILE *fp;
109
void *buf;
110
unsigned len;
111
{
112
int err;
113
int level = Z_DEFAULT_COMPRESSION; /* compression level */
114
int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
115
char *p = (char*)mode;
116
gz_stream *s;
117
char fmode[80]; /* copy of mode, without the compression level */
118
char *m = fmode;
119
120
if (!path || !mode) return Z_NULL;
121
122
s = (gz_stream *)ALLOC(sizeof(gz_stream));
123
if (!s) return Z_NULL;
124
125
s->stream.zalloc = (alloc_func)0;
126
s->stream.zfree = (free_func)0;
127
s->stream.opaque = (voidpf)0;
128
s->stream.next_in = s->inbuf = Z_NULL;
129
s->stream.next_out = s->outbuf = Z_NULL;
130
s->stream.avail_in = s->stream.avail_out = 0;
131
s->file = NULL;
132
s->z_err = Z_OK;
133
s->z_eof = 0;
134
s->in = 0;
135
s->out = 0;
136
s->back = EOF;
137
s->crc = crc32(0L, Z_NULL, 0);
138
#if _PACKAGE_ast
139
s->fatal = 0;
140
s->noclose = 0;
141
s->nocrc = 0;
142
s->verified = 0;
143
#endif
144
s->msg = NULL;
145
s->transparent = 0;
146
147
s->path = (char*)ALLOC(strlen(path)+1);
148
if (s->path == NULL) {
149
return destroy(s), (gzFile)Z_NULL;
150
}
151
strcpy(s->path, path); /* do this early for debugging */
152
153
s->mode = '\0';
154
do {
155
if (*p == 'r') s->mode = 'r';
156
if (*p == 'w' || *p == 'a') s->mode = 'w';
157
if (*p >= '0' && *p <= '9') {
158
level = *p - '0';
159
} else if (*p == 'f') {
160
strategy = Z_FILTERED;
161
} else if (*p == 'h') {
162
strategy = Z_HUFFMAN_ONLY;
163
} else if (*p == 'R') {
164
strategy = Z_RLE;
165
#if _PACKAGE_ast
166
} else if (*p == 'n') {
167
s->nocrc = 1;
168
} else if (*p == 'o') {
169
s->noclose = 1;
170
} else if (*p == 'v') {
171
s->verified = 1;
172
#endif
173
} else {
174
*m++ = *p; /* copy the mode */
175
}
176
} while (*p++ && m != fmode + sizeof(fmode));
177
if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
178
179
if (s->mode == 'w') {
180
#ifdef NO_GZCOMPRESS
181
err = Z_STREAM_ERROR;
182
#else
183
#if _PACKAGE_ast
184
s->nocrc = 0;
185
#endif
186
err = deflateInit2(&(s->stream), level,
187
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
188
/* windowBits is passed < 0 to suppress zlib header */
189
190
s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
191
#endif
192
if (err != Z_OK || s->outbuf == Z_NULL) {
193
return destroy(s), (gzFile)Z_NULL;
194
}
195
} else {
196
if (buf == Z_NULL)
197
len = 0;
198
s->stream.next_in = s->inbuf = (Byte*)ALLOC((len > Z_BUFSIZE) ? len : Z_BUFSIZE);
199
if (len) {
200
s->stream.avail_in = len;
201
zmemcpy(s->inbuf, buf, len);
202
#if 0
203
fprintf(stderr, "AHA gz_open inbuf=< %02x %02x > len=%d offset=%d:%d\n", s->inbuf[0], s->inbuf[1], len, (int)ftell(fp), (int)lseek(fileno(fp), 0, SEEK_CUR));
204
#endif
205
}
206
207
err = inflateInit2(&(s->stream), -MAX_WBITS);
208
/* windowBits is passed < 0 to tell that there is no zlib header.
209
* Note that in this case inflate *requires* an extra "dummy" byte
210
* after the compressed stream in order to complete decompression and
211
* return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
212
* present after the compressed stream.
213
*/
214
if (err != Z_OK || s->inbuf == Z_NULL) {
215
return destroy(s), (gzFile)Z_NULL;
216
}
217
}
218
s->stream.avail_out = Z_BUFSIZE;
219
220
errno = 0;
221
222
if (!(s->file = fp) && !(s->file = F_OPEN(path, fmode))) {
223
return destroy(s), (gzFile)Z_NULL;
224
}
225
if (s->mode == 'w') {
226
/* Write a very simple .gz header:
227
*/
228
fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
229
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
230
s->start = 10L;
231
/* We use 10L instead of ftell(s->file) to because ftell causes an
232
* fflush on some systems. This version of the library doesn't use
233
* start anyway in write mode, so this initialization is not
234
* necessary.
235
*/
236
} else {
237
#if _PACKAGE_ast && 0
238
sfsetbuf(s->file, (void*)s->file, SF_UNBOUND);
239
#endif
240
check_header(s); /* skip the .gz header */
241
s->start = s->stream.next_in - s->inbuf;
242
}
243
244
return (gzFile)s;
245
}
246
247
/* ===========================================================================
248
Opens a gzip (.gz) file for reading or writing.
249
*/
250
gzFile ZEXPORT gzopen (path, mode)
251
const char *path;
252
const char *mode;
253
{
254
return gz_open (path, mode, (FILE*)Z_NULL, (void*)Z_NULL, 0);
255
}
256
257
gzFile ZEXPORT gzbopen (fd, mode, buf, len)
258
int fd;
259
const char *mode;
260
void *buf;
261
unsigned len;
262
{
263
FILE *fp;
264
char name[46]; /* allow for up to 128-bit integers */
265
266
if (fd < 0 || !(fp = fdopen(fd, mode)))
267
return (gzFile)Z_NULL;
268
sprintf(name, "<fd:%d>", fd); /* for debugging */
269
270
return gz_open (name, mode, fp, buf, len);
271
}
272
/* ===========================================================================
273
Associate a gzFile with the file descriptor fd. fd is not dup'ed here
274
to mimic the behavio(u)r of fdopen.
275
*/
276
gzFile ZEXPORT gzdopen (fd, mode)
277
int fd;
278
const char *mode;
279
{
280
return gzbopen (fd, mode, (void*)Z_NULL, 0);
281
}
282
283
/* ===========================================================================
284
Associate a gzFile with the stdio stream fp.
285
*/
286
gzFile ZEXPORT gzfopen (fp, mode)
287
void* fp;
288
const char *mode;
289
{
290
FILE* sp = (FILE*)fp;
291
char name[20];
292
293
if (!sp)
294
return (gzFile)Z_NULL;
295
sprintf(name, "<fd:%d>", fileno(sp)); /* for debugging */
296
297
return gz_open (name, mode, sp, (void*)Z_NULL, 0);
298
}
299
300
/* ===========================================================================
301
* Update the compression level and strategy
302
*/
303
int ZEXPORT gzsetparams (file, level, strategy)
304
gzFile file;
305
int level;
306
int strategy;
307
{
308
gz_stream *s = (gz_stream*)file;
309
310
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
311
312
/* Make room to allow flushing */
313
if (s->stream.avail_out == 0) {
314
315
s->stream.next_out = s->outbuf;
316
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
317
s->z_err = Z_ERRNO;
318
}
319
s->stream.avail_out = Z_BUFSIZE;
320
}
321
322
return deflateParams (&(s->stream), level, strategy);
323
}
324
325
/* ===========================================================================
326
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
327
for end of file.
328
IN assertion: the stream s has been sucessfully opened for reading.
329
*/
330
local int get_byte(s)
331
gz_stream *s;
332
{
333
if (s->z_eof) return EOF;
334
if (s->stream.avail_in == 0) {
335
errno = 0;
336
s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
337
if (s->stream.avail_in == 0) {
338
s->z_eof = 1;
339
if (ferror(s->file)) s->z_err = Z_ERRNO;
340
return EOF;
341
}
342
s->stream.next_in = s->inbuf;
343
}
344
s->stream.avail_in--;
345
return *(s->stream.next_in)++;
346
}
347
348
/* ===========================================================================
349
Check the gzip header of a gz_stream opened for reading. Set the stream
350
mode to transparent if the gzip magic header is not present; set s->err
351
to Z_DATA_ERROR if the magic header is present but the rest of the header
352
is incorrect.
353
IN assertion: the stream s has already been created sucessfully;
354
s->stream.avail_in is zero for the first time, but may be non-zero
355
for concatenated .gz files.
356
*/
357
local void check_header(s)
358
gz_stream *s;
359
{
360
int method; /* method byte */
361
int flags; /* flags byte */
362
uInt len;
363
int c;
364
365
#if _PACKAGE_ast
366
if (!s->verified)
367
for (len = 0; len < 2; len++) {
368
c = get_byte(s);
369
if (c != gz_magic[len]) {
370
if (len != 0) s->stream.avail_in++, s->stream.next_in--;
371
if (c != EOF) {
372
s->stream.avail_in++, s->stream.next_in--;
373
s->transparent = 1;
374
}
375
s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
376
return;
377
}
378
}
379
#else
380
/* Assure two bytes in the buffer so we can peek ahead -- handle case
381
where first byte of header is at the end of the buffer after the last
382
gzip segment */
383
len = s->stream.avail_in;
384
if (len < 2) {
385
if (len) s->inbuf[0] = s->stream.next_in[0];
386
errno = 0;
387
len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
388
if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
389
s->stream.avail_in += len;
390
s->stream.next_in = s->inbuf;
391
if (s->stream.avail_in < 2) {
392
s->transparent = s->stream.avail_in;
393
return;
394
}
395
}
396
397
/* Peek ahead to check the gzip magic header */
398
if (s->stream.next_in[0] != gz_magic[0] ||
399
s->stream.next_in[1] != gz_magic[1]) {
400
s->transparent = 1;
401
return;
402
}
403
s->stream.avail_in -= 2;
404
s->stream.next_in += 2;
405
#endif
406
407
/* Check the rest of the gzip header */
408
method = get_byte(s);
409
flags = get_byte(s);
410
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
411
s->z_err = Z_DATA_ERROR;
412
return;
413
}
414
415
/* Discard time, xflags and OS code: */
416
for (len = 0; len < 6; len++)
417
(void)get_byte(s);
418
419
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
420
len = (uInt)get_byte(s);
421
len += ((uInt)get_byte(s))<<8;
422
/* len is garbage if EOF but the loop below will quit anyway */
423
while (len-- != 0 && get_byte(s) != EOF) ;
424
}
425
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
426
while ((c = get_byte(s)) != 0 && c != EOF) ;
427
}
428
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
429
while ((c = get_byte(s)) != 0 && c != EOF) ;
430
}
431
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
432
for (len = 0; len < 2; len++) (void)get_byte(s);
433
}
434
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
435
}
436
437
/* ===========================================================================
438
* Cleanup then free the given gz_stream. Return a zlib error code.
439
Try freeing in the reverse order of allocations.
440
*/
441
local int destroy (s)
442
gz_stream *s;
443
{
444
int err = Z_OK;
445
446
if (!s) return Z_STREAM_ERROR;
447
448
TRYFREE(s->msg);
449
450
if (s->stream.state != NULL) {
451
if (s->mode == 'w') {
452
#ifdef NO_GZCOMPRESS
453
err = Z_STREAM_ERROR;
454
#else
455
err = deflateEnd(&(s->stream));
456
#endif
457
} else if (s->mode == 'r') {
458
err = inflateEnd(&(s->stream));
459
}
460
}
461
#if _PACKAGE_ast
462
if (s->file != NULL && (s->noclose ? (s->mode == 'r' ? 0 : fflush(s->file)) : fclose(s->file))) {
463
#else
464
if (s->file != NULL && fclose(s->file)) {
465
#endif
466
#ifdef ESPIPE
467
if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
468
#endif
469
err = Z_ERRNO;
470
}
471
if (s->z_err < 0) err = s->z_err;
472
473
TRYFREE(s->inbuf);
474
TRYFREE(s->outbuf);
475
TRYFREE(s->path);
476
TRYFREE(s);
477
return err;
478
}
479
480
/* ===========================================================================
481
Reads the given number of uncompressed bytes from the compressed file.
482
gzread returns the number of bytes actually read (0 for end of file).
483
*/
484
int ZEXPORT gzread (file, buf, len)
485
gzFile file;
486
voidp buf;
487
unsigned len;
488
{
489
gz_stream *s = (gz_stream*)file;
490
Bytef *start = (Bytef*)buf; /* starting point for crc computation */
491
Byte *next_out; /* == stream.next_out but not forced far (for ZLIB_MSDOS) */
492
493
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
494
495
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
496
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
497
498
next_out = (Byte*)buf;
499
s->stream.next_out = (Bytef*)buf;
500
s->stream.avail_out = len;
501
502
if (s->stream.avail_out && s->back != EOF) {
503
*next_out++ = s->back;
504
s->stream.next_out++;
505
s->stream.avail_out--;
506
s->back = EOF;
507
s->out++;
508
start++;
509
if (s->last) {
510
s->z_err = Z_STREAM_END;
511
return 1;
512
}
513
}
514
515
while (s->stream.avail_out != 0) {
516
517
if (s->transparent) {
518
/* Copy first the lookahead bytes: */
519
uInt n = s->stream.avail_in;
520
if (n > s->stream.avail_out) n = s->stream.avail_out;
521
if (n > 0) {
522
zmemcpy(s->stream.next_out, s->stream.next_in, n);
523
next_out += n;
524
s->stream.next_out = next_out;
525
s->stream.next_in += n;
526
s->stream.avail_out -= n;
527
s->stream.avail_in -= n;
528
}
529
if (s->stream.avail_out > 0) {
530
s->stream.avail_out -=
531
(uInt)fread(next_out, 1, s->stream.avail_out, s->file);
532
}
533
len -= s->stream.avail_out;
534
s->in += len;
535
s->out += len;
536
if (len == 0) s->z_eof = 1;
537
return (int)len;
538
}
539
if (s->stream.avail_in == 0 && !s->z_eof) {
540
541
errno = 0;
542
s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
543
if (s->stream.avail_in == 0) {
544
s->z_eof = 1;
545
if (ferror(s->file)) {
546
s->z_err = Z_ERRNO;
547
break;
548
}
549
}
550
s->stream.next_in = s->inbuf;
551
}
552
s->in += s->stream.avail_in;
553
s->out += s->stream.avail_out;
554
s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
555
s->in -= s->stream.avail_in;
556
s->out -= s->stream.avail_out;
557
558
if (s->z_err == Z_STREAM_END) {
559
/* Check CRC and original size */
560
#if _PACKAGE_ast
561
if (!s->nocrc)
562
#endif
563
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
564
start = s->stream.next_out;
565
566
#if _PACKAGE_ast
567
if (getLong(s) != s->crc && !s->nocrc) {
568
#else
569
if (getLong(s) != s->crc) {
570
#endif
571
s->z_err = Z_DATA_ERROR;
572
} else {
573
(void)getLong(s);
574
/* The uncompressed length returned by above getlong() may be
575
* different from s->out in case of concatenated .gz files.
576
* Check for such files:
577
*/
578
check_header(s);
579
if (s->z_err == Z_OK) {
580
inflateReset(&(s->stream));
581
#if _PACKAGE_ast
582
if (!s->nocrc)
583
#endif
584
s->crc = crc32(0L, Z_NULL, 0);
585
#if _PACKAGE_ast
586
else
587
s->z_err = Z_STREAM_END;
588
#endif
589
}
590
}
591
}
592
if (s->z_err != Z_OK || s->z_eof) break;
593
}
594
#if _PACKAGE_ast
595
if (!s->nocrc)
596
#endif
597
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
598
599
if (len == s->stream.avail_out &&
600
(s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
601
return -1;
602
return (int)(len - s->stream.avail_out);
603
}
604
605
606
/* ===========================================================================
607
Reads one byte from the compressed file. gzgetc returns this byte
608
or -1 in case of end of file or error.
609
*/
610
int ZEXPORT gzgetc(file)
611
gzFile file;
612
{
613
unsigned char c;
614
615
return gzread(file, &c, 1) == 1 ? c : -1;
616
}
617
618
619
/* ===========================================================================
620
Push one byte back onto the stream.
621
*/
622
int ZEXPORT gzungetc(c, file)
623
int c;
624
gzFile file;
625
{
626
gz_stream *s = (gz_stream*)file;
627
628
if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
629
s->back = c;
630
s->out--;
631
s->last = (s->z_err == Z_STREAM_END);
632
if (s->last) s->z_err = Z_OK;
633
s->z_eof = 0;
634
return c;
635
}
636
637
638
/* ===========================================================================
639
Reads bytes from the compressed file until len-1 characters are
640
read, or a newline character is read and transferred to buf, or an
641
end-of-file condition is encountered. The string is then terminated
642
with a null character.
643
gzgets returns buf, or Z_NULL in case of error.
644
645
The current implementation is not optimized at all.
646
*/
647
char * ZEXPORT gzgets(file, buf, len)
648
gzFile file;
649
char *buf;
650
int len;
651
{
652
char *b = buf;
653
if (buf == Z_NULL || len <= 0) return Z_NULL;
654
655
while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
656
*buf = '\0';
657
return b == buf && len > 0 ? Z_NULL : b;
658
}
659
660
661
#ifndef NO_GZCOMPRESS
662
/* ===========================================================================
663
Writes the given number of uncompressed bytes into the compressed file.
664
gzwrite returns the number of bytes actually written (0 in case of error).
665
*/
666
int ZEXPORT gzwrite (file, buf, len)
667
gzFile file;
668
voidpc buf;
669
unsigned len;
670
{
671
gz_stream *s = (gz_stream*)file;
672
673
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
674
675
s->stream.next_in = (Bytef*)buf;
676
s->stream.avail_in = len;
677
678
while (s->stream.avail_in != 0) {
679
680
if (s->stream.avail_out == 0) {
681
682
s->stream.next_out = s->outbuf;
683
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
684
s->z_err = Z_ERRNO;
685
break;
686
}
687
s->stream.avail_out = Z_BUFSIZE;
688
}
689
s->in += s->stream.avail_in;
690
s->out += s->stream.avail_out;
691
s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
692
s->in -= s->stream.avail_in;
693
s->out -= s->stream.avail_out;
694
if (s->z_err != Z_OK) break;
695
}
696
s->crc = crc32(s->crc, (const Bytef *)buf, len);
697
698
return (int)(len - s->stream.avail_in);
699
}
700
701
702
/* ===========================================================================
703
Converts, formats, and writes the args to the compressed file under
704
control of the format string, as in fprintf. gzprintf returns the number of
705
uncompressed bytes actually written (0 in case of error).
706
*/
707
708
#if _PACKAGE_ast
709
710
#ifdef __STDC__
711
int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
712
#else
713
int ZEXPORTVA gzprintf ()
714
#endif
715
{
716
#ifndef __STDC__
717
va_dcl
718
gzFile file;
719
char *format;
720
#endif
721
va_list ap;
722
Sfio_t* sp;
723
ssize_t n;
724
725
if (!(sp = sfstropen()))
726
return -1;
727
#ifdef __STDC__
728
va_start(ap, format);
729
#else
730
va_start(ap);
731
file = va_arg(ap, gzFile);
732
format = va_arg(ap, char*);
733
#endif
734
n = sfvprintf(sp, format, ap);
735
va_end(ap);
736
if (n >= 0)
737
n = gzwrite(file, sfstrbase(sp), n);
738
sfclose(sp);
739
return n;
740
}
741
742
#else
743
744
#ifdef ZLIB_STDC
745
#include <stdarg.h>
746
747
int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
748
{
749
char buf[Z_PRINTF_BUFSIZE];
750
va_list va;
751
int len;
752
753
buf[sizeof(buf) - 1] = 0;
754
va_start(va, format);
755
#ifdef NO_vsnprintf
756
# ifdef HAS_vsprintf_void
757
(void)vsprintf(buf, format, va);
758
va_end(va);
759
for (len = 0; len < sizeof(buf); len++)
760
if (buf[len] == 0) break;
761
# else
762
len = vsprintf(buf, format, va);
763
va_end(va);
764
# endif
765
#else
766
# ifdef HAS_vsnprintf_void
767
(void)vsnprintf(buf, sizeof(buf), format, va);
768
va_end(va);
769
len = strlen(buf);
770
# else
771
len = vsnprintf(buf, sizeof(buf), format, va);
772
va_end(va);
773
# endif
774
#endif
775
if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
776
return 0;
777
return gzwrite(file, buf, (unsigned)len);
778
}
779
#else /* not ANSI C */
780
781
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
782
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
783
gzFile file;
784
const char *format;
785
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
786
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
787
{
788
char buf[Z_PRINTF_BUFSIZE];
789
int len;
790
791
buf[sizeof(buf) - 1] = 0;
792
#ifdef NO_snprintf
793
# ifdef HAS_sprintf_void
794
sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
795
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
796
for (len = 0; len < sizeof(buf); len++)
797
if (buf[len] == 0) break;
798
# else
799
len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
800
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
801
# endif
802
#else
803
# ifdef HAS_snprintf_void
804
snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
805
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
806
len = strlen(buf);
807
# else
808
len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
809
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
810
# endif
811
#endif
812
if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
813
return 0;
814
return gzwrite(file, buf, len);
815
}
816
#endif
817
#endif
818
819
/* ===========================================================================
820
Writes c, converted to an unsigned char, into the compressed file.
821
gzputc returns the value that was written, or -1 in case of error.
822
*/
823
int ZEXPORT gzputc(file, c)
824
gzFile file;
825
int c;
826
{
827
unsigned char cc = (unsigned char) c; /* required for big endian systems */
828
829
return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
830
}
831
832
833
/* ===========================================================================
834
Writes the given null-terminated string to the compressed file, excluding
835
the terminating null character.
836
gzputs returns the number of characters written, or -1 in case of error.
837
*/
838
int ZEXPORT gzputs(file, s)
839
gzFile file;
840
const char *s;
841
{
842
return gzwrite(file, (char*)s, (unsigned)strlen(s));
843
}
844
845
846
/* ===========================================================================
847
Flushes all pending output into the compressed file. The parameter
848
flush is as in the deflate() function.
849
*/
850
local int do_flush (file, flush)
851
gzFile file;
852
int flush;
853
{
854
uInt len;
855
int done = 0;
856
gz_stream *s = (gz_stream*)file;
857
858
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
859
860
s->stream.avail_in = 0; /* should be zero already anyway */
861
862
for (;;) {
863
len = Z_BUFSIZE - s->stream.avail_out;
864
865
if (len != 0) {
866
if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
867
s->z_err = Z_ERRNO;
868
return Z_ERRNO;
869
}
870
s->stream.next_out = s->outbuf;
871
s->stream.avail_out = Z_BUFSIZE;
872
}
873
if (done) break;
874
s->out += s->stream.avail_out;
875
s->z_err = deflate(&(s->stream), flush);
876
s->out -= s->stream.avail_out;
877
878
/* Ignore the second of two consecutive flushes: */
879
if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
880
881
/* deflate has finished flushing only when it hasn't used up
882
* all the available space in the output buffer:
883
*/
884
done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
885
886
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
887
}
888
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
889
}
890
891
int ZEXPORT gzflush (file, flush)
892
gzFile file;
893
int flush;
894
{
895
gz_stream *s = (gz_stream*)file;
896
int err = do_flush (file, flush);
897
898
if (err) return err;
899
fflush(s->file);
900
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
901
}
902
#endif /* NO_GZCOMPRESS */
903
904
/* ===========================================================================
905
Sets the starting position for the next gzread or gzwrite on the given
906
compressed file. The offset represents a number of bytes in the
907
gzseek returns the resulting offset location as measured in bytes from
908
the beginning of the uncompressed stream, or -1 in case of error.
909
SEEK_END is not implemented, returns error.
910
In this version of the library, gzseek can be extremely slow.
911
*/
912
z_off_t ZEXPORT gzseek (file, offset, whence)
913
gzFile file;
914
z_off_t offset;
915
int whence;
916
{
917
gz_stream *s = (gz_stream*)file;
918
919
if (s == NULL || whence == SEEK_END ||
920
s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
921
return -1L;
922
}
923
924
if (s->mode == 'w') {
925
#ifdef NO_GZCOMPRESS
926
return -1L;
927
#else
928
if (whence == SEEK_SET) {
929
offset -= s->in;
930
}
931
if (offset < 0) return -1L;
932
933
/* At this point, offset is the number of zero bytes to write. */
934
if (s->inbuf == Z_NULL) {
935
s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
936
if (s->inbuf == Z_NULL) return -1L;
937
zmemzero(s->inbuf, Z_BUFSIZE);
938
}
939
while (offset > 0) {
940
uInt size = Z_BUFSIZE;
941
if (offset < Z_BUFSIZE) size = (uInt)offset;
942
943
size = gzwrite(file, s->inbuf, size);
944
if (size == 0) return -1L;
945
946
offset -= size;
947
}
948
return s->in;
949
#endif
950
}
951
/* Rest of function is for reading only */
952
953
/* compute absolute position */
954
if (whence == SEEK_CUR) {
955
offset += s->out;
956
}
957
if (offset < 0) return -1L;
958
959
if (s->transparent) {
960
/* map to fseek */
961
s->back = EOF;
962
s->stream.avail_in = 0;
963
s->stream.next_in = s->inbuf;
964
if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
965
966
s->in = s->out = offset;
967
return offset;
968
}
969
970
/* For a negative seek, rewind and use positive seek */
971
if (offset >= s->out) {
972
offset -= s->out;
973
} else if (gzrewind(file) < 0) {
974
return -1L;
975
}
976
/* offset is now the number of bytes to skip. */
977
978
if (offset != 0 && s->outbuf == Z_NULL) {
979
s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
980
if (s->outbuf == Z_NULL) return -1L;
981
}
982
if (offset && s->back != EOF) {
983
s->back = EOF;
984
s->out++;
985
offset--;
986
if (s->last) s->z_err = Z_STREAM_END;
987
}
988
while (offset > 0) {
989
int size = Z_BUFSIZE;
990
if (offset < Z_BUFSIZE) size = (int)offset;
991
992
size = gzread(file, s->outbuf, (uInt)size);
993
if (size <= 0) return -1L;
994
offset -= size;
995
}
996
return s->out;
997
}
998
999
/* ===========================================================================
1000
Rewinds input file.
1001
*/
1002
int ZEXPORT gzrewind (file)
1003
gzFile file;
1004
{
1005
gz_stream *s = (gz_stream*)file;
1006
1007
if (s == NULL || s->mode != 'r') return -1;
1008
1009
s->z_err = Z_OK;
1010
s->z_eof = 0;
1011
s->back = EOF;
1012
s->stream.avail_in = 0;
1013
s->stream.next_in = s->inbuf;
1014
s->crc = crc32(0L, Z_NULL, 0);
1015
if (!s->transparent) (void)inflateReset(&s->stream);
1016
s->in = 0;
1017
s->out = 0;
1018
return fseek(s->file, s->start, SEEK_SET);
1019
}
1020
1021
int ZEXPORT gzcrc (file, set)
1022
gzFile file;
1023
int set;
1024
{
1025
#if _PACKAGE_ast
1026
gz_stream *s = (gz_stream*)file;
1027
int crc = !s->nocrc;
1028
1029
s->nocrc = !set;
1030
return crc;
1031
#else
1032
return 0;
1033
#endif
1034
}
1035
1036
/* ===========================================================================
1037
Returns the starting position for the next gzread or gzwrite on the
1038
given compressed file. This position represents a number of bytes in the
1039
uncompressed data stream.
1040
*/
1041
z_off_t ZEXPORT gztell (file)
1042
gzFile file;
1043
{
1044
return gzseek(file, 0L, SEEK_CUR);
1045
}
1046
1047
/* ===========================================================================
1048
Returns 1 when EOF has previously been detected reading the given
1049
input stream, otherwise zero.
1050
*/
1051
int ZEXPORT gzeof (file)
1052
gzFile file;
1053
{
1054
gz_stream *s = (gz_stream*)file;
1055
1056
/* With concatenated compressed files that can have embedded
1057
* crc trailers, z_eof is no longer the only/best indicator of EOF
1058
* on a gz_stream. Handle end-of-stream error explicitly here.
1059
*/
1060
if (s == NULL || s->mode != 'r') return 0;
1061
if (s->z_eof) return 1;
1062
return s->z_err == Z_STREAM_END;
1063
}
1064
1065
/* ===========================================================================
1066
Returns 1 if reading and doing so transparently, otherwise zero.
1067
*/
1068
int ZEXPORT gzdirect (file)
1069
gzFile file;
1070
{
1071
gz_stream *s = (gz_stream*)file;
1072
1073
if (s == NULL || s->mode != 'r') return 0;
1074
return s->transparent;
1075
}
1076
1077
/* ===========================================================================
1078
Outputs a long in LSB order to the given file
1079
*/
1080
local void putLong (file, x)
1081
FILE *file;
1082
uLong x;
1083
{
1084
int n;
1085
for (n = 0; n < 4; n++) {
1086
fputc((int)(x & 0xff), file);
1087
x >>= 8;
1088
}
1089
}
1090
1091
/* ===========================================================================
1092
Reads a long in LSB order from the given gz_stream. Sets z_err in case
1093
of error.
1094
*/
1095
local uLong getLong (s)
1096
gz_stream *s;
1097
{
1098
uLong x = (uLong)get_byte(s);
1099
int c;
1100
1101
x += ((uLong)get_byte(s))<<8;
1102
x += ((uLong)get_byte(s))<<16;
1103
c = get_byte(s);
1104
if (c == EOF) s->z_err = Z_DATA_ERROR;
1105
x += ((uLong)c)<<24;
1106
return x;
1107
}
1108
1109
/* ===========================================================================
1110
Flushes all pending output if necessary, closes the compressed file
1111
and deallocates all the (de)compression state.
1112
*/
1113
int ZEXPORT gzclose (file)
1114
gzFile file;
1115
{
1116
gz_stream *s = (gz_stream*)file;
1117
1118
if (s == NULL) return Z_STREAM_ERROR;
1119
1120
if (s->mode == 'w') {
1121
#ifdef NO_GZCOMPRESS
1122
return Z_STREAM_ERROR;
1123
#else
1124
if (do_flush (file, Z_FINISH) != Z_OK)
1125
return destroy((gz_stream*)file);
1126
1127
putLong (s->file, s->crc);
1128
putLong (s->file, (uLong)(s->in & 0xffffffff));
1129
#endif
1130
}
1131
return destroy((gz_stream*)file);
1132
}
1133
1134
#ifdef ZLIB_STDC
1135
# define zstrerror(errnum) strerror(errnum)
1136
#else
1137
# define zstrerror(errnum) ""
1138
#endif
1139
1140
/* ===========================================================================
1141
Returns the error message for the last error which occurred on the
1142
given compressed file. errnum is set to zlib error number. If an
1143
error occurred in the file system and not in the compression library,
1144
errnum is set to Z_ERRNO and the application may consult errno
1145
to get the exact error code.
1146
*/
1147
const char * ZEXPORT gzerror (file, errnum)
1148
gzFile file;
1149
int *errnum;
1150
{
1151
char *m;
1152
gz_stream *s = (gz_stream*)file;
1153
1154
if (s == NULL) {
1155
*errnum = Z_STREAM_ERROR;
1156
return (const char*)ERR_MSG(Z_STREAM_ERROR);
1157
}
1158
*errnum = s->z_err;
1159
if (*errnum == Z_OK) return (const char*)"";
1160
1161
m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
1162
1163
if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
1164
1165
TRYFREE(s->msg);
1166
s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
1167
if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
1168
strcpy(s->msg, s->path);
1169
strcat(s->msg, ": ");
1170
strcat(s->msg, m);
1171
return (const char*)s->msg;
1172
}
1173
1174
/* ===========================================================================
1175
Clear the error and end-of-file flags, and do the same for the real file.
1176
*/
1177
void ZEXPORT gzclearerr (file)
1178
gzFile file;
1179
{
1180
gz_stream *s = (gz_stream*)file;
1181
1182
if (s == NULL) return;
1183
if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
1184
s->z_eof = 0;
1185
clearerr(s->file);
1186
}
1187
1188
#if _PACKAGE_ast
1189
1190
#ifdef z_off64_t
1191
#define z_OFF_t z_off64_t
1192
#define gzsync gzsync64
1193
#undef fseek
1194
#define fseek fseek64
1195
#undef ftell
1196
#define ftell ftell64
1197
#else
1198
#define z_OFF_t z_off_t
1199
#endif
1200
1201
z_OFF_t ZEXPORT gzsync (file, offset)
1202
gzFile file;
1203
z_OFF_t offset;
1204
{
1205
gz_stream *s = (gz_stream*)file;
1206
1207
if (s == NULL || s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR || s->fatal)
1208
return (z_OFF_t)-1;
1209
if (s->mode == 'w') {
1210
if (do_flush (file, Z_FULL_FLUSH))
1211
return (z_OFF_t)-1;
1212
if (fflush(s->file)) {
1213
s->fatal = 1;
1214
s->z_err = Z_ERRNO;
1215
return (z_OFF_t)-1;
1216
}
1217
}
1218
else if (gzrewind(file) < 0)
1219
return (z_OFF_t)-1;
1220
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END)
1221
return (z_OFF_t)-1;
1222
if (offset == (z_OFF_t)(-1))
1223
return ftell(s->file);
1224
return fseek(s->file, offset, SEEK_SET);
1225
}
1226
1227
#ifdef z_off64_t
1228
1229
#undef gzsync
1230
z_off_t ZEXPORT gzsync (file, offset)
1231
gzFile file;
1232
z_off_t offset;
1233
{
1234
return (z_off_t)gzsync64(file, (z_OFF_t)offset);
1235
}
1236
1237
#endif
1238
1239
#endif
1240
1241