annotate src/zlib-1.2.8/contrib/minizip/mztools.c @ 43:5ea0608b923f

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