packvfs

annotate test/zipcat/src/minizip/mztools.c @ 3:ef6c1472607f

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