mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-31 05:00:35 +00:00
Add QFS_FindFile.
QFS_FindFile's search can be constrained to begin or end at a certain vpath.
This commit is contained in:
parent
8bc2f7f6df
commit
6b87ddbb7c
2 changed files with 168 additions and 2 deletions
|
@ -67,6 +67,17 @@ typedef struct gamedir_s {
|
|||
} dir;
|
||||
} gamedir_t;
|
||||
|
||||
typedef struct vpath_s vpath_t;
|
||||
|
||||
typedef struct findfile_s {
|
||||
const vpath_t *vpath; ///< vpath in which file was found
|
||||
qboolean in_pak; ///< if true, path refers to a pak file rather
|
||||
///< than a directory
|
||||
const char *realname; ///< the name of the file as found (may have
|
||||
///< .gz appended, or .ogg substituded for
|
||||
///< .wav) does not include the path
|
||||
} findfile_t;
|
||||
|
||||
/** Cached information about the current game directory. \see \ref dirconf.
|
||||
*/
|
||||
extern gamedir_t *qfs_gamedir;
|
||||
|
@ -121,6 +132,30 @@ void QFS_Init (const char *game);
|
|||
*/
|
||||
void QFS_Gamedir (const char *gamedir);
|
||||
|
||||
/** Search for a file in the quake file-system.
|
||||
|
||||
The search will begin in the \a start vpath and end in the \a end vpath.
|
||||
If \a start is null, the search will begin in the vpath specified by
|
||||
qfs_vpaths (ie, the first directory in the \c Path attribute
|
||||
(\ref dirconf). If \a end is null, the search will continue to the end
|
||||
of the list of vpaths. If \a start and \a end are the same (and non-null),
|
||||
then only the one vpath will be searched.
|
||||
|
||||
\note All search paths in a vpath will be searched. This keeps \QF's
|
||||
directory system transparent.
|
||||
|
||||
\note It is a fatal error for \a end to be non-null but not in the list
|
||||
of vpaths.
|
||||
|
||||
\param fname The name of the file to be searched for.
|
||||
\param start The first vpath (gamedir) to search.
|
||||
\param start The last vpath (gamedir) to search.
|
||||
\return Pointer to the findfile_t record indicating the location
|
||||
of the file, or null if the file was not found.
|
||||
*/
|
||||
findfile_t *QFS_FindFile (const char *fname, const vpath_t *start,
|
||||
const vpath_t *end);
|
||||
|
||||
/** Open a file from within the user directory.
|
||||
|
||||
If \a path attempts to leave the user directory, this function sets
|
||||
|
|
|
@ -146,12 +146,20 @@ typedef struct searchpath_s {
|
|||
The purpose is to enable searches to be limited to a single gamedir or to
|
||||
not search past a certain gamedir.
|
||||
*/
|
||||
typedef struct vpath_s {
|
||||
struct vpath_s { // typedef to vpath_t is in quakefs.h
|
||||
char *name; // usually the gamedir name
|
||||
searchpath_t *user;
|
||||
searchpath_t *share;
|
||||
struct vpath_s *next;
|
||||
} vpath_t;
|
||||
};
|
||||
|
||||
typedef struct int_findfile_s {
|
||||
findfile_t ff;
|
||||
struct pack_s *pack;
|
||||
dpackfile_t *packfile;
|
||||
const char *path;
|
||||
int fname_index;
|
||||
} int_findfile_t;
|
||||
|
||||
static searchpath_t *free_searchpaths;
|
||||
static vpath_t *free_vpaths;
|
||||
|
@ -792,6 +800,129 @@ QFS_WriteFile (const char *filename, const void *data, int len)
|
|||
Qclose (f);
|
||||
}
|
||||
|
||||
static int_findfile_t *
|
||||
qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp,
|
||||
const char **fnames)
|
||||
{
|
||||
static int_findfile_t found;
|
||||
const char **fn;
|
||||
|
||||
found.ff.vpath = 0;
|
||||
found.ff.in_pak = false;
|
||||
found.pack = 0;
|
||||
found.packfile = 0;
|
||||
found.fname_index = 0;
|
||||
if (found.ff.realname) {
|
||||
free ((char *) found.ff.realname);
|
||||
found.ff.realname = 0;
|
||||
}
|
||||
if (found.path) {
|
||||
free ((char *) found.path);
|
||||
found.path = 0;
|
||||
}
|
||||
// is the element a pak file?
|
||||
if (sp->pack) {
|
||||
dpackfile_t *packfile;
|
||||
|
||||
for (fn = fnames; *fn; fn++) {
|
||||
packfile = pack_find_file (sp->pack, *fn);
|
||||
if (packfile) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (packfile) {
|
||||
Sys_MaskPrintf (SYS_FS_F, "PackFile: %s : %s\n",
|
||||
sp->pack->filename, packfile->name);
|
||||
found.ff.vpath = vpath;
|
||||
found.ff.in_pak = true;
|
||||
found.ff.realname = strdup (*fn);
|
||||
found.pack = sp->pack;
|
||||
found.packfile = packfile;
|
||||
found.fname_index = fn - fnames;
|
||||
found.path = strdup (sp->pack->filename);
|
||||
return &found;
|
||||
}
|
||||
} else {
|
||||
// check a file in the directory tree
|
||||
dstring_t *path = dstring_new ();
|
||||
|
||||
for (fn = fnames; *fn; fn++) {
|
||||
if (qfs_expand_path (path, sp->filename, *fn, 1) == 0) {
|
||||
if (Sys_FileTime (path->str) == -1) {
|
||||
dstring_delete (path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sys_MaskPrintf (SYS_FS_F, "FindFile: %s\n", path->str);
|
||||
|
||||
found.ff.vpath = vpath;
|
||||
found.ff.in_pak = false;
|
||||
found.ff.realname = strdup (*fn);
|
||||
found.path = strdup (path->str);
|
||||
found.fname_index = fn - fnames;
|
||||
return &found;
|
||||
}
|
||||
}
|
||||
dstring_delete (path);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int_findfile_t *
|
||||
qfs_findfile (const char **fnames, const vpath_t *start, const vpath_t *end)
|
||||
{
|
||||
const vpath_t *vp;
|
||||
searchpath_t *sp;
|
||||
int_findfile_t *found;
|
||||
|
||||
if (!start) {
|
||||
start = qfs_vpaths;
|
||||
}
|
||||
if (end) {
|
||||
for (vp = start; vp; vp = vp->next) {
|
||||
if (vp == end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!vp) {
|
||||
Sys_Error ("QFS_FindFile: end vpath not in search list");
|
||||
}
|
||||
end = end->next;
|
||||
}
|
||||
for (vp = start; vp && vp != end; vp = vp->next) {
|
||||
for (sp = vp->user; sp; sp = sp->next) {
|
||||
found = qfs_findfile_search (vp, sp, fnames);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
for (sp = vp->share; sp; sp = sp->next) {
|
||||
found = qfs_findfile_search (vp, sp, fnames);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
// file not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
VISIBLE findfile_t *
|
||||
QFS_FindFile (const char *fname, const vpath_t *start, const vpath_t *end)
|
||||
{
|
||||
int_findfile_t *found;
|
||||
const char *fname_list[2];
|
||||
|
||||
fname_list[0] = fname;
|
||||
fname_list[1] = 0;
|
||||
|
||||
found = qfs_findfile (fname_list, start, end);
|
||||
if (found) {
|
||||
return &found->ff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QFile *
|
||||
qfs_openread (const char *path, int offs, int len, int zip)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue