annotate src/zlib-1.2.7/contrib/minizip/mztools.c @ 83:ae30d91d2ffe

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