⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zip.c

📁 嵌入式环境下的GUI
💻 C
📖 第 1 页 / 共 3 页
字号:
        goto zip_load_entry_puked;        /* seek to the start of the next entry in the central directory... */    if (!__PHYSFS_platformSeek(in, si64 + extralen + commentlen))        goto zip_load_entry_puked;    return(1);  /* success. */zip_load_entry_puked:    free(entry->name);    return(0);  /* failure. */} /* zip_load_entry */static int zip_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two){    ZIPentry *a = (ZIPentry *) _a;    return(strcmp(a[one].name, a[two].name));} /* zip_entry_cmp */static void zip_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two){    ZIPentry tmp;    ZIPentry *first = &(((ZIPentry *) _a)[one]);    ZIPentry *second = &(((ZIPentry *) _a)[two]);    memcpy(&tmp, first, sizeof (ZIPentry));    memcpy(first, second, sizeof (ZIPentry));    memcpy(second, &tmp, sizeof (ZIPentry));} /* zip_entry_swap */static int zip_load_entries(void *in, DirHandle *dirh,                            PHYSFS_uint32 data_ofs, PHYSFS_uint32 central_ofs){    ZIPinfo *info = (ZIPinfo *) dirh->opaque;    PHYSFS_uint32 max = info->entryCount;    PHYSFS_uint32 i;    BAIL_IF_MACRO(!__PHYSFS_platformSeek(in, central_ofs), NULL, 0);    info->entries = (ZIPentry *) malloc(sizeof (ZIPentry) * max);    BAIL_IF_MACRO(info->entries == NULL, ERR_OUT_OF_MEMORY, 0);    for (i = 0; i < max; i++)    {        if (!zip_load_entry(in, &info->entries[i], data_ofs))        {            zip_free_entries(info->entries, i);            return(0);        } /* if */    } /* for */    __PHYSFS_sort(info->entries, max, zip_entry_cmp, zip_entry_swap);    return(1);} /* zip_load_entries */static int zip_parse_end_of_central_dir(void *in, DirHandle *dirh,                                        PHYSFS_uint32 *data_start,                                        PHYSFS_uint32 *central_dir_ofs){    ZIPinfo *zipinfo = (ZIPinfo *) dirh->opaque;    PHYSFS_uint32 ui32;    PHYSFS_uint16 ui16;    PHYSFS_sint64 len;    PHYSFS_sint64 pos;    /* find the end-of-central-dir record, and seek to it. */    pos = zip_find_end_of_central_dir(in, &len);    BAIL_IF_MACRO(pos == -1, NULL, 0);    BAIL_IF_MACRO(!__PHYSFS_platformSeek(in, pos), NULL, 0);    /* check signature again, just in case. */    BAIL_IF_MACRO(!readui32(in, &ui32), NULL, 0);    BAIL_IF_MACRO(ui32 != ZIP_END_OF_CENTRAL_DIR_SIG, ERR_NOT_AN_ARCHIVE, 0);    /* number of this disk */    BAIL_IF_MACRO(!readui16(in, &ui16), NULL, 0);    BAIL_IF_MACRO(ui16 != 0, ERR_UNSUPPORTED_ARCHIVE, 0);    /* number of the disk with the start of the central directory */    BAIL_IF_MACRO(!readui16(in, &ui16), NULL, 0);    BAIL_IF_MACRO(ui16 != 0, ERR_UNSUPPORTED_ARCHIVE, 0);    /* total number of entries in the central dir on this disk */    BAIL_IF_MACRO(!readui16(in, &ui16), NULL, 0);    /* total number of entries in the central dir */    BAIL_IF_MACRO(!readui16(in, &zipinfo->entryCount), NULL, 0);    BAIL_IF_MACRO(ui16 != zipinfo->entryCount, ERR_UNSUPPORTED_ARCHIVE, 0);    /* size of the central directory */    BAIL_IF_MACRO(!readui32(in, &ui32), NULL, 0);    /* offset of central directory */    BAIL_IF_MACRO(!readui32(in, central_dir_ofs), NULL, 0);    BAIL_IF_MACRO(pos < *central_dir_ofs + ui32, ERR_UNSUPPORTED_ARCHIVE, 0);    /*     * For self-extracting archives, etc, there's crapola in the file     *  before the zipfile records; we calculate how much data there is     *  prepended by determining how far the central directory offset is     *  from where it is supposed to be (start of end-of-central-dir minus     *  sizeof central dir)...the difference in bytes is how much arbitrary     *  data is at the start of the physical file.     */    *data_start = (PHYSFS_uint32) (pos - (*central_dir_ofs + ui32));    /* Now that we know the difference, fix up the central dir offset... */    *central_dir_ofs += *data_start;    /* zipfile comment length */    BAIL_IF_MACRO(!readui16(in, &ui16), NULL, 0);    /*     * Make sure that the comment length matches to the end of file...     *  If it doesn't, we're either in the wrong part of the file, or the     *  file is corrupted, but we give up either way.     */    BAIL_IF_MACRO((pos + 22 + ui16) != len, ERR_UNSUPPORTED_ARCHIVE, 0);    return(1);  /* made it. */} /* zip_parse_end_of_central_dir */static DirHandle *zip_allocate_dirhandle(const char *name){    char *ptr;    ZIPinfo *info;    DirHandle *retval = malloc(sizeof (DirHandle));    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);    memset(retval, '\0', sizeof (DirHandle));    info = (ZIPinfo *) malloc(sizeof (ZIPinfo));    if (info == NULL)    {        free(retval);        BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);    } /* if */    memset(info, '\0', sizeof (ZIPinfo));    ptr = (char *) malloc(strlen(name) + 1);    if (ptr == NULL)    {        free(info);        free(retval);        BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);    } /* if */    info->archiveName = ptr;    strcpy(info->archiveName, name);    retval->opaque = info;    retval->funcs = &__PHYSFS_DirFunctions_ZIP;    return(retval);} /* zip_allocate_dirhandle */static DirHandle *ZIP_openArchive(const char *name, int forWriting){    DirHandle *retval = NULL;    void *in = NULL;    PHYSFS_uint32 data_start;    PHYSFS_uint32 cent_dir_ofs;    int success = 0;    BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);    if ((in = __PHYSFS_platformOpenRead(name)) == NULL)        goto zip_openarchive_end;        if ((retval = zip_allocate_dirhandle(name)) == NULL)        goto zip_openarchive_end;    if (!zip_parse_end_of_central_dir(in, retval, &data_start, &cent_dir_ofs))        goto zip_openarchive_end;    if (!zip_load_entries(in, retval, data_start, cent_dir_ofs))        goto zip_openarchive_end;    success = 1;  /* ...and we're good to go.  :)  */zip_openarchive_end:    if (!success)  /* clean up for failures. */    {        if (retval != NULL)        {            if (retval->opaque != NULL)            {                if (((ZIPinfo *) (retval->opaque))->archiveName != NULL)                    free(((ZIPinfo *) (retval->opaque))->archiveName);                free(retval->opaque);            } /* if */            free(retval);            retval = NULL;        } /* if */    } /* if */    if (in != NULL)        __PHYSFS_platformClose(in);  /* Close this even with success. */    return(retval);} /* ZIP_openArchive */static PHYSFS_sint32 zip_find_start_of_dir(ZIPinfo *info, const char *path,                                            int stop_on_first_find){    PHYSFS_sint32 lo = 0;    PHYSFS_sint32 hi = (PHYSFS_sint32) info->entryCount;    PHYSFS_sint32 middle;    PHYSFS_uint32 dlen = strlen(path);    PHYSFS_sint32 retval = -1;    const char *name;    int rc;    if (*path == '\0')  /* root dir? */        return(0);    if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */        dlen--;    while (lo <= hi)    {        middle = lo + ((hi - lo) / 2);        name = info->entries[middle].name;        rc = strncmp(path, name, dlen);        if (rc == 0)        {            char ch = name[dlen];            if (ch < '/') /* make sure this isn't just a substr match. */                rc = -1;            else if (ch > '/')                rc = 1;            else             {                if (stop_on_first_find) /* Just checking dir's existance? */                    return(middle);                if (name[dlen + 1] == '\0') /* Skip initial dir entry. */                    return(middle + 1);                /* there might be more entries earlier in the list. */                retval = middle;                hi = middle - 1;            } /* else */        } /* if */        if (rc > 0)            lo = middle + 1;        else            hi = middle - 1;    } /* while */    return(retval);} /* zip_find_start_of_dir */static LinkedStringList *ZIP_enumerateFiles(DirHandle *h,                                            const char *dirname,                                            int omitSymLinks){    ZIPinfo *info = ((ZIPinfo *) h->opaque);    LinkedStringList *retval = NULL, *p = NULL;    PHYSFS_sint32 dlen, dlen_inc, max, i;    i = zip_find_start_of_dir(info, dirname, 0);    BAIL_IF_MACRO(i == -1, ERR_NO_SUCH_FILE, NULL);    dlen = strlen(dirname);    if ((dlen > 0) && (dirname[dlen - 1] == '/')) /* ignore trailing slash. */        dlen--;    dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;    max = (PHYSFS_sint32) info->entryCount;    while (i < max)    {        char *e = info->entries[i].name;        if ((dlen) && ((strncmp(e, dirname, dlen) != 0) || (e[dlen] != '/')))            break;  /* past end of this dir; we're done. */        if ((omitSymLinks) && (zip_entry_is_symlink(&info->entries[i])))            i++;        else        {            char *add = e + dlen_inc;            char *ptr = strchr(add, '/');            PHYSFS_sint32 ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));            retval = __PHYSFS_addToLinkedStringList(retval, &p, add, ln);            ln += dlen_inc;  /* point past entry to children... */            /* increment counter and skip children of subdirs... */            while ((++i < max) && (ptr != NULL))            {                char *e_new = info->entries[i].name;                if ((strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))                    break;            } /* while */        } /* else */    } /* while */    return(retval);} /* ZIP_enumerateFiles */static int ZIP_exists(DirHandle *h, const char *name){    int isDir;        ZIPinfo *info = (ZIPinfo *) h->opaque;    ZIPentry *entry = zip_find_entry(info, name, &isDir);    return((entry != NULL) || (isDir));} /* ZIP_exists */static PHYSFS_sint64 ZIP_getLastModTime(DirHandle *h,                                        const char *name,                                        int *fileExists){    int isDir;    ZIPinfo *info = (ZIPinfo *) h->opaque;    ZIPentry *entry = zip_find_entry(info, name, &isDir);    *fileExists = ((isDir) || (entry != NULL));    if (isDir)        return(1);  /* Best I can do for a dir... */    BAIL_IF_MACRO(entry == NULL, NULL, -1);    return(entry->last_mod_time);} /* ZIP_getLastModTime */static int ZIP_isDirectory(DirHandle *h, const char *name, int *fileExists){    ZIPinfo *info = (ZIPinfo *) h->opaque;    int isDir;    ZIPentry *entry = zip_find_entry(info, name, &isDir);    *fileExists = ((isDir) || (entry != NULL));    if (isDir)        return(1); /* definitely a dir. */    /* Follow symlinks. This means we might need to resolve entries. */    BAIL_IF_MACRO(entry == NULL, ERR_NO_SUCH_FILE, 0);    if (entry->resolved == ZIP_UNRESOLVED_SYMLINK) /* gotta resolve it. */    {        int rc;        void *in = __PHYSFS_platformOpenRead(info->archiveName);        BAIL_IF_MACRO(in == NULL, NULL, 0);        rc = zip_resolve(in, info, entry);        __PHYSFS_platformClose(in);        if (!rc)            return(0);    } /* if */    BAIL_IF_MACRO(entry->resolved == ZIP_BROKEN_SYMLINK, NULL, 0);    BAIL_IF_MACRO(entry->symlink == NULL, ERR_NOT_A_DIR, 0);    return(zip_find_start_of_dir(info, entry->symlink->name, 1) >= 0);} /* ZIP_isDirectory */static int ZIP_isSymLink(DirHandle *h, const char *name, int *fileExists){    int isDir;    ZIPentry *entry = zip_find_entry((ZIPinfo *) h->opaque, name, &isDir);    *fileExists = ((isDir) || (entry != NULL));    BAIL_IF_MACRO(entry == NULL, NULL, 0);    return(zip_entry_is_symlink(entry));} /* ZIP_isSymLink */static void *zip_get_file_handle(const char *fn, ZIPinfo *inf, ZIPentry *entry){    int success;    void *retval = __PHYSFS_platformOpenRead(fn);    BAIL_IF_MACRO(retval == NULL, NULL, NULL);    success = zip_resolve(retval, inf, entry);    if (success)    {        PHYSFS_sint64 offset;        offset = ((entry->symlink) ? entry->symlink->offset : entry->offset);        success = __PHYSFS_platformSeek(retval, offset);    } /* if */    if (!success)    {        __PHYSFS_platformClose(retval);        retval = NULL;    } /* if */    return(retval);} /* zip_get_file_handle */static FileHandle *ZIP_openRead(DirHandle *h, const char *fnm, int *fileExists){    ZIPinfo *info = (ZIPinfo *) h->opaque;    ZIPentry *entry = zip_find_entry(info, fnm, NULL);    FileHandle *retval = NULL;    ZIPfileinfo *finfo = NULL;    void *in;    *fileExists = (entry != NULL);    BAIL_IF_MACRO(entry == NULL, NULL, NULL);    in = zip_get_file_handle(info->archiveName, info, entry);    BAIL_IF_MACRO(in == NULL, NULL, NULL);    if ( ((retval = (FileHandle *) malloc(sizeof (FileHandle))) == NULL) ||         ((finfo = (ZIPfileinfo *) malloc(sizeof (ZIPfileinfo))) == NULL) )    {        if (retval)            free(retval);        __PHYSFS_platformClose(in);        BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);    } /* if */    retval->opaque = (void *) finfo;    retval->funcs = &__PHYSFS_FileFunctions_ZIP;    retval->dirHandle = h;    memset(finfo, '\0', sizeof (ZIPfileinfo));    finfo->handle = in;    finfo->entry = ((entry->symlink != NULL) ? entry->symlink : entry);    if (finfo->entry->compression_method != COMPMETH_NONE)    {        if (zlib_err(inflateInit2(&finfo->stream, -MAX_WBITS)) != Z_OK)        {            ZIP_fileClose(retval);            return(NULL);        } /* if */        finfo->buffer = (PHYSFS_uint8 *) malloc(ZIP_READBUFSIZE);        if (finfo->buffer == NULL)        {            ZIP_fileClose(retval);            BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);        } /* if */    } /* if */    return(retval);} /* ZIP_openRead */static FileHandle *ZIP_openWrite(DirHandle *h, const char *filename){    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);} /* ZIP_openWrite */static FileHandle *ZIP_openAppend(DirHandle *h, const char *filename){    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);} /* ZIP_openAppend */static void ZIP_dirClose(DirHandle *h){    ZIPinfo *zi = (ZIPinfo *) (h->opaque);    zip_free_entries(zi->entries, zi->entryCount);    free(zi->archiveName);    free(zi);    free(h);} /* ZIP_dirClose */static int ZIP_remove(DirHandle *h, const char *name){    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);} /* ZIP_remove */static int ZIP_mkdir(DirHandle *h, const char *name){    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);} /* ZIP_mkdir */#endif  /* defined PHYSFS_SUPPORTS_ZIP *//* end of zip.c ... */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -