19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
29e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  Additional tools for Minizip
39e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  Code: Xavier Roche '2004
49e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  License: Same as ZLIB (www.gzip.org)
59e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project*/
69e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Code */
89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdio.h>
99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdlib.h>
109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <string.h>
119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "zlib.h"
129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "unzip.h"
139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define READ_8(adr)  ((unsigned char)*(adr))
159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )
169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )
179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define WRITE_8(buff, n) do { \
199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} while(0)
219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define WRITE_16(buff, n) do { \
229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  WRITE_8((unsigned char*)(buff), n); \
239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} while(0)
259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define WRITE_32(buff, n) do { \
269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} while(0)
299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectextern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectconst char* file;
329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectconst char* fileOut;
339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectconst char* fileOutTmp;
349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source ProjectuLong* nRecovered;
359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source ProjectuLong* bytesRecovered;
369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  int err = Z_OK;
389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  FILE* fpZip = fopen(file, "rb");
399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  FILE* fpOut = fopen(fileOut, "wb");
409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  FILE* fpOutCD = fopen(fileOutTmp, "wb");
419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  if (fpZip != NULL &&  fpOut != NULL) {
429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int entries = 0;
439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    uLong totalBytes = 0;
449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    char header[30];
45ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    char filename[1024];
469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    char extra[1024];
479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int offset = 0;
489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int offsetCD = 0;
499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while ( fread(header, 1, 30, fpZip) == 30 ) {
509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      int currentOffset = offset;
519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      /* File entry */
539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      if (READ_32(header) == 0x04034b50) {
549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int version = READ_16(header + 4);
559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int gpflag = READ_16(header + 6);
569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int method = READ_16(header + 8);
579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int filetime = READ_16(header + 10);
589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int filedate = READ_16(header + 12);
599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int crc = READ_32(header + 14); /* crc */
609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int cpsize = READ_32(header + 18); /* compressed size */
619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */
629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int fnsize = READ_16(header + 26); /* file name length */
639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned int extsize = READ_16(header + 28); /* extra field length */
649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        filename[0] = extra[0] = '\0';
65381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* Header */
679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (fwrite(header, 1, 30, fpOut) == 30) {
689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          offset += 30;
699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } else {
709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          err = Z_ERRNO;
719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          break;
729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
73381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* Filename */
759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (fnsize > 0) {
76ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes          if (fnsize < sizeof(filename)) {
77ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            if (fread(filename, 1, fnsize, fpZip) == fnsize) {
78ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
79ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                offset += fnsize;
80ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes              } else {
81ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                err = Z_ERRNO;
82ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                break;
83ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes              }
849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } else {
859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              err = Z_ERRNO;
869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              break;
879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          } else {
899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            err = Z_ERRNO;
909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          }
929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } else {
939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          err = Z_STREAM_ERROR;
949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          break;
959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* Extra field */
989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (extsize > 0) {
99ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes          if (extsize < sizeof(extra)) {
100ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            if (fread(extra, 1, extsize, fpZip) == extsize) {
101ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes              if (fwrite(extra, 1, extsize, fpOut) == extsize) {
102ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                offset += extsize;
103ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                } else {
104ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                err = Z_ERRNO;
105ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                break;
106ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes              }
1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } else {
1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              err = Z_ERRNO;
1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              break;
1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          } else {
1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            err = Z_ERRNO;
1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          }
1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
116381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* Data */
1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        {
1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          int dataSize = cpsize;
1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          if (dataSize == 0) {
1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            dataSize = uncpsize;
1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          }
1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          if (dataSize > 0) {
1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            char* data = malloc(dataSize);
1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (data != NULL) {
1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                  offset += dataSize;
1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                  totalBytes += dataSize;
1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                } else {
1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                  err = Z_ERRNO;
1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              } else {
1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                err = Z_ERRNO;
1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              }
1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              free(data);
1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              if (err != Z_OK) {
1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              }
1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } else {
1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              err = Z_MEM_ERROR;
1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              break;
1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          }
1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
146381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* Central directory entry */
1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        {
1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          char header[46];
1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          char* comment = "";
1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          int comsize = (int) strlen(comment);
1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_32(header, 0x02014b50);
1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 4, version);
1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 6, version);
1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 8, gpflag);
1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 10, method);
1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 12, filetime);
1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 14, filedate);
1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_32(header + 16, crc);
1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_32(header + 20, cpsize);
1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_32(header + 24, uncpsize);
1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 28, fnsize);
1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 30, extsize);
1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 32, comsize);
1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 34, 0);     /* disk # */
1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_16(header + 36, 0);     /* int attrb */
1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_32(header + 38, 0);     /* ext attrb */
1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          WRITE_32(header + 42, currentOffset);
1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          /* Header */
1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          if (fwrite(header, 1, 46, fpOutCD) == 46) {
1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            offsetCD += 46;
172381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* Filename */
1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (fnsize > 0) {
1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                offsetCD += fnsize;
1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              } else {
1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                err = Z_ERRNO;
1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              }
1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } else {
1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              err = Z_STREAM_ERROR;
1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              break;
1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
185381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* Extra field */
1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (extsize > 0) {
1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                offsetCD += extsize;
1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              } else {
1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                err = Z_ERRNO;
1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              }
1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
195381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* Comment field */
1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (comsize > 0) {
1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                offsetCD += comsize;
2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              } else {
2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                err = Z_ERRNO;
2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              }
2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
205381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
206381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          } else {
2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            err = Z_ERRNO;
2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          }
2119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* Success */
2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        entries++;
2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      } else {
2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        break;
2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      }
2199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Final central directory  */
2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    {
2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      int entriesZip = entries;
2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      char header[22];
2259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      int comsize = (int) strlen(comment);
2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      if (entriesZip > 0xffff) {
2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        entriesZip = 0xffff;
2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      }
2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      WRITE_32(header, 0x06054b50);
2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      WRITE_16(header + 4, 0);    /* disk # */
2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      WRITE_16(header + 6, 0);    /* disk # */
2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      WRITE_16(header + 8, entriesZip);   /* hack */
2349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      WRITE_16(header + 10, entriesZip);  /* hack */
2359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      WRITE_32(header + 12, offsetCD);    /* size of CD */
2369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      WRITE_32(header + 16, offset);      /* offset to CD */
2379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      WRITE_16(header + 20, comsize);     /* comment */
238381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
2399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      /* Header */
2409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      if (fwrite(header, 1, 22, fpOutCD) == 22) {
241381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
2429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* Comment field */
2439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (comsize > 0) {
2449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
2459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            err = Z_ERRNO;
2469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          }
2479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
248381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
2499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      } else {
2509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        err = Z_ERRNO;
2519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      }
2529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
2539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Final merge (file + central directory) */
2559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    fclose(fpOutCD);
2569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (err == Z_OK) {
2579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      fpOutCD = fopen(fileOutTmp, "rb");
2589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      if (fpOutCD != NULL) {
2599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        int nRead;
2609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        char buffer[8192];
2619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
2629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
2639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            err = Z_ERRNO;
2649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
2659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project          }
2669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
2679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        fclose(fpOutCD);
2689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      }
2699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
270381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
2719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Close */
2729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    fclose(fpZip);
2739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    fclose(fpOut);
274381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
2759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Wipe temporary file */
2769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    (void)remove(fileOutTmp);
277381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
2789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Number of recovered entries */
2799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (err == Z_OK) {
2809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      if (nRecovered != NULL) {
2819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        *nRecovered = entries;
2829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      }
2839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      if (bytesRecovered != NULL) {
2849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        *bytesRecovered = totalBytes;
2859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project      }
2869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
2879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  } else {
2889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    err = Z_STREAM_ERROR;
2899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  }
2909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  return err;
2919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
292