extern zipFile ZEXPORT zipOpen4()

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;
}