//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== quakefile_t *FindQuakeFilesInZip(char *zipfile, char *filter) { unzFile uf; int err; unz_global_info gi; char filename_inzip[MAX_PATH]; unz_file_info file_info; int i; quakefile_t *qfiles, *lastqf, *qf; uf = unzOpen(zipfile); err = unzGetGlobalInfo(uf, &gi); if (err != UNZ_OK) return NULL; unzGoToFirstFile(uf); qfiles = NULL; lastqf = NULL; for (i = 0; i < gi.number_entry; i++) { err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL,0,NULL,0); if (err != UNZ_OK) break; ConvertPath(filename_inzip); if (FileFilter(filter, filename_inzip, false)) { qf = malloc(sizeof(quakefile_t)); if (!qf) Error("out of memory"); memset(qf, 0, sizeof(quakefile_t)); strcpy(qf->pakfile, zipfile); strcpy(qf->filename, zipfile); strcpy(qf->origname, filename_inzip); qf->zipfile = true; qf->pos = unzGetOffset(uf); qf->length = file_info.uncompressed_size; qf->type = QuakeFileType(filename_inzip); //add the file ot the list qf->next = NULL; if (lastqf) lastqf->next = qf; else qfiles = qf; lastqf = qf; } //end if unzGoToNextFile(uf); } //end for unzClose(uf); return qfiles; } //end of the function FindQuakeFilesInZip
//-----------------------------------------------------------------// bool unzip::open(const std::string& archive) { close(); hnd_ = unzOpen(archive.c_str()); if(hnd_ == 0) { return false; } do { file_info fi; char fn[2048]; fn[0] = 0; if(unzGetCurrentFileInfo(hnd_, &fi.info_, fn, sizeof(fn), NULL, 0, NULL, 0) != UNZ_OK) { break; } const char* p = strrchr(fn, '/'); if(p != 0 && p[1] == 0) { // 最後の文字が「/」で終わる場合はアーカイブに含めない dirs_.push_back(fn); } else { fi.ofs_ = unzGetOffset(hnd_); fi.path_ = fn; zmap::iterator it = zmap_.find(fn); if(it == zmap_.end()) { zmap::value_type stb(fn, files_.size()); zmap_.insert(stb); files_.push_back(fi); } else { files_[it->second] = fi; } } } while(unzGoToNextFile(hnd_) != UNZ_END_OF_LIST_OF_FILE) ; zname_ = archive; return true; }
bool KAppRes::OpenResPack() { bool retval = false; zlib_filefunc_def zip_funcs; std::string strPathAnsi; int nRetCode; HRSRC hResInfo = NULL; HGLOBAL hResDat = NULL; PVOID pResBuffer = NULL; DWORD dwResBuffer = 0; fill_win32_filefunc(&zip_funcs); strPathAnsi = UnicodeToAnsi(m_strResPackPath); m_pResPackData = unzOpen2(strPathAnsi.c_str(), &zip_funcs); if (m_pResPackData) goto UNZRESPACKDATA; if (strlen((const char*)&m_memZipRes) == 0) {//防止.kui格式错误导致unzOpen2返回空的m_pResPackData hResInfo = FindResourceW(_ModulePtr->GetResourceInstance(), L"kuires.dat", L"SKIN"); if (!hResInfo) goto clean0; hResDat = LoadResource(_ModulePtr->GetResourceInstance(), hResInfo); if (!hResDat) goto clean0; pResBuffer = LockResource(hResDat); if (!pResBuffer) goto clean0; dwResBuffer = SizeofResource(_ModulePtr->GetResourceInstance(), hResInfo); m_memZipRes.SetData(pResBuffer, dwResBuffer); } zip_funcs.zopen_file = ZipOpenFunc; zip_funcs.zread_file = ZipReadFunc; zip_funcs.zwrite_file = ZipWriteFunc; zip_funcs.ztell_file = ZipTellFunc; zip_funcs.zseek_file = ZipSeekFunc; zip_funcs.zclose_file = ZipCloseFunc; zip_funcs.zerror_file = ZipErrorFunc; zip_funcs.opaque=NULL; m_pResPackData = unzOpen2((const char*)&m_memZipRes, &zip_funcs); if (!m_pResPackData) goto clean0; UNZRESPACKDATA: nRetCode = unzGoToFirstFile(m_pResPackData); while (UNZ_OK == nRetCode) { char szCurrentFile[260]; unz_file_info fileInfo; uLong dwSeekPos; uLong dwSize; nRetCode = unzGetCurrentFileInfo( m_pResPackData, &fileInfo, szCurrentFile, sizeof(szCurrentFile), NULL, 0, NULL, 0 ); if (nRetCode != UNZ_OK) goto clean0; dwSeekPos = unzGetOffset(m_pResPackData); dwSize = fileInfo.uncompressed_size; m_mapResOffset.insert(KResOffset::value_type(szCurrentFile, KResInfo(dwSeekPos, dwSize))); nRetCode = unzGoToNextFile(m_pResPackData); } clean0: return retval; }
/* ================= FS_LoadPackFile Takes an explicit (not game tree related) path to a pak file. Loads the header and directory, adding the files at the beginning of the list so they override previous pack files. ================= */ static pack_t /*@null@*/ *FS_LoadPackFile (const char *packfile, const char *ext) { int i; void **newitem; pack_t *pack = NULL; packfile_t *info; if (!strcmp (ext, "pak")) { unsigned pakLen; int numpackfiles; FILE *packhandle; dpackheader_t header; packhandle = fopen(packfile, "rb"); if (!packhandle) return NULL; fseek (packhandle, 0, SEEK_END); pakLen = ftell (packhandle); rewind (packhandle); if (fread (&header, sizeof(header), 1, packhandle) != 1) Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't read pak header from %s", packfile); if (LittleLong(header.ident) != IDPAKHEADER) Com_Error (ERR_FATAL, "FS_LoadPackFile: %s is not a valid pak file.", packfile); #if YOU_HAVE_A_BROKEN_COMPUTER header.dirofs = LittleLong (header.dirofs); header.dirlen = LittleLong (header.dirlen); #endif if (header.dirlen % sizeof(packfile_t)) Com_Error (ERR_FATAL, "FS_LoadPackFile: Bad pak file %s (directory length %u is not a multiple of %d)", packfile, header.dirlen, (int)sizeof(packfile_t)); numpackfiles = header.dirlen / sizeof(packfile_t); if (numpackfiles > MAX_FILES_IN_PACK) //Com_Error (ERR_FATAL, "FS_LoadPackFile: packfile %s has %i files (max allowed %d)", packfile, numpackfiles, MAX_FILES_IN_PACK); Com_Printf ("WARNING: Pak file %s has %i files (max allowed %d) - may not be compatible with other clients\n", LOG_GENERAL, packfile, numpackfiles, MAX_FILES_IN_PACK); if (!numpackfiles) { fclose (packhandle); Com_Printf ("WARNING: Empty packfile %s\n", LOG_GENERAL|LOG_WARNING, packfile); return NULL; } //newfiles = Z_TagMalloc (numpackfiles * sizeof(packfile_t), TAGMALLOC_FSLOADPAK); info = Z_TagMalloc (numpackfiles * sizeof(packfile_t), TAGMALLOC_FSLOADPAK); if (fseek (packhandle, header.dirofs, SEEK_SET)) Com_Error (ERR_FATAL, "FS_LoadPackFile: fseek() to offset %u in %s failed. Pak file is possibly corrupt.", header.dirofs, packfile); if ((int)fread (info, 1, header.dirlen, packhandle) != header.dirlen) Com_Error (ERR_FATAL, "FS_LoadPackFile: Error reading packfile directory from %s (failed to read %u bytes at %u). Pak file is possibly corrupt.", packfile, header.dirofs, header.dirlen); pack = Z_TagMalloc (sizeof (pack_t), TAGMALLOC_FSLOADPAK); pack->type = PAK_QUAKE; pack->rb = rbinit ((int (EXPORT *)(const void *, const void *))strcmp, numpackfiles); //entry = Z_TagMalloc (sizeof(packfile_t) * numpackfiles, TAGMALLOC_FSLOADPAK); for (i=0 ; i<numpackfiles ; i++) { fast_strlwr (info[i].name); #if YOU_HAVE_A_BROKEN_COMPUTER info[i].filepos = LittleLong(info[i].filepos); info[i].filelen = LittleLong(info[i].filelen); #endif if (info[i].filepos + info[i].filelen >= pakLen) Com_Error (ERR_FATAL, "FS_LoadPackFile: File '%.64s' in pak file %s has illegal offset %u past end of file %u. Pak file is possibly corrupt.", MakePrintable (info[i].name, 0), packfile, info[i].filepos, pakLen); newitem = rbsearch (info[i].name, pack->rb); *newitem = &info[i]; } Q_strncpy (pack->filename, packfile, sizeof(pack->filename)-1); pack->h.handle = packhandle; pack->numfiles = numpackfiles; Com_Printf ("Added packfile %s (%i files)\n", LOG_GENERAL, packfile, numpackfiles); } #ifndef NO_ZLIB else if (!strcmp (ext, "pkz")) { unzFile f; unz_global_info zipinfo; char zipFileName[56]; unz_file_info fileInfo; f = unzOpen (packfile); if (!f) return NULL; if (unzGetGlobalInfo (f, &zipinfo) != UNZ_OK) Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't read .zip info from '%s'", packfile); info = Z_TagMalloc (zipinfo.number_entry * sizeof(*info), TAGMALLOC_FSLOADPAK); pack = Z_TagMalloc (sizeof (pack_t), TAGMALLOC_FSLOADPAK); pack->type = PAK_ZIP; pack->rb = rbinit ((int (EXPORT *)(const void *, const void *))strcmp, zipinfo.number_entry); if (unzGoToFirstFile (f) != UNZ_OK) Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't seek to first .zip file in '%s'", packfile); zipFileName[sizeof(zipFileName)-1] = 0; i = 0; do { if (unzGetCurrentFileInfo (f, &fileInfo, zipFileName, sizeof(zipFileName)-1, NULL, 0, NULL, 0) == UNZ_OK) { //directory, ignored if (fileInfo.external_fa & 16) continue; strcpy (info[i].name, zipFileName); info[i].filepos = unzGetOffset (f); info[i].filelen = fileInfo.uncompressed_size; newitem = rbsearch (info[i].name, pack->rb); *newitem = &info[i]; i++; } } while (unzGoToNextFile (f) == UNZ_OK); pack->h.zhandle = f; Com_Printf ("Added zpackfile %s (%i files)\n", LOG_GENERAL, packfile, i); } #endif else { Com_Error (ERR_FATAL, "FS_LoadPackFile: Unknown type %s", ext); } return pack; }
void CArchive::InitItems() { // Loading archive info ArchiveGuard arch(mPath.string().c_str()); unz_global_info gi; unzGetGlobalInfo(arch.file, &gi); // Reserving space for items mItems.reserve(gi.number_entry); if(unzGoToFirstFile(arch.file) != UNZ_OK) return; unz_file_info fi; std::vector<char> fnbuf(100); // Iterating through children and creating resource wrappers do { // Getting resource info unzGetCurrentFileInfo(arch.file, &fi, &fnbuf[0], (unsigned long)(fnbuf.size() - 1), 0, 0, 0, 0); if(fi.size_filename >= (fnbuf.size() - 1)) { fnbuf.resize(fi.size_filename + 50); unzGetCurrentFileInfo(arch.file, &fi, &fnbuf[0], (unsigned long)(fnbuf.size() - 1), 0, 0, 0, 0); } // Forming name and path bool isFolder = fnbuf[fi.size_filename - 1] == '/'; if(isFolder) fnbuf[fi.size_filename - 1] = 0; std::string itName(&fnbuf[0]); boost::filesystem::path p(mPath); p /= boost::filesystem::path(itName); IResource* loaded; mFileSystem->TryGetResource(p, &loaded); if(!loaded) { // Resolving file or folder if(isFolder) { CArchFolder* fld; create_instance_impl<CArchFolder>(&fld); fld->FinalConstruct(mFileSystem, mPath, p); loaded = fld; } else { CArchFile* file; create_instance_impl<CArchFile>(&file); file->FinalConstruct(mFileSystem, mPath, p, unzGetOffset(arch.file)); loaded = file; } mFileSystem->AddHandle(p.string(), loaded); } // Ref count == 1 now mItems.push_back(loaded); } while(unzGoToNextFile(arch.file) != UNZ_END_OF_LIST_OF_FILE); }