in ios/CodePush/SSZipArchive/minizip/zip.c [642:874]
extern zipFile ZEXPORT zipOpen4(const void *pathname, int append, ZPOS64_T disk_size, zipcharpc *globalcomment,
zlib_filefunc64_32_def *pzlib_filefunc64_32_def)
{
zip64_internal ziinit;
zip64_internal *zi;
#ifndef NO_ADDFILEINEXISTINGZIP
ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
ZPOS64_T size_central_dir = 0; /* size of the central directory */
ZPOS64_T offset_central_dir = 0; /* offset of start of central directory */
ZPOS64_T number_entry_CD = 0; /* total number of entries in the central dir */
ZPOS64_T number_entry;
ZPOS64_T central_pos;
ZPOS64_T size_central_dir_to_read;
uLong uL;
uLong size_comment = 0;
size_t buf_size = SIZEDATA_INDATABLOCK;
void *buf_read;
#endif
int err = ZIP_OK;
int mode;
ziinit.z_filefunc.zseek32_file = NULL;
ziinit.z_filefunc.ztell32_file = NULL;
if (pzlib_filefunc64_32_def == NULL)
fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
else
ziinit.z_filefunc = *pzlib_filefunc64_32_def;
if (append == APPEND_STATUS_CREATE)
mode = (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE);
else
mode = (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING);
ziinit.filestream = ZOPEN64(ziinit.z_filefunc, pathname, mode);
if (ziinit.filestream == NULL)
return NULL;
if (append == APPEND_STATUS_CREATEAFTER) {
/* Don't support spanning ZIP with APPEND_STATUS_CREATEAFTER */
if (disk_size > 0)
return NULL;
ZSEEK64(ziinit.z_filefunc, ziinit.filestream, 0, SEEK_END);
}
ziinit.filestream_with_CD = ziinit.filestream;
ziinit.append = append;
ziinit.number_disk = 0;
ziinit.number_disk_with_CD = 0;
ziinit.disk_size = disk_size;
ziinit.begin_pos = ZTELL64(ziinit.z_filefunc, ziinit.filestream);
ziinit.in_opened_file_inzip = 0;
ziinit.ci.stream_initialised = 0;
ziinit.number_entry = 0;
ziinit.add_position_when_writting_offset = 0;
init_linkedlist(&(ziinit.central_dir));
zi = (zip64_internal *)ALLOC(sizeof(zip64_internal));
if (zi == NULL) {
ZCLOSE64(ziinit.z_filefunc, ziinit.filestream);
return NULL;
}
#ifndef NO_ADDFILEINEXISTINGZIP
/* Add file in a zipfile */
ziinit.globalcomment = NULL;
if (append == APPEND_STATUS_ADDINZIP) {
/* Read and Cache Central Directory Records */
central_pos = zip64local_SearchCentralDir(&ziinit.z_filefunc, ziinit.filestream);
/* disable to allow appending to empty ZIP archive (must be standard zip, not zip64)
if (central_pos == 0)
err = ZIP_ERRNO;
*/
if (err == ZIP_OK) {
/* read end of central directory info */
if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
err = ZIP_ERRNO;
/* the signature, already checked */
if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
err = ZIP_ERRNO;
/* number of this disk */
if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk) != ZIP_OK)
err = ZIP_ERRNO;
/* number of the disk with the start of the central directory */
if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk_with_CD) != ZIP_OK)
err = ZIP_ERRNO;
/* total number of entries in the central dir on this disk */
number_entry = 0;
if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
err = ZIP_ERRNO;
else
number_entry = uL;
/* total number of entries in the central dir */
number_entry_CD = 0;
if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
err = ZIP_ERRNO;
else
number_entry_CD = uL;
if (number_entry_CD != number_entry)
err = ZIP_BADZIPFILE;
/* size of the central directory */
size_central_dir = 0;
if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
err = ZIP_ERRNO;
else
size_central_dir = uL;
/* offset of start of central directory with respect to the starting disk number */
offset_central_dir = 0;
if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
err = ZIP_ERRNO;
else
offset_central_dir = uL;
/* zipfile global comment length */
if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &size_comment) != ZIP_OK)
err = ZIP_ERRNO;
if ((err == ZIP_OK) && ((number_entry_CD == 0xffff) || (offset_central_dir == 0xffffffff))) {
/* Format should be Zip64, as the central directory or file size is too large */
central_pos = zip64local_SearchCentralDir64(&ziinit.z_filefunc, ziinit.filestream, central_pos);
if (central_pos) {
ZPOS64_T sizeEndOfCentralDirectory;
if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
err = ZIP_ERRNO;
/* the signature, already checked */
if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
err = ZIP_ERRNO;
/* size of zip64 end of central directory record */
if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &sizeEndOfCentralDirectory) != ZIP_OK)
err = ZIP_ERRNO;
/* version made by */
if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
err = ZIP_ERRNO;
/* version needed to extract */
if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
err = ZIP_ERRNO;
/* number of this disk */
if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk) != ZIP_OK)
err = ZIP_ERRNO;
/* number of the disk with the start of the central directory */
if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk_with_CD) != ZIP_OK)
err = ZIP_ERRNO;
/* total number of entries in the central directory on this disk */
if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &number_entry) != ZIP_OK)
err = ZIP_ERRNO;
/* total number of entries in the central directory */
if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &number_entry_CD) != ZIP_OK)
err = ZIP_ERRNO;
if (number_entry_CD != number_entry)
err = ZIP_BADZIPFILE;
/* size of the central directory */
if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &size_central_dir) != ZIP_OK)
err = ZIP_ERRNO;
/* offset of start of central directory with respect to the starting disk number */
if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &offset_central_dir) != ZIP_OK)
err = ZIP_ERRNO;
} else
err = ZIP_BADZIPFILE;
}
}
if ((err == ZIP_OK) && (central_pos < offset_central_dir + size_central_dir))
err = ZIP_BADZIPFILE;
if (err != ZIP_OK) {
ZCLOSE64(ziinit.z_filefunc, ziinit.filestream);
TRYFREE(zi);
return NULL;
}
if (size_comment > 0) {
ziinit.globalcomment = (char *)ALLOC(size_comment + 1);
if (ziinit.globalcomment) {
size_comment = ZREAD64(ziinit.z_filefunc, ziinit.filestream, ziinit.globalcomment, size_comment);
ziinit.globalcomment[size_comment] = 0;
}
}
byte_before_the_zipfile = central_pos - (offset_central_dir + size_central_dir);
ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
/* Store central directory in memory */
size_central_dir_to_read = size_central_dir;
buf_size = SIZEDATA_INDATABLOCK;
buf_read = (void *)ALLOC(buf_size);
if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream,
offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
err = ZIP_ERRNO;
while ((size_central_dir_to_read > 0) && (err == ZIP_OK)) {
ZPOS64_T read_this = SIZEDATA_INDATABLOCK;
if (read_this > size_central_dir_to_read)
read_this = size_central_dir_to_read;
if (ZREAD64(ziinit.z_filefunc, ziinit.filestream, buf_read, (uLong)read_this) != read_this)
err = ZIP_ERRNO;
if (err == ZIP_OK)
err = add_data_in_datablock(&ziinit.central_dir, buf_read, (uLong)read_this);
size_central_dir_to_read -= read_this;
}
TRYFREE(buf_read);
ziinit.begin_pos = byte_before_the_zipfile;
ziinit.number_entry = number_entry_CD;
if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream,
offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
err = ZIP_ERRNO;
}
if (globalcomment)
*globalcomment = ziinit.globalcomment;
#endif
if (err != ZIP_OK) {
#ifndef NO_ADDFILEINEXISTINGZIP
TRYFREE(ziinit.globalcomment);
#endif
TRYFREE(zi);
return NULL;
}
*zi = ziinit;
zipGoToFirstDisk((zipFile)zi);
return (zipFile)zi;
}