1 /* $NetBSD: mztools.c,v 1.1.1.1 2006/01/14 20:10:58 christos Exp $ */
4 Additional tools for Minizip
5 Code: Xavier Roche '2004
6 License: Same as ZLIB (www.gzip.org)
16 #define READ_8(adr) ((unsigned char)*(adr))
17 #define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )
18 #define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )
20 #define WRITE_8(buff, n) do { \
21 *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
23 #define WRITE_16(buff, n) do { \
24 WRITE_8((unsigned char*)(buff), n); \
25 WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
27 #define WRITE_32(buff, n) do { \
28 WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
29 WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
32 extern int ZEXPORT
unzRepair(file
, fileOut
, fileOutTmp
, nRecovered
, bytesRecovered
)
35 const char* fileOutTmp
;
37 uLong
* bytesRecovered
;
40 FILE* fpZip
= fopen(file
, "rb");
41 FILE* fpOut
= fopen(fileOut
, "wb");
42 FILE* fpOutCD
= fopen(fileOutTmp
, "wb");
43 if (fpZip
!= NULL
&& fpOut
!= NULL
) {
51 while ( fread(header
, 1, 30, fpZip
) == 30 ) {
52 int currentOffset
= offset
;
55 if (READ_32(header
) == 0x04034b50) {
56 unsigned int version
= READ_16(header
+ 4);
57 unsigned int gpflag
= READ_16(header
+ 6);
58 unsigned int method
= READ_16(header
+ 8);
59 unsigned int filetime
= READ_16(header
+ 10);
60 unsigned int filedate
= READ_16(header
+ 12);
61 unsigned int crc
= READ_32(header
+ 14); /* crc */
62 unsigned int cpsize
= READ_32(header
+ 18); /* compressed size */
63 unsigned int uncpsize
= READ_32(header
+ 22); /* uncompressed sz */
64 unsigned int fnsize
= READ_16(header
+ 26); /* file name length */
65 unsigned int extsize
= READ_16(header
+ 28); /* extra field length */
66 filename
[0] = extra
[0] = '\0';
69 if (fwrite(header
, 1, 30, fpOut
) == 30) {
78 if (fread(filename
, 1, fnsize
, fpZip
) == fnsize
) {
79 if (fwrite(filename
, 1, fnsize
, fpOut
) == fnsize
) {
96 if (fread(extra
, 1, extsize
, fpZip
) == extsize
) {
97 if (fwrite(extra
, 1, extsize
, fpOut
) == extsize
) {
111 int dataSize
= cpsize
;
116 char* data
= malloc(dataSize
);
118 if ((int)fread(data
, 1, dataSize
, fpZip
) == dataSize
) {
119 if ((int)fwrite(data
, 1, dataSize
, fpOut
) == dataSize
) {
121 totalBytes
+= dataSize
;
139 /* Central directory entry */
143 int comsize
= (int) strlen(comment
);
144 WRITE_32(header
, 0x02014b50);
145 WRITE_16(header
+ 4, version
);
146 WRITE_16(header
+ 6, version
);
147 WRITE_16(header
+ 8, gpflag
);
148 WRITE_16(header
+ 10, method
);
149 WRITE_16(header
+ 12, filetime
);
150 WRITE_16(header
+ 14, filedate
);
151 WRITE_32(header
+ 16, crc
);
152 WRITE_32(header
+ 20, cpsize
);
153 WRITE_32(header
+ 24, uncpsize
);
154 WRITE_16(header
+ 28, fnsize
);
155 WRITE_16(header
+ 30, extsize
);
156 WRITE_16(header
+ 32, comsize
);
157 WRITE_16(header
+ 34, 0); /* disk # */
158 WRITE_16(header
+ 36, 0); /* int attrb */
159 WRITE_32(header
+ 38, 0); /* ext attrb */
160 WRITE_32(header
+ 42, currentOffset
);
162 if (fwrite(header
, 1, 46, fpOutCD
) == 46) {
167 if (fwrite(filename
, 1, fnsize
, fpOutCD
) == fnsize
) {
174 err
= Z_STREAM_ERROR
;
180 if (fwrite(extra
, 1, extsize
, fpOutCD
) == extsize
) {
190 if ((int)fwrite(comment
, 1, comsize
, fpOutCD
) == comsize
) {
213 /* Final central directory */
215 int entriesZip
= entries
;
217 char* comment
= ""; // "ZIP File recovered by zlib/minizip/mztools";
218 int comsize
= (int) strlen(comment
);
219 if (entriesZip
> 0xffff) {
222 WRITE_32(header
, 0x06054b50);
223 WRITE_16(header
+ 4, 0); /* disk # */
224 WRITE_16(header
+ 6, 0); /* disk # */
225 WRITE_16(header
+ 8, entriesZip
); /* hack */
226 WRITE_16(header
+ 10, entriesZip
); /* hack */
227 WRITE_32(header
+ 12, offsetCD
); /* size of CD */
228 WRITE_32(header
+ 16, offset
); /* offset to CD */
229 WRITE_16(header
+ 20, comsize
); /* comment */
232 if (fwrite(header
, 1, 22, fpOutCD
) == 22) {
236 if ((int)fwrite(comment
, 1, comsize
, fpOutCD
) != comsize
) {
246 /* Final merge (file + central directory) */
249 fpOutCD
= fopen(fileOutTmp
, "rb");
250 if (fpOutCD
!= NULL
) {
253 while ( (nRead
= (int)fread(buffer
, 1, sizeof(buffer
), fpOutCD
)) > 0) {
254 if ((int)fwrite(buffer
, 1, nRead
, fpOut
) != nRead
) {
267 /* Wipe temporary file */
268 (void)remove(fileOutTmp
);
270 /* Number of recovered entries */
272 if (nRecovered
!= NULL
) {
273 *nRecovered
= entries
;
275 if (bytesRecovered
!= NULL
) {
276 *bytesRecovered
= totalBytes
;
280 err
= Z_STREAM_ERROR
;