(root)/
binutils-2.41/
zlib/
contrib/
minizip/
mztools.c
       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)
      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[1024];
      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 (fnsize < sizeof(filename)) {
      77              if (fread(filename, 1, fnsize, fpZip) == fnsize) {
      78                  if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
      79                  offset += fnsize;
      80                } else {
      81                  err = Z_ERRNO;
      82                  break;
      83                }
      84              } else {
      85                err = Z_ERRNO;
      86                break;
      87              }
      88            } else {
      89              err = Z_ERRNO;
      90              break;
      91            }
      92          } else {
      93            err = Z_STREAM_ERROR;
      94            break;
      95          }
      96  
      97          /* Extra field */
      98          if (extsize > 0) {
      99            if (extsize < sizeof(extra)) {
     100              if (fread(extra, 1, extsize, fpZip) == extsize) {
     101                if (fwrite(extra, 1, extsize, fpOut) == extsize) {
     102                  offset += extsize;
     103                  } else {
     104                  err = Z_ERRNO;
     105                  break;
     106                }
     107              } else {
     108                err = Z_ERRNO;
     109                break;
     110              }
     111            } else {
     112              err = Z_ERRNO;
     113              break;
     114            }
     115          }
     116  
     117          /* Data */
     118          {
     119            int dataSize = cpsize;
     120            if (dataSize == 0) {
     121              dataSize = uncpsize;
     122            }
     123            if (dataSize > 0) {
     124              char* data = malloc(dataSize);
     125              if (data != NULL) {
     126                if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
     127                  if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
     128                    offset += dataSize;
     129                    totalBytes += dataSize;
     130                  } else {
     131                    err = Z_ERRNO;
     132                  }
     133                } else {
     134                  err = Z_ERRNO;
     135                }
     136                free(data);
     137                if (err != Z_OK) {
     138                  break;
     139                }
     140              } else {
     141                err = Z_MEM_ERROR;
     142                break;
     143              }
     144            }
     145          }
     146  
     147          /* Central directory entry */
     148          {
     149            char header[46];
     150            char* comment = "";
     151            int comsize = (int) strlen(comment);
     152            WRITE_32(header, 0x02014b50);
     153            WRITE_16(header + 4, version);
     154            WRITE_16(header + 6, version);
     155            WRITE_16(header + 8, gpflag);
     156            WRITE_16(header + 10, method);
     157            WRITE_16(header + 12, filetime);
     158            WRITE_16(header + 14, filedate);
     159            WRITE_32(header + 16, crc);
     160            WRITE_32(header + 20, cpsize);
     161            WRITE_32(header + 24, uncpsize);
     162            WRITE_16(header + 28, fnsize);
     163            WRITE_16(header + 30, extsize);
     164            WRITE_16(header + 32, comsize);
     165            WRITE_16(header + 34, 0);     /* disk # */
     166            WRITE_16(header + 36, 0);     /* int attrb */
     167            WRITE_32(header + 38, 0);     /* ext attrb */
     168            WRITE_32(header + 42, currentOffset);
     169            /* Header */
     170            if (fwrite(header, 1, 46, fpOutCD) == 46) {
     171              offsetCD += 46;
     172  
     173              /* Filename */
     174              if (fnsize > 0) {
     175                if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
     176                  offsetCD += fnsize;
     177                } else {
     178                  err = Z_ERRNO;
     179                  break;
     180                }
     181              } else {
     182                err = Z_STREAM_ERROR;
     183                break;
     184              }
     185  
     186              /* Extra field */
     187              if (extsize > 0) {
     188                if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
     189                  offsetCD += extsize;
     190                } else {
     191                  err = Z_ERRNO;
     192                  break;
     193                }
     194              }
     195  
     196              /* Comment field */
     197              if (comsize > 0) {
     198                if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
     199                  offsetCD += comsize;
     200                } else {
     201                  err = Z_ERRNO;
     202                  break;
     203                }
     204              }
     205  
     206  
     207            } else {
     208              err = Z_ERRNO;
     209              break;
     210            }
     211          }
     212  
     213          /* Success */
     214          entries++;
     215  
     216        } else {
     217          break;
     218        }
     219      }
     220  
     221      /* Final central directory  */
     222      {
     223        int entriesZip = entries;
     224        char header[22];
     225        char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
     226        int comsize = (int) strlen(comment);
     227        if (entriesZip > 0xffff) {
     228          entriesZip = 0xffff;
     229        }
     230        WRITE_32(header, 0x06054b50);
     231        WRITE_16(header + 4, 0);    /* disk # */
     232        WRITE_16(header + 6, 0);    /* disk # */
     233        WRITE_16(header + 8, entriesZip);   /* hack */
     234        WRITE_16(header + 10, entriesZip);  /* hack */
     235        WRITE_32(header + 12, offsetCD);    /* size of CD */
     236        WRITE_32(header + 16, offset);      /* offset to CD */
     237        WRITE_16(header + 20, comsize);     /* comment */
     238  
     239        /* Header */
     240        if (fwrite(header, 1, 22, fpOutCD) == 22) {
     241  
     242          /* Comment field */
     243          if (comsize > 0) {
     244            if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
     245              err = Z_ERRNO;
     246            }
     247          }
     248  
     249        } else {
     250          err = Z_ERRNO;
     251        }
     252      }
     253  
     254      /* Final merge (file + central directory) */
     255      fclose(fpOutCD);
     256      if (err == Z_OK) {
     257        fpOutCD = fopen(fileOutTmp, "rb");
     258        if (fpOutCD != NULL) {
     259          int nRead;
     260          char buffer[8192];
     261          while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
     262            if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
     263              err = Z_ERRNO;
     264              break;
     265            }
     266          }
     267          fclose(fpOutCD);
     268        }
     269      }
     270  
     271      /* Close */
     272      fclose(fpZip);
     273      fclose(fpOut);
     274  
     275      /* Wipe temporary file */
     276      (void)remove(fileOutTmp);
     277  
     278      /* Number of recovered entries */
     279      if (err == Z_OK) {
     280        if (nRecovered != NULL) {
     281          *nRecovered = entries;
     282        }
     283        if (bytesRecovered != NULL) {
     284          *bytesRecovered = totalBytes;
     285        }
     286      }
     287    } else {
     288      err = Z_STREAM_ERROR;
     289    }
     290    return err;
     291  }