Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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[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. }
  282.