packvfs
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/zipcat/src/minizip/mztools.c Mon Nov 04 06:46:17 2013 +0200 1.3 @@ -0,0 +1,291 @@ 1.4 +/* 1.5 + Additional tools for Minizip 1.6 + Code: Xavier Roche '2004 1.7 + License: Same as ZLIB (www.gzip.org) 1.8 +*/ 1.9 + 1.10 +/* Code */ 1.11 +#include <stdio.h> 1.12 +#include <stdlib.h> 1.13 +#include <string.h> 1.14 +#include "zlib.h" 1.15 +#include "unzip.h" 1.16 + 1.17 +#define READ_8(adr) ((unsigned char)*(adr)) 1.18 +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) 1.19 +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) 1.20 + 1.21 +#define WRITE_8(buff, n) do { \ 1.22 + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ 1.23 +} while(0) 1.24 +#define WRITE_16(buff, n) do { \ 1.25 + WRITE_8((unsigned char*)(buff), n); \ 1.26 + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ 1.27 +} while(0) 1.28 +#define WRITE_32(buff, n) do { \ 1.29 + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ 1.30 + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ 1.31 +} while(0) 1.32 + 1.33 +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) 1.34 +const char* file; 1.35 +const char* fileOut; 1.36 +const char* fileOutTmp; 1.37 +uLong* nRecovered; 1.38 +uLong* bytesRecovered; 1.39 +{ 1.40 + int err = Z_OK; 1.41 + FILE* fpZip = fopen(file, "rb"); 1.42 + FILE* fpOut = fopen(fileOut, "wb"); 1.43 + FILE* fpOutCD = fopen(fileOutTmp, "wb"); 1.44 + if (fpZip != NULL && fpOut != NULL) { 1.45 + int entries = 0; 1.46 + uLong totalBytes = 0; 1.47 + char header[30]; 1.48 + char filename[1024]; 1.49 + char extra[1024]; 1.50 + int offset = 0; 1.51 + int offsetCD = 0; 1.52 + while ( fread(header, 1, 30, fpZip) == 30 ) { 1.53 + int currentOffset = offset; 1.54 + 1.55 + /* File entry */ 1.56 + if (READ_32(header) == 0x04034b50) { 1.57 + unsigned int version = READ_16(header + 4); 1.58 + unsigned int gpflag = READ_16(header + 6); 1.59 + unsigned int method = READ_16(header + 8); 1.60 + unsigned int filetime = READ_16(header + 10); 1.61 + unsigned int filedate = READ_16(header + 12); 1.62 + unsigned int crc = READ_32(header + 14); /* crc */ 1.63 + unsigned int cpsize = READ_32(header + 18); /* compressed size */ 1.64 + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ 1.65 + unsigned int fnsize = READ_16(header + 26); /* file name length */ 1.66 + unsigned int extsize = READ_16(header + 28); /* extra field length */ 1.67 + filename[0] = extra[0] = '\0'; 1.68 + 1.69 + /* Header */ 1.70 + if (fwrite(header, 1, 30, fpOut) == 30) { 1.71 + offset += 30; 1.72 + } else { 1.73 + err = Z_ERRNO; 1.74 + break; 1.75 + } 1.76 + 1.77 + /* Filename */ 1.78 + if (fnsize > 0) { 1.79 + if (fnsize < sizeof(filename)) { 1.80 + if (fread(filename, 1, fnsize, fpZip) == fnsize) { 1.81 + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { 1.82 + offset += fnsize; 1.83 + } else { 1.84 + err = Z_ERRNO; 1.85 + break; 1.86 + } 1.87 + } else { 1.88 + err = Z_ERRNO; 1.89 + break; 1.90 + } 1.91 + } else { 1.92 + err = Z_ERRNO; 1.93 + break; 1.94 + } 1.95 + } else { 1.96 + err = Z_STREAM_ERROR; 1.97 + break; 1.98 + } 1.99 + 1.100 + /* Extra field */ 1.101 + if (extsize > 0) { 1.102 + if (extsize < sizeof(extra)) { 1.103 + if (fread(extra, 1, extsize, fpZip) == extsize) { 1.104 + if (fwrite(extra, 1, extsize, fpOut) == extsize) { 1.105 + offset += extsize; 1.106 + } else { 1.107 + err = Z_ERRNO; 1.108 + break; 1.109 + } 1.110 + } else { 1.111 + err = Z_ERRNO; 1.112 + break; 1.113 + } 1.114 + } else { 1.115 + err = Z_ERRNO; 1.116 + break; 1.117 + } 1.118 + } 1.119 + 1.120 + /* Data */ 1.121 + { 1.122 + int dataSize = cpsize; 1.123 + if (dataSize == 0) { 1.124 + dataSize = uncpsize; 1.125 + } 1.126 + if (dataSize > 0) { 1.127 + char* data = malloc(dataSize); 1.128 + if (data != NULL) { 1.129 + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { 1.130 + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { 1.131 + offset += dataSize; 1.132 + totalBytes += dataSize; 1.133 + } else { 1.134 + err = Z_ERRNO; 1.135 + } 1.136 + } else { 1.137 + err = Z_ERRNO; 1.138 + } 1.139 + free(data); 1.140 + if (err != Z_OK) { 1.141 + break; 1.142 + } 1.143 + } else { 1.144 + err = Z_MEM_ERROR; 1.145 + break; 1.146 + } 1.147 + } 1.148 + } 1.149 + 1.150 + /* Central directory entry */ 1.151 + { 1.152 + char header[46]; 1.153 + char* comment = ""; 1.154 + int comsize = (int) strlen(comment); 1.155 + WRITE_32(header, 0x02014b50); 1.156 + WRITE_16(header + 4, version); 1.157 + WRITE_16(header + 6, version); 1.158 + WRITE_16(header + 8, gpflag); 1.159 + WRITE_16(header + 10, method); 1.160 + WRITE_16(header + 12, filetime); 1.161 + WRITE_16(header + 14, filedate); 1.162 + WRITE_32(header + 16, crc); 1.163 + WRITE_32(header + 20, cpsize); 1.164 + WRITE_32(header + 24, uncpsize); 1.165 + WRITE_16(header + 28, fnsize); 1.166 + WRITE_16(header + 30, extsize); 1.167 + WRITE_16(header + 32, comsize); 1.168 + WRITE_16(header + 34, 0); /* disk # */ 1.169 + WRITE_16(header + 36, 0); /* int attrb */ 1.170 + WRITE_32(header + 38, 0); /* ext attrb */ 1.171 + WRITE_32(header + 42, currentOffset); 1.172 + /* Header */ 1.173 + if (fwrite(header, 1, 46, fpOutCD) == 46) { 1.174 + offsetCD += 46; 1.175 + 1.176 + /* Filename */ 1.177 + if (fnsize > 0) { 1.178 + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { 1.179 + offsetCD += fnsize; 1.180 + } else { 1.181 + err = Z_ERRNO; 1.182 + break; 1.183 + } 1.184 + } else { 1.185 + err = Z_STREAM_ERROR; 1.186 + break; 1.187 + } 1.188 + 1.189 + /* Extra field */ 1.190 + if (extsize > 0) { 1.191 + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { 1.192 + offsetCD += extsize; 1.193 + } else { 1.194 + err = Z_ERRNO; 1.195 + break; 1.196 + } 1.197 + } 1.198 + 1.199 + /* Comment field */ 1.200 + if (comsize > 0) { 1.201 + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { 1.202 + offsetCD += comsize; 1.203 + } else { 1.204 + err = Z_ERRNO; 1.205 + break; 1.206 + } 1.207 + } 1.208 + 1.209 + 1.210 + } else { 1.211 + err = Z_ERRNO; 1.212 + break; 1.213 + } 1.214 + } 1.215 + 1.216 + /* Success */ 1.217 + entries++; 1.218 + 1.219 + } else { 1.220 + break; 1.221 + } 1.222 + } 1.223 + 1.224 + /* Final central directory */ 1.225 + { 1.226 + int entriesZip = entries; 1.227 + char header[22]; 1.228 + char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; 1.229 + int comsize = (int) strlen(comment); 1.230 + if (entriesZip > 0xffff) { 1.231 + entriesZip = 0xffff; 1.232 + } 1.233 + WRITE_32(header, 0x06054b50); 1.234 + WRITE_16(header + 4, 0); /* disk # */ 1.235 + WRITE_16(header + 6, 0); /* disk # */ 1.236 + WRITE_16(header + 8, entriesZip); /* hack */ 1.237 + WRITE_16(header + 10, entriesZip); /* hack */ 1.238 + WRITE_32(header + 12, offsetCD); /* size of CD */ 1.239 + WRITE_32(header + 16, offset); /* offset to CD */ 1.240 + WRITE_16(header + 20, comsize); /* comment */ 1.241 + 1.242 + /* Header */ 1.243 + if (fwrite(header, 1, 22, fpOutCD) == 22) { 1.244 + 1.245 + /* Comment field */ 1.246 + if (comsize > 0) { 1.247 + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { 1.248 + err = Z_ERRNO; 1.249 + } 1.250 + } 1.251 + 1.252 + } else { 1.253 + err = Z_ERRNO; 1.254 + } 1.255 + } 1.256 + 1.257 + /* Final merge (file + central directory) */ 1.258 + fclose(fpOutCD); 1.259 + if (err == Z_OK) { 1.260 + fpOutCD = fopen(fileOutTmp, "rb"); 1.261 + if (fpOutCD != NULL) { 1.262 + int nRead; 1.263 + char buffer[8192]; 1.264 + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { 1.265 + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { 1.266 + err = Z_ERRNO; 1.267 + break; 1.268 + } 1.269 + } 1.270 + fclose(fpOutCD); 1.271 + } 1.272 + } 1.273 + 1.274 + /* Close */ 1.275 + fclose(fpZip); 1.276 + fclose(fpOut); 1.277 + 1.278 + /* Wipe temporary file */ 1.279 + (void)remove(fileOutTmp); 1.280 + 1.281 + /* Number of recovered entries */ 1.282 + if (err == Z_OK) { 1.283 + if (nRecovered != NULL) { 1.284 + *nRecovered = entries; 1.285 + } 1.286 + if (bytesRecovered != NULL) { 1.287 + *bytesRecovered = totalBytes; 1.288 + } 1.289 + } 1.290 + } else { 1.291 + err = Z_STREAM_ERROR; 1.292 + } 1.293 + return err; 1.294 +}