Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/externals/figlet/zipio.c
12240 views
1
/*
2
* zipio.c - stdio emulation library for reading zip files
3
*
4
* Version 1.1.2
5
*/
6
7
/*
8
* Copyright (C) 1995, Edward B. Hamrick
9
*
10
* Permission to use, copy, modify, and distribute this software and
11
* its documentation for any purpose and without fee is hereby granted,
12
* provided that the above copyright notice appear in all copies and
13
* that both that copyright notice and this permission notice appear in
14
* supporting documentation, and that the name of the copyright holders
15
* not be used in advertising or publicity pertaining to distribution of
16
* the software without specific, written prior permission. The copyright
17
* holders makes no representations about the suitability of this software
18
* for any purpose. It is provided "as is" without express or implied warranty.
19
*
20
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
21
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
22
* IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
23
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
25
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26
* OF THIS SOFTWARE.
27
*/
28
29
/*
30
* Changes from 1.1 to 1.1.1:
31
* Changed "z*" functions to "Z*" to avoid namespace pollution.
32
* Added "zungetc" macro.
33
* Added definitions of SEEK_SET, SEEK_CUR, SEEK_END for the Posixly challenged
34
* John Cowan <[email protected]>
35
*
36
* Changes from 1.1.1 to 1.1.2:
37
* Relicensed under the MIT license, with consent of the copyright holders.
38
* Avoid usage of unitialized "length" variable in _Zgetc
39
* Claudio Matsuoka (Jan 11 2011)
40
*/
41
42
/*
43
* Refer to zipio.h for a description of this package.
44
*/
45
46
/*
47
* The .zip file header is described below. It consists of
48
* 30 fixed bytes, followed by two variable length fields
49
* whose length is contained in the first 30 bytes. After this
50
* header, the data is stored (in deflate format if the compression
51
* method is 8).
52
*
53
* The crc-32 field is the crc on the uncompressed data.
54
*
55
* .zip file header:
56
*
57
* local file header signature 4 bytes (0x04034b50)
58
* version needed to extract 2 bytes
59
* general purpose bit flag 2 bytes
60
* compression method 2 bytes
61
* last mod file time 2 bytes
62
* last mod file date 2 bytes
63
* crc-32 4 bytes
64
* compressed size 4 bytes
65
* uncompressed size 4 bytes
66
* filename length 2 bytes
67
* extra field length 2 bytes
68
*
69
* filename (variable size)
70
* extra field (variable size)
71
*
72
* These fields are described in more detail in appnote.txt
73
* in the pkzip 1.93 distribution.
74
*/
75
76
#include <stdlib.h>
77
#ifdef MEMCPY
78
#include <mem.h>
79
#endif
80
81
#include "zipio.h"
82
#include "inflate.h"
83
#include "crc.h"
84
85
/*
86
* Macros for constants
87
*/
88
89
#ifndef NULL
90
#define NULL ((void *) 0)
91
#endif
92
93
#ifndef TRUE
94
#define TRUE 1
95
#endif
96
97
#ifndef FALSE
98
#define FALSE 0
99
#endif
100
101
#ifndef ZIPSIGNATURE
102
#define ZIPSIGNATURE 0x04034b50L
103
#endif
104
105
#ifndef SEEK_SET
106
#define SEEK_SET 0
107
#endif
108
109
#ifndef SEEK_CUR
110
#define SEEK_CUR 1
111
#endif
112
113
#ifndef SEEK_END
114
#define SEEK_END 2
115
#endif
116
117
118
/*
119
* Buffer size macros
120
*
121
* The following constants are optimized for large-model
122
* (but not flat model) Windows with virtual memory. It
123
* will work fine on unix and flat model Windows as well.
124
*
125
* The constant BUFFERTHRESHOLD determines when memory
126
* buffering changes to file buffering.
127
*
128
* Assumptions:
129
*
130
* 1) INPBUFSIZE + OUTBUFSIZE + sizeof(void *) * PTRBUFSIZE + delta < 64K
131
*
132
* 2) OUTBUFSIZE = 32K * N (related to inflate's 32K window size)
133
*
134
* 2) Max in-memory file size is OUTBUFSIZE * PTRBUFSIZE
135
* which is 64 MBytes by default (32K * 2K).
136
*
137
*/
138
139
#ifndef BUFFERTHRESHOLD
140
#define BUFFERTHRESHOLD (256 * 1024L)
141
#endif
142
143
#ifndef INPBUFSIZE
144
#define INPBUFSIZE ( 8 * 1024 )
145
#endif
146
147
#ifndef PTRBUFSIZE
148
#define PTRBUFSIZE ( 2 * 1024 )
149
#endif
150
151
#ifndef OUTBUFSIZE
152
#define OUTBUFSIZE ((unsigned int) ( 32 * 1024L))
153
#endif
154
155
#define MAXFILESIZE (OUTBUFSIZE * (long) PTRBUFSIZE)
156
157
/*
158
* Macro for short-hand reference to ZipioState (from ZFILE *)
159
*/
160
161
#define ZS ((struct ZipioState *) stream)
162
163
/*
164
* Macro to manipulate Zgetc() cache
165
*/
166
167
#define CACHEINIT \
168
zs->ptr = NULL; \
169
zs->len = 0;
170
171
#define CACHEUPDATE \
172
if (ZS->ptr) \
173
{ \
174
ZS->fileposition &= ~((long) (OUTBUFSIZE-1)); \
175
ZS->fileposition += ZS->ptr - ZS->getbuf; \
176
ZS->ptr = NULL; \
177
} \
178
ZS->len = 0;
179
180
/*
181
* Macros for run-time type identification
182
*/
183
184
#ifndef RUNTIMEENABLE
185
#define RUNTIMEENABLE 0
186
#endif
187
188
#if RUNTIMEENABLE
189
#define ZIPIOSTATETYPE 0x0110f00fL
190
#define RUNTIMEINIT \
191
zs->runtimetypeid1 = ZIPIOSTATETYPE; \
192
zs->runtimetypeid2 = ZIPIOSTATETYPE;
193
194
#define RUNTIMECHECK \
195
if (!ZS || (ZS->runtimetypeid1 != ZIPIOSTATETYPE) \
196
|| (ZS->runtimetypeid2 != ZIPIOSTATETYPE)) return -1;
197
#else
198
#define RUNTIMEINIT
199
#define RUNTIMECHECK
200
#endif
201
202
/*
203
* Macros for converting bytes to unsigned integers
204
*/
205
206
#define GETUINT4(ptr, i4) \
207
{ \
208
i4 = (((unsigned long) *(((unsigned char *) (ptr)) + 0)) ) | \
209
(((unsigned long) *(((unsigned char *) (ptr)) + 1)) << 8) | \
210
(((unsigned long) *(((unsigned char *) (ptr)) + 2)) << 16) | \
211
(((unsigned long) *(((unsigned char *) (ptr)) + 3)) << 24) ; \
212
}
213
214
#define GETUINT2(ptr, i2) \
215
{ \
216
i2 = (((unsigned int) *(((unsigned char *) (ptr)) + 0)) ) | \
217
(((unsigned int) *(((unsigned char *) (ptr)) + 1)) << 8) ; \
218
}
219
220
/* Structure to hold state for decoding zip files */
221
struct ZipioState {
222
223
/* Fields overlaid with ZFILE structure */
224
int len; /* length of Zgetc cache */
225
unsigned char *ptr; /* pointer to Zgetc cache */
226
227
/* Fields invisible to users of ZFILE structure */
228
229
unsigned long runtimetypeid1; /* to detect run-time errors */
230
int errorencountered; /* error encountered flag */
231
232
/* Buffering state */
233
unsigned char inpbuf[INPBUFSIZE]; /* inp buffer from zip file */
234
unsigned char *ptrbuf[PTRBUFSIZE]; /* pointers to in-memory bufs */
235
236
unsigned char getbuf[OUTBUFSIZE]; /* buffer for use by Zgetc */
237
long getoff; /* starting offset of getbuf */
238
239
FILE *tmpfil; /* file ptr to temp file */
240
241
/* Amount of input data inflated */
242
unsigned long inpinf;
243
unsigned long outinf;
244
245
/* Zip file header */
246
unsigned long sign; /* local file header signature (0x04034b50) */
247
unsigned int vers; /* version needed to extract 2 bytes */
248
unsigned int flag; /* general purpose bit flag 2 bytes */
249
unsigned int comp; /* compression method 2 bytes */
250
unsigned int mtim; /* last mod file time 2 bytes */
251
unsigned int mdat; /* last mod file date 2 bytes */
252
unsigned long crc3; /* crc-32 4 bytes */
253
unsigned long csiz; /* compressed size 4 bytes */
254
unsigned long usiz; /* uncompressed size 4 bytes */
255
unsigned int flen; /* filename length 2 bytes */
256
unsigned int elen; /* extra field length 2 bytes */
257
258
/* Application state */
259
FILE *OpenFile; /* currently open file */
260
261
void *inflatestate; /* current state for inflate */
262
263
unsigned long fileposition; /* current file position */
264
265
unsigned long filecrc; /* current crc */
266
267
unsigned long runtimetypeid2; /* to detect run-time errors */
268
};
269
270
/*
271
* Utility routines to handle uncompressed file buffers
272
*/
273
274
/* Initialize buffering */
275
static void BufferInitialize(
276
struct ZipioState *zs,
277
int doinflate
278
)
279
{
280
zs->getoff = -1;
281
zs->tmpfil = NULL;
282
283
/*
284
* If not inflating, use the input file
285
*/
286
287
if (!doinflate)
288
{
289
zs->tmpfil = zs->OpenFile;
290
291
/* Get the uncompressed file size */
292
fseek(zs->tmpfil, 0, SEEK_END);
293
zs->usiz = ftell(zs->tmpfil);
294
zs->outinf = zs->usiz;
295
296
/* Start at the beginning */
297
fseek(zs->tmpfil, 0, SEEK_SET);
298
}
299
300
/* If there's no file open, see if it's big enough for temp file */
301
if (!zs->tmpfil)
302
{
303
if (zs->usiz >= BUFFERTHRESHOLD)
304
zs->tmpfil = tmpfile();
305
}
306
307
/* If there's no file open, then use memory buffering */
308
if (!zs->tmpfil)
309
{
310
int i;
311
312
for (i=0; i<PTRBUFSIZE; i++)
313
zs->ptrbuf[i] = NULL;
314
}
315
}
316
317
/* pump data till length bytes of file are inflated or error encountered */
318
static int BufferPump(struct ZipioState *zs, long length)
319
{
320
size_t inplen, ret;
321
322
/* Check to see if the length is valid */
323
if (length > zs->usiz) return TRUE;
324
325
/* Loop till enough data is pumped */
326
while (!zs->errorencountered && (zs->outinf < length))
327
{
328
/* Compute how much data to read */
329
if ((zs->csiz - zs->inpinf) < INPBUFSIZE)
330
inplen = (size_t) (zs->csiz - zs->inpinf);
331
else
332
inplen = INPBUFSIZE;
333
334
if (inplen <= 0) return TRUE;
335
336
/* Read some data from the file */
337
ret = fread(zs->inpbuf, 1, inplen, zs->OpenFile);
338
if (ret != inplen) return TRUE;
339
340
/* Update how much data has been read from the file */
341
zs->inpinf += inplen;
342
343
/* Pump this data into the decompressor */
344
if (InflatePutBuffer(zs->inflatestate, zs->inpbuf, inplen)) return TRUE;
345
}
346
347
return FALSE;
348
}
349
350
/* Read from the buffer */
351
static int BufferRead(
352
struct ZipioState *zs,
353
long offset,
354
unsigned char *buffer,
355
long length
356
)
357
{
358
/*
359
* Make sure enough bytes have been inflated
360
* Note that the correction for reading past EOF has to
361
* be done before calling this routine
362
*/
363
364
if (BufferPump(zs, offset+length)) return TRUE;
365
366
/* If using file buffering, just get the data from the file */
367
if (zs->tmpfil)
368
{
369
if (fseek(zs->tmpfil, offset, SEEK_SET)) return TRUE;
370
if (fread(buffer, 1, (size_t) length, zs->tmpfil) != length) return TRUE;
371
}
372
/* If no temp file, use memory buffering */
373
else
374
{
375
unsigned int i;
376
unsigned int off, len;
377
unsigned char *ptr;
378
379
long tmpoff;
380
unsigned char *tmpbuf;
381
long tmplen;
382
383
/* Save copies of offset, buffer and length for the loop */
384
tmpoff = offset;
385
tmpbuf = buffer;
386
tmplen = length;
387
388
/* Validate the transfer */
389
if (tmpoff+tmplen > MAXFILESIZE) return TRUE;
390
391
/* Loop till done */
392
while (tmplen)
393
{
394
/* Get a pointer to the next block */
395
i = (unsigned int) (tmpoff / OUTBUFSIZE);
396
ptr = zs->ptrbuf[i];
397
if (!ptr) return TRUE;
398
399
/* Get the offset,length for this block */
400
off = (unsigned int) (tmpoff & (OUTBUFSIZE-1));
401
len = OUTBUFSIZE - off;
402
if (len > tmplen) len = (unsigned int) tmplen;
403
404
/* Get the starting pointer for the transfer */
405
ptr += off;
406
407
/* Copy the data for this block */
408
#ifdef MEMCPY
409
memcpy(tmpbuf, ptr, len);
410
#else
411
for (i=0; i<len; i++)
412
tmpbuf[i] = ptr[i];
413
#endif
414
415
/* Update the offset, buffer, and length */
416
tmpoff += len;
417
tmpbuf += len;
418
tmplen -= len;
419
}
420
}
421
422
/* return success */
423
return FALSE;
424
}
425
426
/* Append to the buffer */
427
static int BufferAppend(
428
struct ZipioState *zs,
429
unsigned char *buffer,
430
long length
431
)
432
{
433
/* If using file buffering, just append the data from the file */
434
if (zs->tmpfil)
435
{
436
if (fseek(zs->tmpfil, zs->outinf, SEEK_SET)) return TRUE;
437
if (fwrite(buffer, 1, (size_t) length, zs->tmpfil) != length) return TRUE;
438
}
439
/* If no temp file, use memory buffering */
440
else
441
{
442
unsigned int i;
443
unsigned int off, len;
444
unsigned char *ptr;
445
446
long tmpoff;
447
unsigned char *tmpbuf;
448
long tmplen;
449
450
/* Save copies of outinf, buffer and length for the loop */
451
tmpoff = zs->outinf;
452
tmpbuf = buffer;
453
tmplen = length;
454
455
/* Validate the transfer */
456
if (tmpoff+tmplen > MAXFILESIZE) return TRUE;
457
458
/* Loop till done */
459
while (tmplen)
460
{
461
/* Get a pointer to the next block */
462
i = (unsigned int) (tmpoff / OUTBUFSIZE);
463
ptr = zs->ptrbuf[i];
464
if (!ptr)
465
{
466
ptr = (unsigned char *) malloc(OUTBUFSIZE);
467
if (!ptr) return TRUE;
468
zs->ptrbuf[i] = ptr;
469
}
470
471
/* Get the offset,length for this block */
472
off = (unsigned int) (tmpoff & (OUTBUFSIZE-1));
473
len = OUTBUFSIZE - off;
474
if (len > tmplen) len = (unsigned int) tmplen;
475
476
/* Get the starting pointer for the transfer */
477
ptr += off;
478
479
/* Copy the data for this block */
480
#ifdef MEMCPY
481
memcpy(ptr, tmpbuf, len);
482
#else
483
for (i=0; i<len; i++)
484
ptr[i] = tmpbuf[i];
485
#endif
486
487
/* Update the offset, buffer, and length */
488
tmpoff += len;
489
tmpbuf += len;
490
tmplen -= len;
491
}
492
}
493
494
/* Update the output buffer length */
495
zs->outinf += length;
496
497
/* return success */
498
return FALSE;
499
}
500
501
/* Terminate buffering */
502
static void BufferTerminate(
503
struct ZipioState *zs
504
)
505
{
506
/* If reading directly from the uncompressed file, just mark with NULL */
507
if (zs->tmpfil == zs->OpenFile)
508
{
509
zs->tmpfil = NULL;
510
}
511
/* If using the a temporary file, close it */
512
else if (zs->tmpfil)
513
{
514
fclose(zs->tmpfil);
515
zs->tmpfil = NULL;
516
}
517
/* If doing memory buffering, free the buffers */
518
else
519
{
520
int i;
521
522
for (i=0; i<PTRBUFSIZE; i++)
523
if (zs->ptrbuf[i]) free(zs->ptrbuf[i]);
524
}
525
}
526
527
/*
528
* callout routines for InflateInitialize
529
*/
530
531
static int inflate_putbuffer( /* returns 0 on success */
532
void *stream, /* opaque ptr from Initialize */
533
unsigned char *buffer, /* buffer to put */
534
long length /* length of buffer */
535
)
536
{
537
RUNTIMECHECK;
538
539
/* If the write will go past the end of file, return an error */
540
if (ZS->outinf + length > ZS->usiz) return TRUE;
541
542
/* Update the CRC */
543
ZS->filecrc = CrcUpdate(ZS->filecrc, buffer, length);
544
545
/* Append to the buffer */
546
if (BufferAppend(ZS, buffer, length)) return TRUE;
547
548
/* Return success */
549
return FALSE;
550
}
551
552
static void *inflate_malloc(long length)
553
{
554
return malloc((size_t) length);
555
}
556
557
static void inflate_free(void *buffer)
558
{
559
free(buffer);
560
}
561
562
ZFILE *Zopen(const char *path, const char *mode)
563
{
564
struct ZipioState *zs;
565
566
long inplen;
567
568
/* Allocate the ZipioState memory area */
569
zs = (struct ZipioState *) malloc(sizeof(struct ZipioState));
570
if (!zs) return NULL;
571
572
/* Set up the initial values of the inflate state */
573
574
CACHEINIT;
575
576
RUNTIMEINIT;
577
578
zs->errorencountered = FALSE;
579
580
zs->inpinf = 0;
581
zs->outinf = 0;
582
583
zs->fileposition = 0;
584
585
zs->filecrc = 0xffffffffL;
586
587
/* Open the real file */
588
zs->OpenFile = fopen(path, mode);
589
if (!zs->OpenFile)
590
{
591
free(zs);
592
return NULL;
593
}
594
595
/* Read the first input buffer */
596
if ((inplen = (long) fread(zs->inpbuf, 1, INPBUFSIZE, zs->OpenFile)) >= 30)
597
{
598
GETUINT4(zs->inpbuf+ 0, zs->sign);
599
GETUINT2(zs->inpbuf+ 4, zs->vers);
600
GETUINT2(zs->inpbuf+ 6, zs->flag);
601
GETUINT2(zs->inpbuf+ 8, zs->comp);
602
GETUINT2(zs->inpbuf+10, zs->mtim);
603
GETUINT2(zs->inpbuf+12, zs->mdat);
604
GETUINT4(zs->inpbuf+14, zs->crc3);
605
GETUINT4(zs->inpbuf+18, zs->csiz);
606
GETUINT4(zs->inpbuf+22, zs->usiz);
607
GETUINT2(zs->inpbuf+26, zs->flen);
608
GETUINT2(zs->inpbuf+28, zs->elen);
609
610
#ifdef PRINTZIPHEADER
611
fprintf(stderr, "local file header signature hex %8lx\n", zs->sign);
612
fprintf(stderr, "version needed to extract %8d\n" , zs->vers);
613
fprintf(stderr, "general purpose bit flag hex %8x\n" , zs->flag);
614
fprintf(stderr, "compression method %8d\n" , zs->comp);
615
fprintf(stderr, "last mod file time %8d\n" , zs->mtim);
616
fprintf(stderr, "last mod file date %8d\n" , zs->mdat);
617
fprintf(stderr, "crc-32 hex %8lx\n", zs->crc3);
618
fprintf(stderr, "compressed size %8ld\n", zs->csiz);
619
fprintf(stderr, "uncompressed size %8ld\n", zs->usiz);
620
fprintf(stderr, "filename length %8d\n" , zs->flen);
621
fprintf(stderr, "extra field length %8d\n" , zs->elen);
622
#endif
623
}
624
else
625
{
626
zs->sign = 0;
627
}
628
629
/*
630
* If the file isn't a zip file, set up to read it normally
631
*/
632
if ((zs->sign != ZIPSIGNATURE) ||
633
(zs->flag & 1) ||
634
(zs->comp != 8) ||
635
(inplen <= 30 + zs->flen + zs->elen) )
636
{
637
/* Initialize buffering */
638
BufferInitialize(zs, FALSE);
639
640
zs->inflatestate = NULL;
641
}
642
else
643
{
644
/* Initialize buffering */
645
BufferInitialize(zs, TRUE);
646
647
zs->inflatestate = InflateInitialize(
648
(void *) zs,
649
inflate_putbuffer,
650
inflate_malloc,
651
inflate_free
652
);
653
654
if (InflatePutBuffer(zs->inflatestate,
655
zs->inpbuf+30+zs->flen+zs->elen,
656
inplen-30-zs->flen-zs->elen
657
)
658
)
659
zs->errorencountered = TRUE;
660
661
zs->inpinf += inplen-30-zs->flen-zs->elen;
662
}
663
664
/* Return this state info to the caller */
665
return (ZFILE *) zs;
666
}
667
668
int _Zgetc(ZFILE *stream)
669
{
670
long offset, length;
671
672
int off;
673
674
RUNTIMECHECK;
675
676
if (ZS->errorencountered) return -1;
677
678
CACHEUPDATE;
679
680
/* If already at EOF, return */
681
if (ZS->fileposition >= ZS->usiz) return -1;
682
683
/* If data isn't in current outbuf, get it */
684
offset = ZS->fileposition & ~((long) (OUTBUFSIZE-1));
685
length = ZS->usiz - offset;
686
if (length > OUTBUFSIZE) length = OUTBUFSIZE;
687
688
if (ZS->getoff != offset)
689
{
690
if (BufferRead(ZS, offset, ZS->getbuf, length)) return -1;
691
692
ZS->getoff = offset;
693
}
694
695
/* Set up the cache */
696
off = (int) (ZS->fileposition & (OUTBUFSIZE-1));
697
ZS->len = (int) (length - off);
698
ZS->ptr = ZS->getbuf + off;
699
700
/* Return the character */
701
ZS->len--;
702
return *(ZS->ptr++);
703
}
704
705
size_t Zread(void *ptr, size_t size, size_t n, ZFILE *stream)
706
{
707
long length;
708
709
RUNTIMECHECK;
710
711
if (ZS->errorencountered) return 0;
712
713
CACHEUPDATE;
714
715
/* Compute the length requested */
716
length = size * (long) n;
717
718
/* Adjust the length to account for premature EOF */
719
if (ZS->fileposition+length > ZS->usiz)
720
length = ZS->usiz - ZS->fileposition;
721
722
/* If the length is zero, then just return an EOF error */
723
if (length <= 0) return 0;
724
725
/* Make the length a multiple of size */
726
length /= size;
727
length *= size;
728
729
/* If the length is zero, then just return an EOF error */
730
if (length <= 0) return 0;
731
732
/* Read from the buffer */
733
if (BufferRead(ZS, ZS->fileposition, (unsigned char *) ptr, length))
734
return 0;
735
736
/* Update the file position */
737
ZS->fileposition += length;
738
739
/* Return the number of items transferred */
740
return (size_t) (length / size);
741
}
742
743
int Zseek(ZFILE *stream, long offset, int whence)
744
{
745
long newoffset;
746
747
RUNTIMECHECK;
748
749
if (ZS->errorencountered) return -1;
750
751
CACHEUPDATE;
752
753
if (whence == SEEK_SET)
754
{
755
newoffset = offset;
756
}
757
else if (whence == SEEK_CUR)
758
{
759
newoffset = ZS->fileposition + offset;
760
}
761
else if (whence == SEEK_END)
762
{
763
newoffset = ZS->fileposition + ZS->usiz;
764
}
765
else
766
{
767
return -1;
768
}
769
770
if ((newoffset < 0) || (newoffset > ZS->usiz)) return -1;
771
772
ZS->fileposition = newoffset;
773
774
return 0;
775
}
776
777
long Ztell(ZFILE *stream)
778
{
779
RUNTIMECHECK;
780
781
if (ZS->errorencountered) return -1;
782
783
CACHEUPDATE;
784
785
return ZS->fileposition;
786
}
787
788
int Zclose(ZFILE *stream)
789
{
790
int ret;
791
792
RUNTIMECHECK;
793
794
CACHEUPDATE;
795
796
/* terminate the inflate routines, and check for errors */
797
if (ZS->inflatestate)
798
{
799
if (InflateTerminate(ZS->inflatestate))
800
ZS->errorencountered = TRUE;
801
802
/* Check that the CRC is OK */
803
if (ZS->filecrc != (ZS->crc3 ^ 0xffffffffL))
804
ZS->errorencountered = TRUE;
805
}
806
807
/* save the final error status */
808
ret = ZS->errorencountered;
809
810
/* terminate the buffering */
811
BufferTerminate(ZS);
812
813
/* free the ZipioState structure */
814
free(ZS);
815
816
/* return the final error status */
817
return ret;
818
}
819
820