filesearch: Add "Priority folder" string parameter

If non-NULL, filesearch will begin in that subfolder of the desired searchpath, but can go back up to the root of the search later if not found in that location.

Primarily a small optimisation for checking the addons folder first
This commit is contained in:
toaster 2025-08-25 20:14:37 +01:00
parent 8230bbbca4
commit 48261ae4b5
14 changed files with 67 additions and 38 deletions

View file

@ -853,7 +853,7 @@ static void COM_Exec_f(void)
// Now try by searching the file path
// filename is modified with the full found path
strcpy(filename, COM_Argv(1));
if (findfile(filename, NULL, true) != FS_NOTFOUND)
if (findfile(filename, NULL, NULL, true) != FS_NOTFOUND)
FIL_ReadFile(filename, &buf);
if (!buf)

View file

@ -1434,7 +1434,7 @@ static void IdentifyVersion(void)
#define MUSICTEST(str) \
musicpath = va(spandf,srb2waddir,"data",str);\
handle = W_OpenWadFile(&musicpath, false); \
handle = W_OpenWadFile(&musicpath, NULL, false); \
if (handle) \
{ \
int ms = W_VerifyNMUSlumps(musicpath, handle, false); \

View file

@ -4311,7 +4311,7 @@ static void Got_RunSOCcmd(const UINT8 **cp, INT32 playernum)
// Maybe add md5 support?
if (strstr(filename, ".soc") != NULL)
{
ncs = findfile(filename,NULL,true);
ncs = findfile(filename, "addons", NULL, true);
if (ncs != FS_FOUND)
{
@ -4397,7 +4397,7 @@ static void Command_Addfile(void)
fhandle = NULL;
}
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL)
if ((fhandle = W_OpenWadFile(&fn, "addons", true)) != NULL)
{
musiconly = W_VerifyNMUSlumps(fn, fhandle, false);
}
@ -4523,7 +4523,7 @@ static void Got_RequestAddfilecmd(const UINT8 **cp, INT32 playernum)
if (numwadfiles >= MAX_WADFILES)
toomany = true;
else
ncs = findfile(filename,md5sum,true);
ncs = findfile(filename, "addons", md5sum, true);
if (ncs != FS_FOUND || toomany)
{
@ -4567,7 +4567,7 @@ static void Got_Addfilecmd(const UINT8 **cp, INT32 playernum)
return;
}
ncs = findfile(filename,md5sum,true);
ncs = findfile(filename, "addons", md5sum, true);
if (ncs != FS_FOUND || !P_AddWadFile(filename))
{

View file

@ -636,7 +636,7 @@ INT32 CL_CheckFiles(void)
packetsize += nameonlylength(fileneeded[i].filename) + 22;
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
fileneeded[i].status = findfile(fileneeded[i].filename, "addons", fileneeded[i].md5sum, true);
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
return 4;
}
@ -1759,13 +1759,13 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum)
// Rewritten by Monster Iestyn to be less stupid
// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned
// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore)
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
filestatus_t findfile(char *filename, const char *priorityfolder, const UINT8 *wantedmd5sum, boolean completepath)
{
filestatus_t homecheck; // store result of last file search
boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third)
// first, check SRB2's "home" directory
homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
homecheck = filesearch(filename, srb2home, priorityfolder, wantedmd5sum, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
@ -1774,7 +1774,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
// if not found at all, just move on without doing anything
// next, check SRB2's "path" directory
homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
homecheck = filesearch(filename, srb2path, priorityfolder, wantedmd5sum, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
@ -1783,7 +1783,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
// if not found at all, just move on without doing anything
// finally check "." directory
homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10);
homecheck = filesearch(filename, ".", priorityfolder, wantedmd5sum, completepath, 10);
if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
return homecheck; // otherwise return the result we got

View file

@ -157,7 +157,7 @@ void Command_Downloads_f(void);
boolean fileexist(char *filename, time_t ptime);
// Search a file in the wadpath, return FS_FOUND when found
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum,
filestatus_t findfile(char *filename, const char *suggestedfolder, const UINT8 *wantedmd5sum,
boolean completepath);
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum);

View file

