Fossil SCM

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

Keyboard Shortcuts

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