Fossil SCM

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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button