2 Additional tools for Minizip
3 Code: Xavier Roche '2004
4 License: Same as ZLIB (www.gzip.org)
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) )
18 #define WRITE_8(buff, n) do { \
19 *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
21 #define WRITE_16(buff, n) do { \
22 WRITE_8((unsigned char*)(buff), n); \
23 WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
25 #define WRITE_32(buff, n) do { \
26 WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
27 WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
30 extern int ZEXPORT
unzRepair(file
, fileOut
, fileOutTmp
, nRecovered
, bytesRecovered
)
33 const char* fileOutTmp
;
35 uLong
* bytesRecovered
;
38 FILE* fpZip
= fopen(file
, "rb");
39 FILE* fpOut
= fopen(fileOut
, "wb");
40 FILE* fpOutCD
= fopen(fileOutTmp
, "wb");
41 if (fpZip
!= NULL
&& fpOut
!= NULL
) {
49 while ( fread(header
, 1, 30, fpZip
) == 30 ) {
50 int currentOffset
= offset
;
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';
67 if (fwrite(header
, 1, 30, fpOut
) == 30) {
76 if (fnsize
< sizeof(filename
)) {
77 if (fread(filename
, 1, fnsize
, fpZip
) == fnsize
) {
78 if (fwrite(filename
, 1, fnsize
, fpOut
) == fnsize
) {
99 if (extsize
< sizeof(extra
)) {
100 if (fread(extra
, 1, extsize
, fpZip
) == extsize
) {
101 if (fwrite(extra
, 1, extsize
, fpOut
) == extsize
) {
119 int dataSize
= cpsize
;
124 char* data
= malloc(dataSize
);
126 if ((int)fread(data
, 1, dataSize
, fpZip
) == dataSize
) {
127 if ((int)fwrite(data
, 1, dataSize
, fpOut
) == dataSize
) {
129 totalBytes
+= dataSize
;
147 /* Central directory entry */
151 int comsize
= (int) strlen(comment
);
152 WRITE_32(header
, 0x02014b50);
153 WRITE_16(header
+ 4, version
);
154 WRITE_16(header
+ 6, version
);
155 WRITE_16(header
+ 8, gpflag
);
156 WRITE_16(header
+ 10, method
);
157 WRITE_16(header
+ 12, filetime
);
158 WRITE_16(header
+ 14, filedate
);
159 WRITE_32(header
+ 16, crc
);
160 WRITE_32(header
+ 20, cpsize
);
161 WRITE_32(header
+ 24, uncpsize
);
162 WRITE_16(header
+ 28, fnsize
);
163 WRITE_16(header
+ 30, extsize
);
164 WRITE_16(header
+ 32, comsize
);
165 WRITE_16(header
+ 34, 0); /* disk # */
166 WRITE_16(header
+ 36, 0); /* int attrb */
167 WRITE_32(header
+ 38, 0); /* ext attrb */
168 WRITE_32(header
+ 42, currentOffset
);
170 if (fwrite(header
, 1, 46, fpOutCD
) == 46) {
175 if (fwrite(filename
, 1, fnsize
, fpOutCD
) == fnsize
) {
182 err
= Z_STREAM_ERROR
;
188 if (fwrite(extra
, 1, extsize
, fpOutCD
) == extsize
) {
198 if ((int)fwrite(comment
, 1, comsize
, fpOutCD
) == comsize
) {
221 /* Final central directory */
223 int entriesZip
= entries
;
225 char* comment
= ""; // "ZIP File recovered by zlib/minizip/mztools";
226 int comsize
= (int) strlen(comment
);
227 if (entriesZip
> 0xffff) {
230 WRITE_32(header
, 0x06054b50);
231 WRITE_16(header
+ 4, 0); /* disk # */
232 WRITE_16(header
+ 6, 0); /* disk # */
233 WRITE_16(header
+ 8, entriesZip
); /* hack */
234 WRITE_16(header
+ 10, entriesZip
); /* hack */
235 WRITE_32(header
+ 12, offsetCD
); /* size of CD */
236 WRITE_32(header
+ 16, offset
); /* offset to CD */
237 WRITE_16(header
+ 20, comsize
); /* comment */
240 if (fwrite(header
, 1, 22, fpOutCD
) == 22) {
244 if ((int)fwrite(comment
, 1, comsize
, fpOutCD
) != comsize
) {
254 /* Final merge (file + central directory) */
257 fpOutCD
= fopen(fileOutTmp
, "rb");
258 if (fpOutCD
!= NULL
) {
261 while ( (nRead
= (int)fread(buffer
, 1, sizeof(buffer
), fpOutCD
)) > 0) {
262 if ((int)fwrite(buffer
, 1, nRead
, fpOut
) != nRead
) {
275 /* Wipe temporary file */
276 (void)remove(fileOutTmp
);
278 /* Number of recovered entries */
280 if (nRecovered
!= NULL
) {
281 *nRecovered
= entries
;
283 if (bytesRecovered
!= NULL
) {
284 *bytesRecovered
= totalBytes
;
288 err
= Z_STREAM_ERROR
;