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 +}