1
- // JUnzip library by Joonas Pihlajamaa. See junzip.h for license and details.
1
+ // Unzip library by Per Bothner and Joonas Pihlajamaa.
2
+ // See junzip.h for license and details.
2
3
3
- #include <stdio.h>
4
4
#include <stdlib.h>
5
5
#include <string.h>
6
6
7
7
#include <zlib.h>
8
8
9
9
#include "junzip.h"
10
10
11
- int
11
+ #define ZIP_CENTRAL_SIGNATURE 0
12
+ #define ZIP_CENTRAL_VERSION_MADE_BY 4
13
+ #define ZIP_CENTRAL_VERSION_NEEDED_TO_EXTRACT 6
14
+ #define ZIP_CENTRAL_GENERAL_PURPOSE_BIT_FLAG 8
15
+ #define ZIP_CENTRAL_COMPRESSION_METHOD 10
16
+ #define ZIP_CENTRAL_LAST_MOD_FILE_TIME 12
17
+ #define ZIP_CENTRAL_LAST_MOD_FILE_DATE 14
18
+ #define ZIP_CENTRAL_CRC32 16
19
+ #define ZIP_CENTRAL_COMPRESSED_SIZE 20
20
+ #define ZIP_CENTRAL_UNCOMPRESSED_SIZE 24
21
+ #define ZIP_CENTRAL_FILE_NAME_LENGTH 28
22
+ #define ZIP_CENTRAL_EXTRA_FIELD_LENGTH 30
23
+ #define ZIP_CENTRAL_FILE_COMMENT_LENGTH 32
24
+ #define ZIP_CENTRAL_DISK_NUMBER_START 34
25
+ #define ZIP_CENTRAL_INTERNAL_FILE_ATTRIBUTES 36
26
+ #define ZIP_CENTRAL_EXTERNAL_FILE_ATTRIBUTES 38
27
+ #define ZIP_CENTRAL_RELATIVE_OFFSET_OF_LOCAL_HEADER 42
28
+ #define ZIP_CENTRAL_DIRECTORY_LENGTH 46
29
+
30
+ #define ZIP_END_SIGNATURE_OFFSET 0
31
+ #define ZIP_END_DESK_NUMBER 4
32
+ #define ZIP_END_CENTRAL_DIRECTORY_DISK_NUMBER 6
33
+ #define ZIP_END_NUM_ENTRIES_THIS_DISK 8
34
+ #define ZIP_END_NUM_ENTRIES 10
35
+ #define ZIP_END_CENTRAL_DIRECTORY_SIZE 12
36
+ #define ZIP_END_CENTRAL_DIRECTORY_OFFSET 16
37
+ #define ZIP_END_ZIP_COMMENT_LENGTH 20
38
+ #define ZIP_END_DIRECTORY_LENGTH 22
39
+
40
+ #define get_u16 (PTR ) ((PTR)[0] | ((PTR)[1] << 8))
41
+ #define get_u32 (PTR ) ((PTR)[0] | ((PTR)[1]<<8) | ((PTR)[2]<<16) | ((PTR)[3]<<24))
42
+
43
+ static int
12
44
zf_seek_set (JZFile * zfile , size_t offset )
13
45
{
14
46
int new_position = offset ;
@@ -18,7 +50,7 @@ zf_seek_set(JZFile *zfile, size_t offset)
18
50
return 0 ;
19
51
}
20
52
21
- int
53
+ static int
22
54
zf_seek_cur (JZFile * zfile , size_t offset )
23
55
{
24
56
int new_position = zfile -> position + offset ;
@@ -28,7 +60,7 @@ zf_seek_cur(JZFile *zfile, size_t offset)
28
60
return 0 ;
29
61
}
30
62
31
- int
63
+ static int
32
64
zf_seek_end (JZFile * zfile , size_t offset )
33
65
{
34
66
int new_position = zfile -> length + offset ;
@@ -53,14 +85,12 @@ int jzReadEndRecord(JZFile *zip) {
53
85
long fileSize , readBytes , i ;
54
86
55
87
if (zf_seek_end (zip , - ZIP_END_DIRECTORY_LENGTH )) {
56
- fprintf (stderr , "Too small file to be a zip!" );
57
88
return Z_ERRNO ;
58
89
}
59
90
60
91
unsigned char * ptr = zf_current (zip );
61
92
while (ptr [0 ] != 0x50 || ptr [1 ] != 0x4B || ptr [2 ] != 0x05 || ptr [3 ] != 0x06 ) {
62
93
if (ptr == zip -> start ) {
63
- fprintf (stderr , "End record signature not found in zip!" );
64
94
return Z_ERRNO ;
65
95
}
66
96
ptr -- ;
@@ -70,7 +100,6 @@ int jzReadEndRecord(JZFile *zip) {
70
100
if (get_u16 (ptr + ZIP_END_DESK_NUMBER )
71
101
|| get_u16 (ptr + ZIP_END_CENTRAL_DIRECTORY_DISK_NUMBER )
72
102
|| zip -> numEntries != get_u16 (ptr + ZIP_END_NUM_ENTRIES_THIS_DISK )) {
73
- fprintf (stderr , "Multifile zips not supported!" );
74
103
return Z_ERRNO ;
75
104
}
76
105
@@ -83,19 +112,16 @@ int jzReadCentralDirectory(JZFile *zip, JZRecordCallback callback) {
83
112
int i ;
84
113
85
114
if (zf_seek_set (zip , zip -> centralDirectoryOffset )) {
86
- fprintf (stderr , "Cannot seek in zip file!" );
87
115
return Z_ERRNO ;
88
116
}
89
117
90
118
for (i = 0 ; i < zip -> numEntries ; i ++ ) {
91
119
unsigned char * ptr = zf_current (zip );
92
120
if (zf_available (zip ) < ZIP_CENTRAL_DIRECTORY_LENGTH ) {
93
- fprintf (stderr , "Couldn't read file header %d!" , i );
94
121
return Z_ERRNO ;
95
122
}
96
123
zf_seek_cur (zip , ZIP_CENTRAL_DIRECTORY_LENGTH );
97
124
if (get_u32 (ptr + ZIP_CENTRAL_SIGNATURE ) != 0x02014B50 ) {
98
- fprintf (stderr , "Invalid file header signature %d!" , i );
99
125
return Z_ERRNO ;
100
126
}
101
127
// Construct JZFileHeader from global file header
@@ -109,7 +135,6 @@ int jzReadCentralDirectory(JZFile *zip, JZRecordCallback callback) {
109
135
110
136
header .fileNameStart = zf_tell (zip );
111
137
if (zf_seek_cur (zip , header .fileNameLength + header .extraFieldLength + get_u16 (ptr + ZIP_CENTRAL_FILE_COMMENT_LENGTH ))) {
112
- fprintf (stderr , "Couldn't skip extra field or file comment %d" , i );
113
138
return Z_ERRNO ;
114
139
}
115
140
@@ -120,6 +145,16 @@ int jzReadCentralDirectory(JZFile *zip, JZRecordCallback callback) {
120
145
return Z_OK ;
121
146
}
122
147
148
+ int jzSeekData (JZFile * zip , JZFileHeader * entry ) {
149
+ size_t offset = entry -> offset ;
150
+ offset += ZIP_LOCAL_FILE_HEADER_LENGTH ;
151
+ offset += entry -> fileNameLength + entry -> extraFieldLength ;
152
+ if (offset < 0 || offset > zip -> length )
153
+ return Z_STREAM_END ;
154
+ zip -> position = offset ;
155
+ return Z_OK ;
156
+ }
157
+
123
158
// Read data from file stream, described by header, to preallocated buffer
124
159
int jzReadData (JZFile * zip , JZFileHeader * header , void * buffer ) {
125
160
unsigned char * bytes = (unsigned char * )buffer ; // cast
@@ -128,10 +163,10 @@ int jzReadData(JZFile *zip, JZFileHeader *header, void *buffer) {
128
163
int ret ;
129
164
130
165
if (header -> compressionMethod == 0 ) { // Store - just read it
131
- if (zf_read (zip , buffer , header -> uncompressedSize ) <
166
+ if (zf_read (zip , buffer , header -> uncompressedSize ) <
132
167
header -> uncompressedSize )
133
168
return Z_ERRNO ;
134
- } else if (header -> compressionMethod == 8 ) { // Deflate - using zlib
169
+ } else if (header -> compressionMethod == 8 ) { // Deflate - using zlib
135
170
strm .zalloc = Z_NULL ;
136
171
strm .zfree = Z_NULL ;
137
172
strm .opaque = Z_NULL ;
@@ -140,11 +175,11 @@ int jzReadData(JZFile *zip, JZFileHeader *header, void *buffer) {
140
175
strm .next_in = Z_NULL ;
141
176
142
177
// Use inflateInit2 with negative window bits to indicate raw data
143
- if ((ret = inflateInit2 (& strm , - MAX_WBITS )) != Z_OK )
178
+ if ((ret = inflateInit2 (& strm , - MAX_WBITS )) != Z_OK )
144
179
return ret ; // Zlib errors are negative
145
180
146
181
// Inflate compressed data
147
- for (compressedLeft = header -> compressedSize ,
182
+ for (compressedLeft = header -> compressedSize ,
148
183
uncompressedLeft = header -> uncompressedSize ;
149
184
compressedLeft && uncompressedLeft && ret != Z_STREAM_END ;
150
185
compressedLeft -= strm .avail_in ) {
0 commit comments