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 // Now try by searching the file path
// filename is modified with the full found path // filename is modified with the full found path
strcpy(filename, COM_Argv(1)); strcpy(filename, COM_Argv(1));
if (findfile(filename, NULL, true) != FS_NOTFOUND) if (findfile(filename, NULL, NULL, true) != FS_NOTFOUND)
FIL_ReadFile(filename, &buf); FIL_ReadFile(filename, &buf);
if (!buf) if (!buf)

View file

@ -1434,7 +1434,7 @@ static void IdentifyVersion(void)
#define MUSICTEST(str) \ #define MUSICTEST(str) \
musicpath = va(spandf,srb2waddir,"data",str);\ musicpath = va(spandf,srb2waddir,"data",str);\
handle = W_OpenWadFile(&musicpath, false); \ handle = W_OpenWadFile(&musicpath, NULL, false); \
if (handle) \ if (handle) \
{ \ { \
int ms = W_VerifyNMUSlumps(musicpath, handle, false); \ 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? // Maybe add md5 support?
if (strstr(filename, ".soc") != NULL) if (strstr(filename, ".soc") != NULL)
{ {
ncs = findfile(filename,NULL,true); ncs = findfile(filename, "addons", NULL, true);
if (ncs != FS_FOUND) if (ncs != FS_FOUND)
{ {
@ -4397,7 +4397,7 @@ static void Command_Addfile(void)
fhandle = NULL; fhandle = NULL;
} }
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) if ((fhandle = W_OpenWadFile(&fn, "addons", true)) != NULL)
{ {
musiconly = W_VerifyNMUSlumps(fn, fhandle, false); musiconly = W_VerifyNMUSlumps(fn, fhandle, false);
} }
@ -4523,7 +4523,7 @@ static void Got_RequestAddfilecmd(const UINT8 **cp, INT32 playernum)
if (numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
toomany = true; toomany = true;
else else
ncs = findfile(filename,md5sum,true); ncs = findfile(filename, "addons", md5sum, true);
if (ncs != FS_FOUND || toomany) if (ncs != FS_FOUND || toomany)
{ {
@ -4567,7 +4567,7 @@ static void Got_Addfilecmd(const UINT8 **cp, INT32 playernum)
return; return;
} }
ncs = findfile(filename,md5sum,true); ncs = findfile(filename, "addons", md5sum, true);
if (ncs != FS_FOUND || !P_AddWadFile(filename)) if (ncs != FS_FOUND || !P_AddWadFile(filename))
{ {

View file

@ -636,7 +636,7 @@ INT32 CL_CheckFiles(void)
packetsize += nameonlylength(fileneeded[i].filename) + 22; 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); CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
return 4; return 4;
} }
@ -1759,13 +1759,13 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum)
// Rewritten by Monster Iestyn to be less stupid // 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 // 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) // (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 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) 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 // 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 :) if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND; 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 // if not found at all, just move on without doing anything
// next, check SRB2's "path" directory // 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 :) if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND; 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 // if not found at all, just move on without doing anything
// finally check "." directory // 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 if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
return homecheck; // otherwise return the result we got 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); boolean fileexist(char *filename, time_t ptime);
// Search a file in the wadpath, return FS_FOUND when found // 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); boolean completepath);
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum); filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum);

View file

