root/lib/zlib/contrib/minizip/mztools.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. unzRepair

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

/* [<][>][^][v][top][bottom][index][help] */