third_party/zlib: Initial copy of zlib.
[bbaumbach/samba-autobuild/.git] / third_party / zlib / contrib / minizip / mztools.c
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 = (int)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 }