/* ============ FS_ExistsInGameDir See if a file exists in the mod directory/paks (ignores baseq2) ============ */ qboolean FS_ExistsInGameDir (char *filename) { size_t len; char *gamedir; char lowered[MAX_QPATH]; searchpath_t *search; pack_t *pak; Q_strncpy (lowered, filename, sizeof(lowered)-1); fast_strlwr (lowered); gamedir = FS_Gamedir(); len = strlen(gamedir); for (search = fs_searchpaths ; search ; search = search->next) { // is the element a pak file? if (search->pack) { packfile_t *entry; //r1: optimized btree search pak = search->pack; if (strncmp (pak->filename, gamedir, len)) continue; entry = rbfind (lowered, pak->rb); if (entry) return true; } else { char netpath[MAX_OSPATH]; if (strncmp (search->filename, gamedir, len)) continue; Com_sprintf (netpath, sizeof(netpath), "%s/%s",search->filename, filename); if (Sys_FileLength (netpath) != -1) return true; } } return false; }
/* ================= Mod_LoadSpriteModel ================= */ void Mod_LoadSpriteModel (model_t *mod, void *buffer) { dsprite_t *sprin, *sprout; int i; sprin = (dsprite_t *)buffer; sprout = (dsprite_t *) Hunk_Alloc (modfilelen); sprout->ident = LittleLong(sprin->ident); sprout->version = LittleLong(sprin->version); sprout->numframes = LittleLong(sprin->numframes); if (sprout->version != SPRITE_VERSION) VID_Error (ERR_DROP, "sprite %s has wrong version number (%i should be %i)", mod->name, sprout->version, SPRITE_VERSION); if (sprout->numframes > MAX_MD2SKINS) VID_Error (ERR_DROP, "sprite %s has too many frames (%i > %i)", mod->name, sprout->numframes, MAX_MD2SKINS); if (sprout->numframes <= 0) VID_Error (ERR_DROP, "sprite %s has no frames", mod->name); // byte swap everything for (i=0 ; i<sprout->numframes ; i++) { sprout->frames[i].width = LittleLong(sprin->frames[i].width); sprout->frames[i].height = LittleLong(sprin->frames[i].height); sprout->frames[i].origin_x = LittleLong(sprin->frames[i].origin_x); sprout->frames[i].origin_y = LittleLong(sprin->frames[i].origin_y); memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME); fast_strlwr (sprout->frames[i].name); mod->skins[i] = GL_FindImage (sprout->frames[i].name, sprout->frames[i].name, it_sprite); //r1: sprites crash if they don't have valid skins for framenum so be noisy if (!mod->skins[i]) VID_Printf (PRINT_ALL, "GL_FindImage: Couldn't find skin '%s' for sprite '%s'\n", sprout->frames[i].name, mod->name); } mod->type = mod_sprite; }
/* ================= Mod_LoadTexinfo ================= */ void Mod_LoadTexinfo (lump_t *l) { texinfo_t *in; // image_t *last_image; mtexinfo_t *out, *step; int i, count; char name[MAX_QPATH]; int next; size_t length; in = (texinfo_t *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) VID_Error (ERR_DROP, "Mod_LoadTexinfo: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = (mtexinfo_t *) Hunk_Alloc ( count*sizeof(*out)); loadmodel->texinfo = out; loadmodel->numtexinfo = count; for ( i=0 ; i<count ; i++, in++, out++) { memcpy (out->vecs, in->vecs, sizeof(out->vecs)); out->flags = LittleLong(in->flags); next = LittleLong(in->nexttexinfo); if (next > 0) out->next = loadmodel->texinfo + next; else out->next = NULL; fast_strlwr (in->texture); out->image = GL_FindImageBase (in->texture, it_wall); if (out->image) continue; Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); if (!GetWalInfo (name, &global_hax_texture_x, &global_hax_texture_y)) { VID_Printf (PRINT_ALL, "Couldn't load %s\n", name); out->image = r_notexture; continue; } length = strlen(name); if (load_tga_wals) { //Com_sprintf (name, sizeof(name), "textures/%s.tga", in->texture); memcpy (name + length-3, "tga", 3); out->image = GL_FindImage (name, in->texture, it_wall); } else { out->image = NULL; } if (!out->image) { if (load_png_wals) { memcpy (name + length-3, "png", 3); //Com_sprintf (name, sizeof(name), "textures/%s.png", in->texture); out->image = GL_FindImage (name, in->texture, it_wall); } if (!out->image) { if (load_jpg_wals) { memcpy (name + length-3, "jpg", 3); //Com_sprintf (name, sizeof(name), "textures/%s.jpg", in->texture); out->image = GL_FindImage (name, in->texture, it_wall); } if (!out->image) { memcpy (name + length-3, "wal", 3); //Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); out->image = GL_FindImage (name, in->texture, it_wall); if (!out->image) { VID_Printf (PRINT_ALL, "Couldn't load %s\n", name); out->image = r_notexture; } } } } //last_image = out->image; global_hax_texture_x = global_hax_texture_y = 0; } // count animation frames for (i=0 ; i<count ; i++) { out = &loadmodel->texinfo[i]; out->numframes = 1; for (step = out->next ; step && step != out ; step=step->next) out->numframes++; } }
/* ================== Mod_ForName Loads in a model for the given name ================== */ model_t *Mod_ForName (const char *name_, qboolean crash) { model_t *mod; model_t *modelhash; mscache_t *model_size; byte *buf; int i; unsigned hash; size_t len = strlen(name_); char *name = (char *) alloca(len + 1); strcpy(name, name_); if (!name || !name[0]) VID_Error (ERR_DROP, "Mod_ForName: NULL name"); // // inline models are grabbed only from worldmodel // if (name[0] == '*') { i = atoi(name+1); if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels) VID_Error (ERR_DROP, "bad inline model number %d", i); return &mod_inline[i]; } fast_strlwr (name); hash = hashify (name) % MODEL_HASH_SIZE; for (modelhash = models_hash[hash]; modelhash; modelhash = modelhash->hash_next) { if (!strcmp (modelhash->name, name)) { return modelhash; } } for (model_size = model_size_cache[hash]; model_size; model_size = model_size->hash_next) { if (!strcmp (model_size->name, name)) break; } // // search the currently loaded models // /*for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0] || mod->hash != hash) continue; if (!strcmp (mod->name, name) ) return mod; }*/ // // find a free model slot spot // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0]) break; // free spot } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) VID_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); mod_numknown++; } strncpy (mod->name, name, sizeof(mod->name)-1); // // load the file // modfilelen = FS_LoadFile (name, (void **)&buf); if (!buf) { if (crash) VID_Error (ERR_DROP, "Mod_NumForName: %s not found", mod->name); mod->name[0] = 0; return NULL; } loadmodel = mod; // // fill it in // // call the apropriate loader switch (LittleLong(*(unsigned *)buf)) { case IDALIASHEADER: if (model_size) loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size); else loadmodel->extradata = Hunk_Begin (0x200000, 0); Mod_LoadAliasModel (mod, buf); break; case IDSPRITEHEADER: if (model_size) loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size); else loadmodel->extradata = Hunk_Begin (0x4000, 0); Mod_LoadSpriteModel (mod, buf); break; case IDBSPHEADER: if (model_size) loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size); else loadmodel->extradata = Hunk_Begin (0x1000000, 0); Mod_LoadBrushModel (mod, buf); break; default: VID_Error (ERR_DROP,"Mod_NumForName: unknown 0x%.8x fileid for %s", LittleLong(*(unsigned *)buf), mod->name); break; } if (model_size) { loadmodel->extradatasize = model_size->size; } else { loadmodel->extradatasize = Hunk_End (); model_size = (mscache_t *) malloc (sizeof(*model_size)); if (!model_size) VID_Error (ERR_FATAL, "Mod_ForName: out of memory"); strcpy (model_size->name, mod->name); model_size->size = loadmodel->extradatasize; model_size->hash_next = model_size_cache[hash]; model_size_cache[hash] = model_size; } mod->hash_next = models_hash[hash]; models_hash[hash] = mod; FS_FreeFile (buf); return mod; }
/* ================= Mod_LoadAliasModel ================= */ void Mod_LoadAliasModel (model_t *mod, void *buffer) { unsigned int i; dmdl_t header; dmdl_t *pinmodel, *pheader; dstvert_t *pinst, *poutst; dtriangle_t *pintri, *pouttri; daliasframe_t *pinframe, *poutframe; int *pincmd, *poutcmd; int version; unsigned int required; char *skin_name; pinmodel = (dmdl_t *)buffer; version = LittleLong(pinmodel->version); if (version != ALIAS_VERSION) VID_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", mod->name, version, ALIAS_VERSION); //pheader = Hunk_Alloc (size); pheader = &header; // byte swap the header fields and sanity check memcpy (pheader, buffer, sizeof(dmdl_t)); if (pheader->skinheight > MAX_LBM_HEIGHT) Com_DPrintf("model %s has a skin taller than traditional maximum of %d", mod->name, MAX_LBM_HEIGHT); if (pheader->num_xyz <= 0) VID_Error (ERR_DROP, "model %s has no vertices", mod->name); if (pheader->num_xyz > MAX_VERTS) VID_Error (ERR_DROP, "model %s has too many vertices", mod->name); if (pheader->num_st <= 0) VID_Error (ERR_DROP, "model %s has no st vertices", mod->name); if (pheader->num_tris <= 0) VID_Error (ERR_DROP, "model %s has no triangles", mod->name); if (pheader->num_frames <= 0) VID_Error (ERR_DROP, "model %s has no frames", mod->name); if (pheader->num_skins >= 31) VID_Error (ERR_DROP, "model %s has too many skins", mod->name); if (pheader->ofs_st <= 0 || pheader->ofs_frames <= 0 || pheader->ofs_glcmds <= 0 || pheader->ofs_skins <= 0 || pheader->ofs_tris <= 0) VID_Error (ERR_DROP, "model %s has invalid offsets", mod->name); required = 0; required += sizeof(dmdl_t); required += pheader->num_st * sizeof(dstvert_t); required += pheader->num_tris * sizeof(dtriangle_t); required += pheader->num_frames * (sizeof(daliasframe_t)-4); //variable sized required += pheader->num_xyz * pheader->num_frames * sizeof(dtrivertx_t); required += pheader->num_glcmds * sizeof(int); required += pheader->num_skins * MAX_SKINNAME; if (pheader->ofs_end != required) VID_Error (ERR_DROP, "model %s has bad size header (%d != %d)", mod->name, pheader->ofs_end, required); if (pheader->ofs_frames + pheader->num_frames * sizeof(daliasframe_t) > required) VID_Error (ERR_DROP, "model %s has illegal frames offset", mod->name); if (pheader->ofs_glcmds + pheader->num_glcmds * sizeof(int) > required) VID_Error (ERR_DROP, "model %s has illegal glcmds offset", mod->name); if (pheader->ofs_skins + pheader->num_skins * MAX_SKINNAME > required) VID_Error (ERR_DROP, "model %s has illegal skins offset", mod->name); if (pheader->ofs_st + pheader->num_st * sizeof(dstvert_t) > required) VID_Error (ERR_DROP, "model %s has illegal vertices offset", mod->name); if (pheader->ofs_tris + pheader->num_tris * sizeof(dtriangle_t) > required) VID_Error (ERR_DROP, "model %s has illegal triangles offset", mod->name); if (pheader->framesize * pheader->num_frames != pheader->num_frames * (int)((sizeof(daliasframe_t)-4) + pheader->num_xyz*sizeof(dtrivertx_t))) VID_Error (ERR_DROP, "model %s has invalid frame size", mod->name); pheader = (dmdl_t *) Hunk_Alloc (required); memcpy (pheader, &header, sizeof(dmdl_t)); // // load base s and t vertices (not used in gl version) // pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st); poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st); memcpy (poutst, pinst, pheader->num_st * sizeof(dstvert_t)); // // load triangle lists // pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris); pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris); memcpy (pouttri, pintri, pheader->num_tris * sizeof(dtriangle_t)); // // load the frames // for (i=0 ; i<pheader->num_frames ; i++) { pinframe = (daliasframe_t *) ((byte *)pinmodel + pheader->ofs_frames + i * pheader->framesize); poutframe = (daliasframe_t *) ((byte *)pheader + pheader->ofs_frames + i * pheader->framesize); memcpy (poutframe, pinframe, sizeof(daliasframe_t)-4); memcpy (poutframe->verts, pinframe->verts, pheader->num_xyz*sizeof(dtrivertx_t)); } mod->type = mod_alias; // // load the glcmds // pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds); poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds); memcpy (poutcmd, pincmd, pheader->num_glcmds * sizeof(int)); // register all skins memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins, pheader->num_skins*MAX_SKINNAME); for (i=0 ; i<pheader->num_skins ; i++) { skin_name = (char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME; fast_strlwr (skin_name); mod->skins[i] = GL_FindImage (skin_name, skin_name, it_skin); } mod->mins[0] = -32; mod->mins[1] = -32; mod->mins[2] = -32; mod->maxs[0] = 32; mod->maxs[1] = 32; mod->maxs[2] = 32; }
/* ================= 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; }
int EXPORT FS_FOpenFile (const char *filename, FILE **file, handlestyle_t openHandle, qboolean *closeHandle) { fscache_t *cache; searchpath_t *search; pack_t *pak; filelink_t *link; char netpath[MAX_OSPATH]; char lowered[MAX_QPATH]; // check for links firstal if (!fs_noextern->intvalue) { for (link = fs_links ; link ; link=link->next) { if (!strncmp (filename, link->from, link->fromlength)) { Com_sprintf (netpath, sizeof(netpath), "%s%s",link->to, filename+link->fromlength); if (openHandle != HANDLE_NONE) { *file = fopen (netpath, "rb"); if (*file) { Com_DPrintf ("link file: %s\n",netpath); *closeHandle = true; return FS_filelength (*file); } return -1; } else { return Sys_FileLength (netpath); } } } } #ifdef BTREE_SEARCH cache = rbfind (filename, rb); if (cache) { cache = *(fscache_t **)cache; if (cache->filepath[0] == 0) { *file = NULL; return -1; } #ifdef _DEBUG Com_DPrintf ("File '%s' found in cache: %s\n", filename, cache->filepath); #endif if (openHandle != HANDLE_NONE) { if (cache->pak) { if (openHandle == HANDLE_DUPE) { *file = fopen (cache->pak->filename, "rb"); if (!*file) { Com_Printf ("WARNING: Cached pak '%s' failed to open! Did you delete it?\n", LOG_WARNING|LOG_GENERAL, cache->pak->filename); rbdelete (filename, rb); return -1; } *closeHandle = true; } else { *file = cache->pak->h.handle; *closeHandle = false; } } else { *file = fopen (cache->filepath, "rb"); if (!*file) { Com_Printf ("WARNING: Cached file '%s' failed to open! Did you delete it?\n", LOG_WARNING|LOG_GENERAL, cache->filepath); rbdelete (filename, rb); return -1; } //Com_Error (ERR_FATAL, "Couldn't open %s (cached)", cache->filepath); *closeHandle = true; } if (cache->fileseek && fseek (*file, cache->fileseek, SEEK_SET)) Com_Error (ERR_FATAL, "Couldn't seek to offset %u in %s (cached)", cache->fileseek, cache->filepath); } return cache->filelen; } #elif HASH_CACHE hash = hashify (filename); cache = &fscache; while (cache->next) { cache = cache->next; if (cache->hash == hash && !Q_stricmp (cache->filename, filename)) { Com_Printf (" (cached) ", LOG_GENERAL); if (cache->filepath[0] == 0) { *file = NULL; return -1; } *file = fopen (cache->filepath, "rb"); if (!*file) Com_Error (ERR_FATAL, "Couldn't open %s", cache->filepath); fseek (*file, cache->fileseek, SEEK_SET); return cache->filelen; } } #elif MAGIC_BTREE { magic_t *magic; hash = hashify (filename); magic = rbfind ((void *)hash, rb); if (magic) { magic = *(magic_t **)magic; do { cache = magic->entry; if (!Q_stricmp (cache->filename, filename)) { if (cache->filepath[0] == 0) { *file = NULL; return -1; } *file = fopen (cache->filepath, "rb"); if (!*file) Com_Error (ERR_FATAL, "Couldn't open %s", cache->filepath); fseek (*file, cache->fileseek, SEEK_SET); return cache->filelen; } magic = magic->next; } while (magic); } } #endif #ifdef _DEBUG Com_DPrintf ("File '%s' not found in cache, searching fs_searchpaths\n", filename); #endif Q_strncpy (lowered, filename, sizeof(lowered)-1); fast_strlwr (lowered); for (search = fs_searchpaths ; search ; search = search->next) { // is the element a pak file? if (search->pack) { // char *lower; packfile_t *entry; //r1: optimized btree search pak = search->pack; if (pak->type == PAK_QUAKE) { entry = rbfind (lowered, pak->rb); if (entry) { entry = *(packfile_t **)entry; #ifdef _DEBUG Com_DPrintf ("File '%s' found in %s, (%s)\n", filename, pak->filename, entry->name); #endif if (openHandle != HANDLE_NONE) { //*file = fopen (pak->filename, "rb"); if (openHandle == HANDLE_DUPE) { *file = fopen (pak->filename, "rb"); *closeHandle = true; } else { *file = pak->h.handle; *closeHandle = false; } //if (!*file) // Com_Error (ERR_FATAL, "Couldn't reopen pak file %s", pak->filename); if (fseek (*file, entry->filepos, SEEK_SET)) Com_Error (ERR_FATAL, "Couldn't seek to offset %u for %s in %s", entry->filepos, entry->name, pak->filename); } if (fs_cache->intvalue & 1) { #if BTREE_SEARCH FS_AddToCache (pak->filename, entry->filelen, entry->filepos, filename, pak); #elif HASH_CACHE FS_AddToCache (hash, pak->filename, entry->filelen, entry->filepos, cache, filename); #elif MAGIC_BTREE FS_AddToCache (pak->filename, entry->filelen, entry->filepos, filename, hash); #endif } return entry->filelen; } } } else if (!fs_noextern->intvalue) { struct stat statInfo; int filelen; // check a file in the directory tree Com_sprintf (netpath, sizeof(netpath), "%s/%s",search->filename, filename); if (openHandle == HANDLE_NONE) { filelen = Sys_FileLength (netpath); if (filelen == -1) continue; if (fs_cache->intvalue & 4) FS_AddToCache (netpath, filelen, 0, filename, NULL); return filelen; } //fix for moronic implementations that allow fopen (FILE OPEN) to open a directory //(this means you linux and krew) if (stat (netpath, &statInfo)) continue; if (statInfo.st_mode & S_IFDIR) { Com_Printf ("WARNING: Tried to open a directory as a file: %s\n", LOG_WARNING, netpath); continue; } *file = fopen (netpath, "rb"); if (!*file) continue; *closeHandle = true; Com_DPrintf ("FindFile: %s\n",netpath); filelen = FS_filelength (*file); if (fs_cache->intvalue & 4) { #if BTREE_SEARCH FS_AddToCache (netpath, filelen, 0, filename, NULL); #elif HASH_CACHE FS_AddToCache (hash, netpath, filelen, 0, cache, filename); #elif MAGIC_BTREE FS_AddToCache (netpath, filelen, 0, filename, hash); #endif } return filelen; } } Com_DPrintf ("FindFile: can't find %s\n", filename); if (fs_cache->intvalue & 2) { #if BTREE_SEARCH FS_AddToCache (NULL, 0, 0, filename, NULL); #elif HASH_CACHE FS_AddToCache (hash, NULL, 0, 0, cache, filename); #elif MAGIC_BTREE FS_AddToCache (NULL, 0, 0, filename, hash); #endif } *file = NULL; return -1; }
void FS_WhereIs_f (void) { char *filename; searchpath_t *search; pack_t *pak; filelink_t *link; char netpath[MAX_OSPATH]; char lowered[MAX_QPATH]; if (Cmd_Argc() != 2) { Com_Printf ("Purpose: Find where a file is being loaded from on the filesystem.\n" "Syntax : whereis <path>\n" "Example: whereis maps/q2dm1.bsp\n", LOG_GENERAL); return; } filename = Cmd_Argv(1); // check for links firstal if (!fs_noextern->intvalue) { for (link = fs_links ; link ; link=link->next) { if (!strncmp (filename, link->from, link->fromlength)) { int len; Com_sprintf (netpath, sizeof(netpath), "%s%s",link->to, filename+link->fromlength); len = Sys_FileLength (netpath); if (len != -1) { Com_Printf ("%s is found on disk as %s (using linkpath), %d bytes.\n", LOG_GENERAL, Cmd_Argv(1), netpath, len); } else { Com_Printf ("%s is not found.\n", LOG_GENERAL, Cmd_Argv(1)); } return; } } } Q_strncpy (lowered, filename, sizeof(lowered)-1); fast_strlwr (lowered); for (search = fs_searchpaths ; search ; search = search->next) { // is the element a pak file? if (search->pack) { packfile_t *entry; //r1: optimized btree search pak = search->pack; entry = rbfind (lowered, pak->rb); if (entry) { entry = *(packfile_t **)entry; Com_Printf ("%s is found in pakfile %s as %s, %d bytes.\n", LOG_GENERAL, Cmd_Argv(1), pak->filename, entry->name, entry->filelen); return; } } else if (!fs_noextern->intvalue) { int filelen; // check a file in the directory tree Com_sprintf (netpath, sizeof(netpath), "%s/%s",search->filename, filename); filelen = Sys_FileLength (netpath); if (filelen == -1) continue; Com_Printf ("%s is found on disk as %s, %d bytes.\n", LOG_GENERAL, Cmd_Argv(1), netpath, filelen); return; } } Com_Printf ("%s is not found.\n", LOG_GENERAL, Cmd_Argv(1)); }