@ -333,7 +333,8 @@ char *refreshdirname = NULL;
#if defined (_XBOX) && defined (_MSC_VER) #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) boolean completepath, int maxsearchdepth)
{ {
//NONE? //NONE?
@ -364,7 +365,8 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
} }
#elif defined (_WIN32_WCE) #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) boolean completepath, int maxsearchdepth)
{ {
#ifdef __GNUC__ #ifdef __GNUC__
@ -378,6 +380,8 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
HANDLE searchhandle = INVALID_HANDLE_VALUE; HANDLE searchhandle = INVALID_HANDLE_VALUE;
const wchar_t wm[4] = L"*.*"; const wchar_t wm[4] = L"*.*";
(void)priorityfolder;
//if (startpath) SetCurrentDirectory(startpath); //if (startpath) SetCurrentDirectory(startpath);
if (FIL_ReadFileOK(filename)) if (FIL_ReadFileOK(filename))
{ {
@ -396,7 +400,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
//if (SetCurrentDirectory(dta.cFileName)) //if (SetCurrentDirectory(dta.cFileName))
{ // can fail if we haven't the right { // can fail if we haven't the right
filestatus_t found; filestatus_t found;
found = filesearch(filename,NULL,wantedmd5sum,completepath,maxsearchdepth-1); found = filesearch(filename,NULL,NULL,wantedmd5sum,completepath,maxsearchdepth-1);
//SetCurrentDirectory(".."); //SetCurrentDirectory("..");
if (found == FS_FOUND || found == FS_MD5SUMBAD) if (found == FS_FOUND || found == FS_MD5SUMBAD)
{ {
@ -442,7 +446,9 @@ static const char *filesearch_exclude[] = {
NULL 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; filestatus_t retval = FS_NOTFOUND;
DIR **dirhandle; DIR **dirhandle;
@ -479,6 +485,27 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
else else
searchpathindex[depthleft]--; 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)) while ((!found) && (depthleft < maxsearchdepth))
{ {
searchpath[searchpathindex[depthleft]]=0; searchpath[searchpathindex[depthleft]]=0;
@ -517,7 +544,14 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
if (depthleft == maxsearchdepth-1) if (depthleft == maxsearchdepth-1)
{ {
// When we're at the root of the search, we exclude certain folders. // 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)) if (strcasecmp(*path, dent->d_name))
continue; 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 filename the file to look for
\param startpath where to start look from \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 wantedmd5sum want to check with MD5
\param completepath want to return the complete path of the file? \param completepath want to return the complete path of the file?
\param maxsearchdepth the max depth to search for 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); boolean completepath, int maxsearchdepth);
#define menudepth 20 #define menudepth 20

View file

@ -1785,7 +1785,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
if (numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
toomany = true; toomany = true;
else else
ncs = findfile(filename, md5sum, false); ncs = findfile(filename, "addons", md5sum, false);
if (toomany) if (toomany)
{ {
@ -1894,7 +1894,7 @@ static UINT8 G_CheckDemoExtraFiles(savebuffer_t *info, boolean quick)
if (numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
error = DFILE_ERROR_CANNOTLOAD; 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; error = DFILE_ERROR_CANNOTLOAD;
else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER) else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER)
error |= DFILE_ERROR_NOTLOADED; 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 // If findfile finds the file, the full path will be returned
// in filenamebuf == filename. // in filenamebuf == filename.
if (findfile(filenamebuf, NULL, true)) if (findfile(filenamebuf, NULL, NULL, true))
{ {
if ((handle = fopen(filename, "rb")) == NULL) if ((handle = fopen(filename, "rb")) == NULL)
{ {

View file

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

View file

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

View file

@ -3432,7 +3432,7 @@ static const char *searchWad(const char *searchDir)
filestatus_t fstemp; filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD); strcpy(tempsw, WADKEYWORD);
fstemp = filesearch(tempsw,searchDir,NULL,true,20); fstemp = filesearch(tempsw, searchDir, NULL, NULL, true, 20);
if (fstemp == FS_FOUND) if (fstemp == FS_FOUND)
{ {
pathonly(tempsw); 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 // 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 // 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 // "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; 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 // If findfile finds the file, the full path will be returned
// in filenamebuf == *filename. // in filenamebuf == *filename.
if (findfile(filenamebuf, NULL, true)) if (findfile(filenamebuf, priorityfolder, NULL, true))
{ {
if ((handle = fopen(*filename, "rb")) == NULL) if ((handle = fopen(*filename, "rb")) == NULL)
{ {
@ -845,7 +845,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, const
} }
// open wad file // 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); return W_InitFileError(filename, startup);
important = W_VerifyNMUSlumps(filename, handle, startup); important = W_VerifyNMUSlumps(filename, handle, startup);
@ -2472,17 +2472,11 @@ void W_InitShaderLookup(const char *filename)
{ {
nameonly(filename_buf); nameonly(filename_buf);
if (findfile(filename_buf, NULL, true)) if (!findfile(filename_buf, "data", NULL, true))
{ return;
if ((handle = fopen(filename_buf, "rb")) == NULL)
{ if ((handle = fopen(filename_buf, "rb")) == NULL)
return;
}
}
else
{
return; return;
}
} }
// It is acceptable to fail opening the pk3 lookup. // It is acceptable to fail opening the pk3 lookup.

View file

@ -147,7 +147,7 @@ extern wadfile_t *wadfiles[MAX_WADFILES];
void W_Shutdown(void); 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 // 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 // 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); UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, const char *md5expected);