Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F423187
zipio.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
zipio.c
View Options
/*
* zipio.c - stdio emulation library for reading zip files
*
* Version 1.1.2
*/
/*
* Copyright (C) 1995, Edward B. Hamrick
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the copyright holders
* not be used in advertising or publicity pertaining to distribution of
* the software without specific, written prior permission. The copyright
* holders makes no representations about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
* IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
/*
* Changes from 1.1 to 1.1.1:
* Changed "z*" functions to "Z*" to avoid namespace pollution.
* Added "zungetc" macro.
* Added definitions of SEEK_SET, SEEK_CUR, SEEK_END for the Posixly challenged
* John Cowan <cowan@ccil.org>
*
* Changes from 1.1.1 to 1.1.2:
* Relicensed under the MIT license, with consent of the copyright holders.
* Avoid usage of unitialized "length" variable in _Zgetc
* Claudio Matsuoka (Jan 11 2011)
*/
/*
* Refer to zipio.h for a description of this package.
*/
/*
* The .zip file header is described below. It consists of
* 30 fixed bytes, followed by two variable length fields
* whose length is contained in the first 30 bytes. After this
* header, the data is stored (in deflate format if the compression
* method is 8).
*
* The crc-32 field is the crc on the uncompressed data.
*
* .zip file header:
*
* local file header signature 4 bytes (0x04034b50)
* version needed to extract 2 bytes
* general purpose bit flag 2 bytes
* compression method 2 bytes
* last mod file time 2 bytes
* last mod file date 2 bytes
* crc-32 4 bytes
* compressed size 4 bytes
* uncompressed size 4 bytes
* filename length 2 bytes
* extra field length 2 bytes
*
* filename (variable size)
* extra field (variable size)
*
* These fields are described in more detail in appnote.txt
* in the pkzip 1.93 distribution.
*/
#include
<stdlib.h>
#ifdef MEMCPY
#include
<mem.h>
#endif
#include
"zipio.h"
#include
"inflate.h"
#include
"crc.h"
/*
* Macros for constants
*/
#ifndef NULL
#define NULL ((void *) 0)
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef ZIPSIGNATURE
#define ZIPSIGNATURE 0x04034b50L
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
/*
* Buffer size macros
*
* The following constants are optimized for large-model
* (but not flat model) Windows with virtual memory. It
* will work fine on unix and flat model Windows as well.
*
* The constant BUFFERTHRESHOLD determines when memory
* buffering changes to file buffering.
*
* Assumptions:
*
* 1) INPBUFSIZE + OUTBUFSIZE + sizeof(void *) * PTRBUFSIZE + delta < 64K
*
* 2) OUTBUFSIZE = 32K * N (related to inflate's 32K window size)
*
* 2) Max in-memory file size is OUTBUFSIZE * PTRBUFSIZE
* which is 64 MBytes by default (32K * 2K).
*
*/
#ifndef BUFFERTHRESHOLD
#define BUFFERTHRESHOLD (256 * 1024L)
#endif
#ifndef INPBUFSIZE
#define INPBUFSIZE ( 8 * 1024 )
#endif
#ifndef PTRBUFSIZE
#define PTRBUFSIZE ( 2 * 1024 )
#endif
#ifndef OUTBUFSIZE
#define OUTBUFSIZE ((unsigned int) ( 32 * 1024L))
#endif
#define MAXFILESIZE (OUTBUFSIZE * (long) PTRBUFSIZE)
/*
* Macro for short-hand reference to ZipioState (from ZFILE *)
*/
#define ZS ((struct ZipioState *) stream)
/*
* Macro to manipulate Zgetc() cache
*/
#define CACHEINIT \
zs->ptr = NULL; \
zs->len = 0;
#define CACHEUPDATE \
if (ZS->ptr) \
{ \
ZS->fileposition &= ~((long) (OUTBUFSIZE-1)); \
ZS->fileposition += ZS->ptr - ZS->getbuf; \
ZS->ptr = NULL; \
} \
ZS->len = 0;
/*
* Macros for run-time type identification
*/
#ifndef RUNTIMEENABLE
#define RUNTIMEENABLE 0
#endif
#if RUNTIMEENABLE
#define ZIPIOSTATETYPE 0x0110f00fL
#define RUNTIMEINIT \
zs->runtimetypeid1 = ZIPIOSTATETYPE; \
zs->runtimetypeid2 = ZIPIOSTATETYPE;
#define RUNTIMECHECK \
if (!ZS || (ZS->runtimetypeid1 != ZIPIOSTATETYPE) \
|| (ZS->runtimetypeid2 != ZIPIOSTATETYPE)) return -1;
#else
#define RUNTIMEINIT
#define RUNTIMECHECK
#endif
/*
* Macros for converting bytes to unsigned integers
*/
#define GETUINT4(ptr, i4) \
{ \
i4 = (((unsigned long) *(((unsigned char *) (ptr)) + 0)) ) | \
(((unsigned long) *(((unsigned char *) (ptr)) + 1)) << 8) | \
(((unsigned long) *(((unsigned char *) (ptr)) + 2)) << 16) | \
(((unsigned long) *(((unsigned char *) (ptr)) + 3)) << 24) ; \
}
#define GETUINT2(ptr, i2) \
{ \
i2 = (((unsigned int) *(((unsigned char *) (ptr)) + 0)) ) | \
(((unsigned int) *(((unsigned char *) (ptr)) + 1)) << 8) ; \
}
/* Structure to hold state for decoding zip files */
struct
ZipioState
{
/* Fields overlaid with ZFILE structure */
int
len
;
/* length of Zgetc cache */
unsigned
char
*
ptr
;
/* pointer to Zgetc cache */
/* Fields invisible to users of ZFILE structure */
unsigned
long
runtimetypeid1
;
/* to detect run-time errors */
int
errorencountered
;
/* error encountered flag */
/* Buffering state */
unsigned
char
inpbuf
[
INPBUFSIZE
];
/* inp buffer from zip file */
unsigned
char
*
ptrbuf
[
PTRBUFSIZE
];
/* pointers to in-memory bufs */
unsigned
char
getbuf
[
OUTBUFSIZE
];
/* buffer for use by Zgetc */
long
getoff
;
/* starting offset of getbuf */
FILE
*
tmpfil
;
/* file ptr to temp file */
/* Amount of input data inflated */
unsigned
long
inpinf
;
unsigned
long
outinf
;
/* Zip file header */
unsigned
long
sign
;
/* local file header signature (0x04034b50) */
unsigned
int
vers
;
/* version needed to extract 2 bytes */
unsigned
int
flag
;
/* general purpose bit flag 2 bytes */
unsigned
int
comp
;
/* compression method 2 bytes */
unsigned
int
mtim
;
/* last mod file time 2 bytes */
unsigned
int
mdat
;
/* last mod file date 2 bytes */
unsigned
long
crc3
;
/* crc-32 4 bytes */
unsigned
long
csiz
;
/* compressed size 4 bytes */
unsigned
long
usiz
;
/* uncompressed size 4 bytes */
unsigned
int
flen
;
/* filename length 2 bytes */
unsigned
int
elen
;
/* extra field length 2 bytes */
/* Application state */
FILE
*
OpenFile
;
/* currently open file */
void
*
inflatestate
;
/* current state for inflate */
unsigned
long
fileposition
;
/* current file position */
unsigned
long
filecrc
;
/* current crc */
unsigned
long
runtimetypeid2
;
/* to detect run-time errors */
};
/*
* Utility routines to handle uncompressed file buffers
*/
/* Initialize buffering */
static
void
BufferInitialize
(
struct
ZipioState
*
zs
,
int
doinflate
)
{
zs
->
getoff
=
-1
;
zs
->
tmpfil
=
NULL
;
/*
* If not inflating, use the input file
*/
if
(
!
doinflate
)
{
zs
->
tmpfil
=
zs
->
OpenFile
;
/* Get the uncompressed file size */
fseek
(
zs
->
tmpfil
,
0
,
SEEK_END
);
zs
->
usiz
=
ftell
(
zs
->
tmpfil
);
zs
->
outinf
=
zs
->
usiz
;
/* Start at the beginning */
fseek
(
zs
->
tmpfil
,
0
,
SEEK_SET
);
}
/* If there's no file open, see if it's big enough for temp file */
if
(
!
zs
->
tmpfil
)
{
if
(
zs
->
usiz
>=
BUFFERTHRESHOLD
)
zs
->
tmpfil
=
tmpfile
();
}
/* If there's no file open, then use memory buffering */
if
(
!
zs
->
tmpfil
)
{
int
i
;
for
(
i
=
0
;
i
<
PTRBUFSIZE
;
i
++
)
zs
->
ptrbuf
[
i
]
=
NULL
;
}
}
/* pump data till length bytes of file are inflated or error encountered */
static
int
BufferPump
(
struct
ZipioState
*
zs
,
long
length
)
{
size_t
inplen
,
ret
;
/* Check to see if the length is valid */
if
(
length
>
zs
->
usiz
)
return
TRUE
;
/* Loop till enough data is pumped */
while
(
!
zs
->
errorencountered
&&
(
zs
->
outinf
<
length
))
{
/* Compute how much data to read */
if
((
zs
->
csiz
-
zs
->
inpinf
)
<
INPBUFSIZE
)
inplen
=
(
size_t
)
(
zs
->
csiz
-
zs
->
inpinf
);
else
inplen
=
INPBUFSIZE
;
if
(
inplen
<=
0
)
return
TRUE
;
/* Read some data from the file */
ret
=
fread
(
zs
->
inpbuf
,
1
,
inplen
,
zs
->
OpenFile
);
if
(
ret
!=
inplen
)
return
TRUE
;
/* Update how much data has been read from the file */
zs
->
inpinf
+=
inplen
;
/* Pump this data into the decompressor */
if
(
InflatePutBuffer
(
zs
->
inflatestate
,
zs
->
inpbuf
,
inplen
))
return
TRUE
;
}
return
FALSE
;
}
/* Read from the buffer */
static
int
BufferRead
(
struct
ZipioState
*
zs
,
long
offset
,
unsigned
char
*
buffer
,
long
length
)
{
/*
* Make sure enough bytes have been inflated
* Note that the correction for reading past EOF has to
* be done before calling this routine
*/
if
(
BufferPump
(
zs
,
offset
+
length
))
return
TRUE
;
/* If using file buffering, just get the data from the file */
if
(
zs
->
tmpfil
)
{
if
(
fseek
(
zs
->
tmpfil
,
offset
,
SEEK_SET
))
return
TRUE
;
if
(
fread
(
buffer
,
1
,
(
size_t
)
length
,
zs
->
tmpfil
)
!=
length
)
return
TRUE
;
}
/* If no temp file, use memory buffering */
else
{
unsigned
int
i
;
unsigned
int
off
,
len
;
unsigned
char
*
ptr
;
long
tmpoff
;
unsigned
char
*
tmpbuf
;
long
tmplen
;
/* Save copies of offset, buffer and length for the loop */
tmpoff
=
offset
;
tmpbuf
=
buffer
;
tmplen
=
length
;
/* Validate the transfer */
if
(
tmpoff
+
tmplen
>
MAXFILESIZE
)
return
TRUE
;
/* Loop till done */
while
(
tmplen
)
{
/* Get a pointer to the next block */
i
=
(
unsigned
int
)
(
tmpoff
/
OUTBUFSIZE
);
ptr
=
zs
->
ptrbuf
[
i
];
if
(
!
ptr
)
return
TRUE
;
/* Get the offset,length for this block */
off
=
(
unsigned
int
)
(
tmpoff
&
(
OUTBUFSIZE
-1
));
len
=
OUTBUFSIZE
-
off
;
if
(
len
>
tmplen
)
len
=
(
unsigned
int
)
tmplen
;
/* Get the starting pointer for the transfer */
ptr
+=
off
;
/* Copy the data for this block */
#ifdef MEMCPY
memcpy
(
tmpbuf
,
ptr
,
len
);
#else
for
(
i
=
0
;
i
<
len
;
i
++
)
tmpbuf
[
i
]
=
ptr
[
i
];
#endif
/* Update the offset, buffer, and length */
tmpoff
+=
len
;
tmpbuf
+=
len
;
tmplen
-=
len
;
}
}
/* return success */
return
FALSE
;
}
/* Append to the buffer */
static
int
BufferAppend
(
struct
ZipioState
*
zs
,
unsigned
char
*
buffer
,
long
length
)
{
/* If using file buffering, just append the data from the file */
if
(
zs
->
tmpfil
)
{
if
(
fseek
(
zs
->
tmpfil
,
zs
->
outinf
,
SEEK_SET
))
return
TRUE
;
if
(
fwrite
(
buffer
,
1
,
(
size_t
)
length
,
zs
->
tmpfil
)
!=
length
)
return
TRUE
;
}
/* If no temp file, use memory buffering */
else
{
unsigned
int
i
;
unsigned
int
off
,
len
;
unsigned
char
*
ptr
;
long
tmpoff
;
unsigned
char
*
tmpbuf
;
long
tmplen
;
/* Save copies of outinf, buffer and length for the loop */
tmpoff
=
zs
->
outinf
;
tmpbuf
=
buffer
;
tmplen
=
length
;
/* Validate the transfer */
if
(
tmpoff
+
tmplen
>
MAXFILESIZE
)
return
TRUE
;
/* Loop till done */
while
(
tmplen
)
{
/* Get a pointer to the next block */
i
=
(
unsigned
int
)
(
tmpoff
/
OUTBUFSIZE
);
ptr
=
zs
->
ptrbuf
[
i
];
if
(
!
ptr
)
{
ptr
=
(
unsigned
char
*
)
malloc
(
OUTBUFSIZE
);
if
(
!
ptr
)
return
TRUE
;
zs
->
ptrbuf
[
i
]
=
ptr
;
}
/* Get the offset,length for this block */
off
=
(
unsigned
int
)
(
tmpoff
&
(
OUTBUFSIZE
-1
));
len
=
OUTBUFSIZE
-
off
;
if
(
len
>
tmplen
)
len
=
(
unsigned
int
)
tmplen
;
/* Get the starting pointer for the transfer */
ptr
+=
off
;
/* Copy the data for this block */
#ifdef MEMCPY
memcpy
(
ptr
,
tmpbuf
,
len
);
#else
for
(
i
=
0
;
i
<
len
;
i
++
)
ptr
[
i
]
=
tmpbuf
[
i
];
#endif
/* Update the offset, buffer, and length */
tmpoff
+=
len
;
tmpbuf
+=
len
;
tmplen
-=
len
;
}
}
/* Update the output buffer length */
zs
->
outinf
+=
length
;
/* return success */
return
FALSE
;
}
/* Terminate buffering */
static
void
BufferTerminate
(
struct
ZipioState
*
zs
)
{
/* If reading directly from the uncompressed file, just mark with NULL */
if
(
zs
->
tmpfil
==
zs
->
OpenFile
)
{
zs
->
tmpfil
=
NULL
;
}
/* If using the a temporary file, close it */
else
if
(
zs
->
tmpfil
)
{
fclose
(
zs
->
tmpfil
);
zs
->
tmpfil
=
NULL
;
}
/* If doing memory buffering, free the buffers */
else
{
int
i
;
for
(
i
=
0
;
i
<
PTRBUFSIZE
;
i
++
)
if
(
zs
->
ptrbuf
[
i
])
free
(
zs
->
ptrbuf
[
i
]);
}
}
/*
* callout routines for InflateInitialize
*/
static
int
inflate_putbuffer
(
/* returns 0 on success */
void
*
stream
,
/* opaque ptr from Initialize */
unsigned
char
*
buffer
,
/* buffer to put */
long
length
/* length of buffer */
)
{
RUNTIMECHECK
;
/* If the write will go past the end of file, return an error */
if
(
ZS
->
outinf
+
length
>
ZS
->
usiz
)
return
TRUE
;
/* Update the CRC */
ZS
->
filecrc
=
CrcUpdate
(
ZS
->
filecrc
,
buffer
,
length
);
/* Append to the buffer */
if
(
BufferAppend
(
ZS
,
buffer
,
length
))
return
TRUE
;
/* Return success */
return
FALSE
;
}
static
void
*
inflate_malloc
(
long
length
)
{
return
malloc
((
size_t
)
length
);
}
static
void
inflate_free
(
void
*
buffer
)
{
free
(
buffer
);
}
ZFILE
*
Zopen
(
const
char
*
path
,
const
char
*
mode
)
{
struct
ZipioState
*
zs
;
long
inplen
;
/* Allocate the ZipioState memory area */
zs
=
(
struct
ZipioState
*
)
malloc
(
sizeof
(
struct
ZipioState
));
if
(
!
zs
)
return
NULL
;
/* Set up the initial values of the inflate state */
CACHEINIT
;
RUNTIMEINIT
;
zs
->
errorencountered
=
FALSE
;
zs
->
inpinf
=
0
;
zs
->
outinf
=
0
;
zs
->
fileposition
=
0
;
zs
->
filecrc
=
0xffffffffL
;
/* Open the real file */
zs
->
OpenFile
=
fopen
(
path
,
mode
);
if
(
!
zs
->
OpenFile
)
{
free
(
zs
);
return
NULL
;
}
/* Read the first input buffer */
if
((
inplen
=
(
long
)
fread
(
zs
->
inpbuf
,
1
,
INPBUFSIZE
,
zs
->
OpenFile
))
>=
30
)
{
GETUINT4
(
zs
->
inpbuf
+
0
,
zs
->
sign
);
GETUINT2
(
zs
->
inpbuf
+
4
,
zs
->
vers
);
GETUINT2
(
zs
->
inpbuf
+
6
,
zs
->
flag
);
GETUINT2
(
zs
->
inpbuf
+
8
,
zs
->
comp
);
GETUINT2
(
zs
->
inpbuf
+
10
,
zs
->
mtim
);
GETUINT2
(
zs
->
inpbuf
+
12
,
zs
->
mdat
);
GETUINT4
(
zs
->
inpbuf
+
14
,
zs
->
crc3
);
GETUINT4
(
zs
->
inpbuf
+
18
,
zs
->
csiz
);
GETUINT4
(
zs
->
inpbuf
+
22
,
zs
->
usiz
);
GETUINT2
(
zs
->
inpbuf
+
26
,
zs
->
flen
);
GETUINT2
(
zs
->
inpbuf
+
28
,
zs
->
elen
);
#ifdef PRINTZIPHEADER
fprintf
(
stderr
,
"local file header signature hex %8lx
\n
"
,
zs
->
sign
);
fprintf
(
stderr
,
"version needed to extract %8d
\n
"
,
zs
->
vers
);
fprintf
(
stderr
,
"general purpose bit flag hex %8x
\n
"
,
zs
->
flag
);
fprintf
(
stderr
,
"compression method %8d
\n
"
,
zs
->
comp
);
fprintf
(
stderr
,
"last mod file time %8d
\n
"
,
zs
->
mtim
);
fprintf
(
stderr
,
"last mod file date %8d
\n
"
,
zs
->
mdat
);
fprintf
(
stderr
,
"crc-32 hex %8lx
\n
"
,
zs
->
crc3
);
fprintf
(
stderr
,
"compressed size %8ld
\n
"
,
zs
->
csiz
);
fprintf
(
stderr
,
"uncompressed size %8ld
\n
"
,
zs
->
usiz
);
fprintf
(
stderr
,
"filename length %8d
\n
"
,
zs
->
flen
);
fprintf
(
stderr
,
"extra field length %8d
\n
"
,
zs
->
elen
);
#endif
}
else
{
zs
->
sign
=
0
;
}
/*
* If the file isn't a zip file, set up to read it normally
*/
if
((
zs
->
sign
!=
ZIPSIGNATURE
)
||
(
zs
->
flag
&
1
)
||
(
zs
->
comp
!=
8
)
||
(
inplen
<=
30
+
zs
->
flen
+
zs
->
elen
)
)
{
/* Initialize buffering */
BufferInitialize
(
zs
,
FALSE
);
zs
->
inflatestate
=
NULL
;
}
else
{
/* Initialize buffering */
BufferInitialize
(
zs
,
TRUE
);
zs
->
inflatestate
=
InflateInitialize
(
(
void
*
)
zs
,
inflate_putbuffer
,
inflate_malloc
,
inflate_free
);
if
(
InflatePutBuffer
(
zs
->
inflatestate
,
zs
->
inpbuf
+
30
+
zs
->
flen
+
zs
->
elen
,
inplen
-30
-
zs
->
flen
-
zs
->
elen
)
)
zs
->
errorencountered
=
TRUE
;
zs
->
inpinf
+=
inplen
-30
-
zs
->
flen
-
zs
->
elen
;
}
/* Return this state info to the caller */
return
(
ZFILE
*
)
zs
;
}
int
_Zgetc
(
ZFILE
*
stream
)
{
long
offset
,
length
;
int
off
;
RUNTIMECHECK
;
if
(
ZS
->
errorencountered
)
return
-1
;
CACHEUPDATE
;
/* If already at EOF, return */
if
(
ZS
->
fileposition
>=
ZS
->
usiz
)
return
-1
;
/* If data isn't in current outbuf, get it */
offset
=
ZS
->
fileposition
&
~
((
long
)
(
OUTBUFSIZE
-1
));
length
=
ZS
->
usiz
-
offset
;
if
(
length
>
OUTBUFSIZE
)
length
=
OUTBUFSIZE
;
if
(
ZS
->
getoff
!=
offset
)
{
if
(
BufferRead
(
ZS
,
offset
,
ZS
->
getbuf
,
length
))
return
-1
;
ZS
->
getoff
=
offset
;
}
/* Set up the cache */
off
=
(
int
)
(
ZS
->
fileposition
&
(
OUTBUFSIZE
-1
));
ZS
->
len
=
(
int
)
(
length
-
off
);
ZS
->
ptr
=
ZS
->
getbuf
+
off
;
/* Return the character */
ZS
->
len
--
;
return
*
(
ZS
->
ptr
++
);
}
size_t
Zread
(
void
*
ptr
,
size_t
size
,
size_t
n
,
ZFILE
*
stream
)
{
long
length
;
RUNTIMECHECK
;
if
(
ZS
->
errorencountered
)
return
0
;
CACHEUPDATE
;
/* Compute the length requested */
length
=
size
*
(
long
)
n
;
/* Adjust the length to account for premature EOF */
if
(
ZS
->
fileposition
+
length
>
ZS
->
usiz
)
length
=
ZS
->
usiz
-
ZS
->
fileposition
;
/* If the length is zero, then just return an EOF error */
if
(
length
<=
0
)
return
0
;
/* Make the length a multiple of size */
length
/=
size
;
length
*=
size
;
/* If the length is zero, then just return an EOF error */
if
(
length
<=
0
)
return
0
;
/* Read from the buffer */
if
(
BufferRead
(
ZS
,
ZS
->
fileposition
,
(
unsigned
char
*
)
ptr
,
length
))
return
0
;
/* Update the file position */
ZS
->
fileposition
+=
length
;
/* Return the number of items transferred */
return
(
size_t
)
(
length
/
size
);
}
int
Zseek
(
ZFILE
*
stream
,
long
offset
,
int
whence
)
{
long
newoffset
;
RUNTIMECHECK
;
if
(
ZS
->
errorencountered
)
return
-1
;
CACHEUPDATE
;
if
(
whence
==
SEEK_SET
)
{
newoffset
=
offset
;
}
else
if
(
whence
==
SEEK_CUR
)
{
newoffset
=
ZS
->
fileposition
+
offset
;
}
else
if
(
whence
==
SEEK_END
)
{
newoffset
=
ZS
->
fileposition
+
ZS
->
usiz
;
}
else
{
return
-1
;
}
if
((
newoffset
<
0
)
||
(
newoffset
>
ZS
->
usiz
))
return
-1
;
ZS
->
fileposition
=
newoffset
;
return
0
;
}
long
Ztell
(
ZFILE
*
stream
)
{
RUNTIMECHECK
;
if
(
ZS
->
errorencountered
)
return
-1
;
CACHEUPDATE
;
return
ZS
->
fileposition
;
}
int
Zclose
(
ZFILE
*
stream
)
{
int
ret
;
RUNTIMECHECK
;
CACHEUPDATE
;
/* terminate the inflate routines, and check for errors */
if
(
ZS
->
inflatestate
)
{
if
(
InflateTerminate
(
ZS
->
inflatestate
))
ZS
->
errorencountered
=
TRUE
;
/* Check that the CRC is OK */
if
(
ZS
->
filecrc
!=
(
ZS
->
crc3
^
0xffffffffL
))
ZS
->
errorencountered
=
TRUE
;
}
/* save the final error status */
ret
=
ZS
->
errorencountered
;
/* terminate the buffering */
BufferTerminate
(
ZS
);
/* free the ZipioState structure */
free
(
ZS
);
/* return the final error status */
return
ret
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, May 2, 1:43 PM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
57066
Default Alt Text
zipio.c (20 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment