mztools.c
上传用户:shengde
上传日期:2021-02-21
资源大小:638k
文件大小:8k
源码类别:

压缩解压

开发平台:

Visual C++

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