diff options
author | Mark Adler <madler@alumni.caltech.edu> | 2011-09-09 23:23:45 -0700 |
---|---|---|
committer | Mark Adler <madler@alumni.caltech.edu> | 2011-09-09 23:23:45 -0700 |
commit | 7a6955760ba950eb82f57929f8f6c9847c65f0af (patch) | |
tree | e2cd657aca6d606e0b28bf57fe45e914717a334c /contrib/minizip/mztools.c | |
parent | f0e76a6634eb26e3ddc6dfc6f2489553eff8c8f4 (diff) | |
download | zlib-1.2.1.2.tar.gz zlib-1.2.1.2.tar.bz2 zlib-1.2.1.2.zip |
zlib 1.2.1.2v1.2.1.2
Diffstat (limited to 'contrib/minizip/mztools.c')
-rw-r--r-- | contrib/minizip/mztools.c | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/contrib/minizip/mztools.c b/contrib/minizip/mztools.c new file mode 100644 index 0000000..363ee13 --- /dev/null +++ b/contrib/minizip/mztools.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | Additional tools for Minizip | ||
3 | Code: Xavier Roche '2004 | ||
4 | License: Same as ZLIB (www.gzip.org) | ||
5 | */ | ||
6 | |||
7 | /* Code */ | ||
8 | #include <stdio.h> | ||
9 | #include <stdlib.h> | ||
10 | #include <string.h> | ||
11 | #include "zlib.h" | ||
12 | #include "unzip.h" | ||
13 | |||
14 | #define READ_8(adr) ((unsigned char)*(adr)) | ||
15 | #define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) | ||
16 | #define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) | ||
17 | |||
18 | #define WRITE_8(buff, n) do { \ | ||
19 | *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ | ||
20 | } while(0) | ||
21 | #define WRITE_16(buff, n) do { \ | ||
22 | WRITE_8((unsigned char*)(buff), n); \ | ||
23 | WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ | ||
24 | } while(0) | ||
25 | #define WRITE_32(buff, n) do { \ | ||
26 | WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ | ||
27 | WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ | ||
28 | } while(0) | ||
29 | |||
30 | extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) | ||
31 | const char* file; | ||
32 | const char* fileOut; | ||
33 | const char* fileOutTmp; | ||
34 | uLong* nRecovered; | ||
35 | uLong* bytesRecovered; | ||
36 | { | ||
37 | int err = Z_OK; | ||
38 | FILE* fpZip = fopen(file, "rb"); | ||
39 | FILE* fpOut = fopen(fileOut, "wb"); | ||
40 | FILE* fpOutCD = fopen(fileOutTmp, "wb"); | ||
41 | if (fpZip != NULL && fpOut != NULL) { | ||
42 | int entries = 0; | ||
43 | uLong totalBytes = 0; | ||
44 | char header[30]; | ||
45 | char filename[256]; | ||
46 | char extra[1024]; | ||
47 | int offset = 0; | ||
48 | int offsetCD = 0; | ||
49 | while ( fread(header, 1, 30, fpZip) == 30 ) { | ||
50 | int currentOffset = offset; | ||
51 | |||
52 | /* File entry */ | ||
53 | if (READ_32(header) == 0x04034b50) { | ||
54 | unsigned int version = READ_16(header + 4); | ||
55 | unsigned int gpflag = READ_16(header + 6); | ||
56 | unsigned int method = READ_16(header + 8); | ||
57 | unsigned int filetime = READ_16(header + 10); | ||
58 | unsigned int filedate = READ_16(header + 12); | ||
59 | unsigned int crc = READ_32(header + 14); /* crc */ | ||
60 | unsigned int cpsize = READ_32(header + 18); /* compressed size */ | ||
61 | unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ | ||
62 | unsigned int fnsize = READ_16(header + 26); /* file name length */ | ||
63 | unsigned int extsize = READ_16(header + 28); /* extra field length */ | ||
64 | filename[0] = extra[0] = '\0'; | ||
65 | |||
66 | /* Header */ | ||
67 | if (fwrite(header, 1, 30, fpOut) == 30) { | ||
68 | offset += 30; | ||
69 | } else { | ||
70 | err = Z_ERRNO; | ||
71 | break; | ||
72 | } | ||
73 | |||
74 | /* Filename */ | ||
75 | if (fnsize > 0) { | ||
76 | if (fread(filename, 1, fnsize, fpZip) == fnsize) { | ||
77 | if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { | ||
78 | offset += fnsize; | ||
79 | } else { | ||
80 | err = Z_ERRNO; | ||
81 | break; | ||
82 | } | ||
83 | } else { | ||
84 | err = Z_ERRNO; | ||
85 | break; | ||
86 | } | ||
87 | } else { | ||
88 | err = Z_STREAM_ERROR; | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | /* Extra field */ | ||
93 | if (extsize > 0) { | ||
94 | if (fread(extra, 1, extsize, fpZip) == extsize) { | ||
95 | if (fwrite(extra, 1, extsize, fpOut) == extsize) { | ||
96 | offset += extsize; | ||
97 | } else { | ||
98 | err = Z_ERRNO; | ||
99 | break; | ||
100 | } | ||
101 | } else { | ||
102 | err = Z_ERRNO; | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | /* Data */ | ||
108 | { | ||
109 | int dataSize = cpsize; | ||
110 | if (dataSize == 0) { | ||
111 | dataSize = uncpsize; | ||
112 | } | ||
113 | if (dataSize > 0) { | ||
114 | char* data = malloc(dataSize); | ||
115 | if (data != NULL) { | ||
116 | if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { | ||
117 | if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { | ||
118 | offset += dataSize; | ||
119 | totalBytes += dataSize; | ||
120 | } else { | ||
121 | err = Z_ERRNO; | ||
122 | } | ||
123 | } else { | ||
124 | err = Z_ERRNO; | ||
125 | } | ||
126 | free(data); | ||
127 | if (err != Z_OK) { | ||
128 | break; | ||
129 | } | ||
130 | } else { | ||
131 | err = Z_MEM_ERROR; | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /* Central directory entry */ | ||
138 | { | ||
139 | char header[46]; | ||
140 | char* comment = ""; | ||
141 | int comsize = (int) strlen(comment); | ||
142 | WRITE_32(header, 0x02014b50); | ||
143 | WRITE_16(header + 4, version); | ||
144 | WRITE_16(header + 6, version); | ||
145 | WRITE_16(header + 8, gpflag); | ||
146 | WRITE_16(header + 10, method); | ||
147 | WRITE_16(header + 12, filetime); | ||
148 | WRITE_16(header + 14, filedate); | ||
149 | WRITE_32(header + 16, crc); | ||
150 | WRITE_32(header + 20, cpsize); | ||
151 | WRITE_32(header + 24, uncpsize); | ||
152 | WRITE_16(header + 28, fnsize); | ||
153 | WRITE_16(header + 30, extsize); | ||
154 | WRITE_16(header + 32, comsize); | ||
155 | WRITE_16(header + 34, 0); /* disk # */ | ||
156 | WRITE_16(header + 36, 0); /* int attrb */ | ||
157 | WRITE_32(header + 38, 0); /* ext attrb */ | ||
158 | WRITE_32(header + 42, currentOffset); | ||
159 | /* Header */ | ||
160 | if (fwrite(header, 1, 46, fpOutCD) == 46) { | ||
161 | offsetCD += 46; | ||
162 | |||
163 | /* Filename */ | ||
164 | if (fnsize > 0) { | ||
165 | if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { | ||
166 | offsetCD += fnsize; | ||
167 | } else { | ||
168 | err = Z_ERRNO; | ||
169 | break; | ||
170 | } | ||
171 | } else { | ||
172 | err = Z_STREAM_ERROR; | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | /* Extra field */ | ||
177 | if (extsize > 0) { | ||
178 | if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { | ||
179 | offsetCD += extsize; | ||
180 | } else { | ||
181 | err = Z_ERRNO; | ||
182 | break; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /* Comment field */ | ||
187 | if (comsize > 0) { | ||
188 | if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { | ||
189 | offsetCD += comsize; | ||
190 | } else { | ||
191 | err = Z_ERRNO; | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | |||
197 | } else { | ||
198 | err = Z_ERRNO; | ||
199 | break; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | /* Success */ | ||
204 | entries++; | ||
205 | |||
206 | } else { | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | /* Final central directory */ | ||
212 | { | ||
213 | int entriesZip = entries; | ||
214 | char header[22]; | ||
215 | char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; | ||
216 | int comsize = (int) strlen(comment); | ||
217 | if (entriesZip > 0xffff) { | ||
218 | entriesZip = 0xffff; | ||
219 | } | ||
220 | WRITE_32(header, 0x06054b50); | ||
221 | WRITE_16(header + 4, 0); /* disk # */ | ||
222 | WRITE_16(header + 6, 0); /* disk # */ | ||
223 | WRITE_16(header + 8, entriesZip); /* hack */ | ||
224 | WRITE_16(header + 10, entriesZip); /* hack */ | ||
225 | WRITE_32(header + 12, offsetCD); /* size of CD */ | ||
226 | WRITE_32(header + 16, offset); /* offset to CD */ | ||
227 | WRITE_16(header + 20, comsize); /* comment */ | ||
228 | |||
229 | /* Header */ | ||
230 | if (fwrite(header, 1, 22, fpOutCD) == 22) { | ||
231 | |||
232 | /* Comment field */ | ||
233 | if (comsize > 0) { | ||
234 | if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { | ||
235 | err = Z_ERRNO; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | } else { | ||
240 | err = Z_ERRNO; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /* Final merge (file + central directory) */ | ||
245 | fclose(fpOutCD); | ||
246 | if (err == Z_OK) { | ||
247 | fpOutCD = fopen(fileOutTmp, "rb"); | ||
248 | if (fpOutCD != NULL) { | ||
249 | int nRead; | ||
250 | char buffer[8192]; | ||
251 | while ( (nRead = fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { | ||
252 | if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { | ||
253 | err = Z_ERRNO; | ||
254 | break; | ||
255 | } | ||
256 | } | ||
257 | fclose(fpOutCD); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | /* Close */ | ||
262 | fclose(fpZip); | ||
263 | fclose(fpOut); | ||
264 | |||
265 | /* Wipe temporary file */ | ||
266 | (void)remove(fileOutTmp); | ||
267 | |||
268 | /* Number of recovered entries */ | ||
269 | if (err == Z_OK) { | ||
270 | if (nRecovered != NULL) { | ||
271 | *nRecovered = entries; | ||
272 | } | ||
273 | if (bytesRecovered != NULL) { | ||
274 | *bytesRecovered = totalBytes; | ||
275 | } | ||
276 | } | ||
277 | } else { | ||
278 | err = Z_STREAM_ERROR; | ||
279 | } | ||
280 | return err; | ||
281 | } | ||