?? zip.c
字號:
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, ¢_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 + -