@ -333,7 +333,8 @@ char *refreshdirname = NULL;
#if defined (_XBOX) && defined (_MSC_VER)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
filestatus_t filesearch(char *filename, const char *startpath,
const char *priorityfolder, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth)
{
//NONE?
@ -364,7 +365,8 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
}
#elif defined (_WIN32_WCE)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
filestatus_t filesearch(char *filename, const char *startpath,
const char *priorityfolder, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth)
{
#ifdef __GNUC__
@ -378,6 +380,8 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
HANDLE searchhandle = INVALID_HANDLE_VALUE;
const wchar_t wm[4] = L"*.*";
(void)priorityfolder;
//if (startpath) SetCurrentDirectory(startpath);
if (FIL_ReadFileOK(filename))
{
@ -396,7 +400,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
//if (SetCurrentDirectory(dta.cFileName))
{ // can fail if we haven't the right
filestatus_t found;
found = filesearch(filename,NULL,wantedmd5sum,completepath,maxsearchdepth-1);
found = filesearch(filename,NULL,NULL,wantedmd5sum,completepath,maxsearchdepth-1);
//SetCurrentDirectory("..");
if (found == FS_FOUND || found == FS_MD5SUMBAD)
{
@ -442,7 +446,9 @@ static const char *filesearch_exclude[] = {
NULL
};
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
filestatus_t filesearch(char *filename, const char *startpath,
const char *priorityfolder, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth)
{
filestatus_t retval = FS_NOTFOUND;
DIR **dirhandle;
@ -479,6 +485,27 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
else
searchpathindex[depthleft]--;
if (priorityfolder != NULL)
{
// Start the search at [startpath]/priorityfolder
strcpy(&searchpath[searchpathindex[depthleft]], priorityfolder);
if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
; // was the file (re)moved? can't stat it
else if (S_ISDIR(fsstat.st_mode) && depthleft)
{
if ((dirhandle[depthleft-1] = opendir(searchpath)) != NULL)
{
// Got read permissions!
searchpathindex[--depthleft] = strlen(searchpath) + 1;
searchpath[searchpathindex[depthleft]-1] = PATHSEP[0];
searchpath[searchpathindex[depthleft]] = 0;
}
}
}
while ((!found) && (depthleft < maxsearchdepth))
{
searchpath[searchpathindex[depthleft]]=0;
@ -517,7 +544,14 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
if (depthleft == maxsearchdepth-1)
{
// When we're at the root of the search, we exclude certain folders.
for (; *path; path++)
if (priorityfolder != NULL
&& strcasecmp(priorityfolder, dent->d_name))
{
// We skip revisiting the priority by pretending
// it matched the first exclude directory instead
}
else for (; *path; path++)
{
if (strcasecmp(*path, dent->d_name))
continue;

View file

@ -31,6 +31,7 @@ extern consvar_t cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_add
\param filename the file to look for
\param startpath where to start look from
\param priorityfolder priority for starting checking, then go back up?
\param wantedmd5sum want to check with MD5
\param completepath want to return the complete path of the file?
\param maxsearchdepth the max depth to search for the file
@ -40,7 +41,7 @@ extern consvar_t cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_add
*/
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
filestatus_t filesearch(char *filename, const char *startpath, const char *priorityfolder, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth);
#define menudepth 20

View file

@ -1785,7 +1785,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
if (numwadfiles >= MAX_WADFILES)
toomany = true;
else
ncs = findfile(filename, md5sum, false);
ncs = findfile(filename, "addons", md5sum, false);
if (toomany)
{
@ -1894,7 +1894,7 @@ static UINT8 G_CheckDemoExtraFiles(savebuffer_t *info, boolean quick)
if (numwadfiles >= MAX_WADFILES)
error = DFILE_ERROR_CANNOTLOAD;
else if (!quick && findfile(filename, md5sum, false) != FS_FOUND)
else if (!quick && findfile(filename, "addons", md5sum, false) != FS_FOUND)
error = DFILE_ERROR_CANNOTLOAD;
else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER)
error |= DFILE_ERROR_NOTLOADED;

View file

@ -628,7 +628,7 @@ void LUA_DumpFile(const char *filename)
// If findfile finds the file, the full path will be returned
// in filenamebuf == filename.
if (findfile(filenamebuf, NULL, true))
if (findfile(filenamebuf, NULL, NULL, true))
{
if ((handle = fopen(filename, "rb")) == NULL)
{

View file

@ -2160,7 +2160,7 @@ static const char *searchWad(const char *searchDir)
filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD);
fstemp = filesearch(tempsw,searchDir,NULL,true,20);
fstemp = filesearch(tempsw, searchDir, NULL, NULL, true, 20);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);

View file

@ -53,7 +53,7 @@ static char *searchFont(const char *fontsearchDir)
filestatus_t fstemp;
strcpy(tempsw, FONTFILE);
fstemp = filesearch(tempsw, fontsearchDir, NULL, true, 20);
fstemp = filesearch(tempsw, fontsearchDir, NULL, NULL, true, 20);
if (fstemp == FS_FOUND)
{
return tempsw;

View file

@ -3432,7 +3432,7 @@ static const char *searchWad(const char *searchDir)
filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD);
fstemp = filesearch(tempsw,searchDir,NULL,true,20);
fstemp = filesearch(tempsw, searchDir, NULL, NULL, true, 20);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);

View file

@ -186,7 +186,7 @@ static char filenamebuf[MAX_WADPATH];
// Returns the FILE * handle for the file, or NULL if not found or could not be opened
// If "useerrors" is true then print errors in the console, else just don't bother
// "filename" may be modified to have the correct path the actual file is located in, if necessary
FILE *W_OpenWadFile(const char **filename, boolean useerrors)
FILE *W_OpenWadFile(const char **filename, const char *priorityfolder, boolean useerrors)
{
FILE *handle;
@ -209,7 +209,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors)
// If findfile finds the file, the full path will be returned
// in filenamebuf == *filename.
if (findfile(filenamebuf, NULL, true))
if (findfile(filenamebuf, priorityfolder, NULL, true))
{
if ((handle = fopen(*filename, "rb")) == NULL)
{
@ -845,7 +845,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, const
}
// open wad file
if ((handle = W_OpenWadFile(&filename, true)) == NULL)
if ((handle = W_OpenWadFile(&filename, (mainfile ? NULL : "addons"), true)) == NULL)
return W_InitFileError(filename, startup);
important = W_VerifyNMUSlumps(filename, handle, startup);
@ -2472,18 +2472,12 @@ void W_InitShaderLookup(const char *filename)
{
nameonly(filename_buf);
if (findfile(filename_buf, NULL, true))
{
if (!findfile(filename_buf, "data", NULL, true))
return;
if ((handle = fopen(filename_buf, "rb")) == NULL)
{
return;
}
}
else
{
return;
}
}
// It is acceptable to fail opening the pk3 lookup.
// The shader pk3 lookup is only needed to build a lookup directory of the zip

View file

@ -147,7 +147,7 @@ extern wadfile_t *wadfiles[MAX_WADFILES];
void W_Shutdown(void);
// Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened
FILE *W_OpenWadFile(const char **filename, boolean useerrors);
FILE *W_OpenWadFile(const char **filename, const char *priorityfolder, boolean useerrors);
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, const char *md5expected);