Port faster file finding from SRB2Kart Saturn
This commit is contained in:
parent
f792afd288
commit
4208fdd197
6 changed files with 202 additions and 85 deletions
|
|
@ -712,7 +712,10 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
|
||||
// Loading progress
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, MENUCAPS|V_YELLOWMAP, "Checking server addons...");
|
||||
totalfileslength = !fileneedednum ? 0 : ((checkednum/fileneedednum) * 256);
|
||||
if (checkednum && fileneedednum)
|
||||
totalfileslength = (INT32)((checkednum/(double)(fileneedednum)) * 256);
|
||||
else
|
||||
totalfileslength = 0;
|
||||
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 96);
|
||||
|
|
|
|||
|
|
@ -1330,17 +1330,23 @@ static void IdentifyVersion(void)
|
|||
srb2waddir = I_LocateWad();
|
||||
#endif
|
||||
|
||||
char tempsrb2path[256] = ".";
|
||||
getcwd(tempsrb2path, 256);
|
||||
|
||||
// get the current directory (possible problem on NT with "." as current dir)
|
||||
if (srb2waddir)
|
||||
if (!srb2waddir)
|
||||
{
|
||||
strlcpy(srb2path,srb2waddir,sizeof (srb2path));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getcwd(srb2path, 256) != NULL)
|
||||
srb2waddir = srb2path;
|
||||
if (tempsrb2path[0])
|
||||
srb2waddir = tempsrb2path;
|
||||
else
|
||||
srb2waddir = ".";
|
||||
srb2waddir = srb2path;
|
||||
}
|
||||
|
||||
#if (1) // reduce the amount of findfile by only using full cwd in this func
|
||||
if (strcmp(tempsrb2path, srb2waddir))
|
||||
#endif
|
||||
{
|
||||
strlcpy(srb2path, srb2waddir, sizeof (srb2path));
|
||||
}
|
||||
|
||||
// Load the IWAD
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ typedef enum
|
|||
} mainwad_t;
|
||||
|
||||
// make sure not to write back the config until it's been correctly loaded
|
||||
extern boolean gameconfig_loaded;
|
||||
extern tic_t rendergametic;
|
||||
|
||||
extern char srb2home[256]; //Alam: My Home
|
||||
|
|
|
|||
|
|
@ -1763,23 +1763,63 @@ filestatus_t findfile(char *filename, UINT64 wantedhash, boolean completepath)
|
|||
filestatus_t homecheck; // store result of last file search
|
||||
boolean badhash = false; // store whether hash was bad from either of the first two searches (if nothing was found in the third)
|
||||
|
||||
// skip for startup, our mainwads wont be in there
|
||||
if (gameconfig_loaded)
|
||||
{
|
||||
if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0')
|
||||
{
|
||||
// first, check any custom directory if specified
|
||||
homecheck = filesearch(filename, cv_addons_folder.string, wantedhash, completepath, 10);
|
||||
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right md5
|
||||
badhash = true;
|
||||
// if not found at all, just move on without doing anything
|
||||
}
|
||||
|
||||
// next, check "DOWNLOAD" directory
|
||||
homecheck = filesearch(filename, "DOWNLOAD", wantedhash, completepath, 10);
|
||||
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
else if (homecheck == FS_BADHASH) // file has a bad md5; move on and look for a file with the right md5
|
||||
badhash = true;
|
||||
// if not found at all, just move on without doing anything
|
||||
|
||||
// next, check "addons" directory
|
||||
homecheck = filesearch(filename, "addons", wantedhash, completepath, 10);
|
||||
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
else if (homecheck == FS_BADHASH) // file has a bad md5; move on and look for a file with the right md5
|
||||
badhash = true;
|
||||
// if not found at all, just move on without doing anything
|
||||
}
|
||||
|
||||
// first, check SRB2's "home" directory
|
||||
homecheck = filesearch(filename, srb2home, wantedhash, completepath, 10);
|
||||
if (strcmp(srb2home, "."))
|
||||
{
|
||||
homecheck = filesearch(filename, srb2home, wantedhash, completepath, 10);
|
||||
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right hash
|
||||
badhash = true;
|
||||
// if not found at all, just move on without doing anything
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right hash
|
||||
badhash = true;
|
||||
// if not found at all, just move on without doing anything
|
||||
}
|
||||
|
||||
// next, check SRB2's "path" directory
|
||||
homecheck = filesearch(filename, srb2path, wantedhash, completepath, 10);
|
||||
if (strcmp(srb2home, "."))
|
||||
{
|
||||
// next, check SRB2's "path" directory
|
||||
homecheck = filesearch(filename, srb2path, wantedhash, completepath, 10);
|
||||
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right hash
|
||||
badhash = true;
|
||||
// if not found at all, just move on without doing anything
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right hash
|
||||
badhash = true;
|
||||
// if not found at all, just move on without doing anything
|
||||
}
|
||||
|
||||
// finally check "." directory
|
||||
homecheck = filesearch(filename, ".", wantedhash, completepath, 10);
|
||||
|
|
|
|||
191
src/filesrch.c
191
src/filesrch.c
|
|
@ -57,6 +57,14 @@ size_t dir_on[menudepth];
|
|||
UINT8 refreshdirmenu = 0;
|
||||
char *refreshdirname = NULL;
|
||||
|
||||
// skip those folders, they will not have any addons
|
||||
static const char *exclude_paths[] = {
|
||||
"logs",
|
||||
"models",
|
||||
"media",
|
||||
NULL
|
||||
};
|
||||
|
||||
filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash, boolean completepath, int maxsearchdepth)
|
||||
{
|
||||
filestatus_t retval = FS_NOTFOUND;
|
||||
|
|
@ -66,27 +74,28 @@ filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash
|
|||
struct stat fsstat;
|
||||
#endif
|
||||
int found = 0;
|
||||
char *searchname = strdup(filename);
|
||||
char *searchname;
|
||||
int depthleft = maxsearchdepth;
|
||||
char searchpath[MAXFILEPATH];
|
||||
size_t *searchpathindex;
|
||||
|
||||
dirhandle = (DIR**) malloc(maxsearchdepth * sizeof (DIR*));
|
||||
searchpathindex = (size_t *) malloc(maxsearchdepth * sizeof (size_t));
|
||||
dirhandle = (DIR**)malloc(maxsearchdepth * sizeof(DIR*));
|
||||
searchpathindex = (size_t *)malloc(maxsearchdepth * sizeof(size_t));
|
||||
|
||||
strcpy(searchpath,startpath);
|
||||
strcpy(searchpath, startpath);
|
||||
searchpathindex[--depthleft] = strlen(searchpath) + 1;
|
||||
|
||||
dirhandle[depthleft] = opendir(searchpath);
|
||||
|
||||
if (dirhandle[depthleft] == NULL)
|
||||
{
|
||||
free(searchname);
|
||||
free(dirhandle);
|
||||
free(searchpathindex);
|
||||
return FS_NOTFOUND;
|
||||
}
|
||||
|
||||
searchname = strdup(filename);
|
||||
|
||||
if (searchpath[searchpathindex[depthleft]-2] != PATHSEP[0])
|
||||
{
|
||||
searchpath[searchpathindex[depthleft]-1] = PATHSEP[0];
|
||||
|
|
@ -118,63 +127,89 @@ filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash
|
|||
// okay, now we actually want searchpath to incorporate d_name
|
||||
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
if (dent->d_type == DT_UNKNOWN && lstat(searchpath, &fsstat) == 0)
|
||||
{
|
||||
if (S_ISDIR(fsstat.st_mode))
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
if (dent->d_type == DT_UNKNOWN || dent->d_type == DT_LNK)
|
||||
if (stat(searchpath, &fsstat) == 0 && S_ISDIR(fsstat.st_mode))
|
||||
dent->d_type = DT_DIR;
|
||||
else if (S_ISLNK(fsstat.st_mode))
|
||||
dent->d_type = DT_LNK;
|
||||
}
|
||||
|
||||
// Symlinks aren't always directory symlinks. Dunno if this would resolve recursive
|
||||
// symlinks, but i think stat already does that
|
||||
if (dent->d_type == DT_LNK && stat(searchpath, &fsstat) == 0 && !S_ISDIR(fsstat.st_mode))
|
||||
{
|
||||
dent->d_type = DT_UNKNOWN;
|
||||
}
|
||||
|
||||
// Linux and FreeBSD has a special field for file type on dirent, so use that to speed up lookups.
|
||||
// FIXME: should we also follow symlinks?
|
||||
if ((dent->d_type == DT_DIR && depthleft) || (dent->d_type == DT_LNK && depthleft))
|
||||
#else
|
||||
if (dent->d_type == DT_DIR)
|
||||
#elif defined (_WIN32)
|
||||
// if we wanna follow symlinks we can check with FILE_ATTRIBUTE_REPARSE_POINT
|
||||
DWORD fileattr = GetFileAttributes(searchpath);
|
||||
if (fileattr == INVALID_FILE_ATTRIBUTES)
|
||||
; // was the file (re)moved? can't stat it
|
||||
else if ((fileattr & FILE_ATTRIBUTE_DIRECTORY) && depthleft)
|
||||
continue; // was the file (re)moved? can't stat it
|
||||
|
||||
if (fileattr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
#else
|
||||
if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||
continue; // was the file (re)moved? can't stat it
|
||||
|
||||
if (S_ISDIR(fsstat.st_mode))
|
||||
#endif
|
||||
{
|
||||
searchpathindex[--depthleft] = strlen(searchpath) + 1;
|
||||
dirhandle[depthleft] = opendir(searchpath);
|
||||
if (!dirhandle[depthleft])
|
||||
{
|
||||
// I am a folder!
|
||||
|
||||
if (!depthleft)
|
||||
continue; // No additional folder delving permitted...
|
||||
|
||||
const char **path = exclude_paths;
|
||||
|
||||
if (depthleft == maxsearchdepth-1)
|
||||
{
|
||||
// can't open it... maybe no read-permissions
|
||||
// go back to previous dir
|
||||
depthleft++;
|
||||
// When we're at the root of the search, we exclude certain folders.
|
||||
|
||||
boolean skipfolder = false;
|
||||
|
||||
for (; *path != NULL; path++)
|
||||
{
|
||||
if (strcasecmp(*path, dent->d_name) == 0)
|
||||
{
|
||||
skipfolder = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This folder is excluded
|
||||
if (skipfolder)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
searchpath[searchpathindex[depthleft]-1] = PATHSEP[0];
|
||||
searchpath[searchpathindex[depthleft]] = 0;
|
||||
}
|
||||
else if (!strcasecmp(searchname, dent->d_name))
|
||||
{
|
||||
switch (checkfilehash(searchpath, wantedhash))
|
||||
if (strcasecmp(".git", dent->d_name) // sanity if you're weird like me
|
||||
&& (dirhandle[depthleft-1] = opendir(searchpath)) != NULL)
|
||||
{
|
||||
case FS_FOUND:
|
||||
if (completepath)
|
||||
strcpy(filename,searchpath);
|
||||
else
|
||||
strcpy(filename,dent->d_name);
|
||||
retval = FS_FOUND;
|
||||
found = 1;
|
||||
break;
|
||||
case FS_BADHASH:
|
||||
retval = FS_BADHASH;
|
||||
break;
|
||||
default: // prevent some compiler warnings
|
||||
break;
|
||||
// Got read permissions!
|
||||
searchpathindex[--depthleft] = strlen(searchpath) + 1;
|
||||
|
||||
searchpath[searchpathindex[depthleft]-1] = PATHSEP[0];
|
||||
searchpath[searchpathindex[depthleft]] = 0;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// I am a file!
|
||||
|
||||
if (strcasecmp(searchname, dent->d_name))
|
||||
continue; // Not what we're looking for!
|
||||
|
||||
switch (checkfilehash(searchpath, wantedhash))
|
||||
{
|
||||
case FS_FOUND:
|
||||
if (completepath)
|
||||
strcpy(filename, searchpath);
|
||||
else
|
||||
strcpy(filename, dent->d_name);
|
||||
retval = FS_FOUND;
|
||||
found = 1;
|
||||
break;
|
||||
case FS_BADHASH:
|
||||
retval = FS_BADHASH;
|
||||
break;
|
||||
default: // prevent some compiler warnings
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -351,7 +386,9 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
|
|||
{
|
||||
DIR *dirhandle;
|
||||
struct dirent *dent;
|
||||
#ifndef _WIN32
|
||||
struct stat fsstat;
|
||||
#endif
|
||||
size_t pos = 0, folderpos = 0, numfolders = 0;
|
||||
char *tempname = NULL;
|
||||
|
||||
|
|
@ -390,30 +427,43 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
|
|||
if (!dent)
|
||||
break;
|
||||
else if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
continue; // we don't want to scan uptree
|
||||
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||
|
||||
if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||
#ifndef _WIN32
|
||||
if (stat(menupath, &fsstat) < 0)
|
||||
#else
|
||||
// if we wanna follow symlinks we can check with FILE_ATTRIBUTE_REPARSE_POINT
|
||||
DWORD fileattr = GetFileAttributes(menupath);
|
||||
if (fileattr == INVALID_FILE_ATTRIBUTES)
|
||||
#endif
|
||||
; // was the file (re)moved? can't stat it
|
||||
else // is a file or directory
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if (!S_ISDIR(fsstat.st_mode)) // file
|
||||
#else
|
||||
if (!(fileattr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
#endif
|
||||
{
|
||||
size_t len = strlen(dent->d_name)+1;
|
||||
if (replayhut)
|
||||
{
|
||||
if (strcasecmp(".lmp", dent->d_name+len-5)) continue; // Not a replay
|
||||
if (strcasecmp(".lmp", dent->d_name+len-5))
|
||||
continue; // Not a replay
|
||||
}
|
||||
else if (!cv_addons_showall.value)
|
||||
{
|
||||
UINT8 ext;
|
||||
for (ext = 0; ext < NUM_EXT_TABLE; ext++)
|
||||
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
|
||||
if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file
|
||||
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0])))
|
||||
break; // extension comparison
|
||||
if (ext == NUM_EXT_TABLE)
|
||||
continue; // not an addfile-able (or exec-able) file
|
||||
}
|
||||
}
|
||||
else // directory
|
||||
|
|
@ -465,7 +515,13 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
|
|||
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||
|
||||
if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||
#ifndef _WIN32
|
||||
if (stat(menupath, &fsstat) < 0)
|
||||
#else
|
||||
// if we wanna follow symlinks we can check with FILE_ATTRIBUTE_REPARSE_POINT
|
||||
DWORD fileattr = GetFileAttributes(menupath);
|
||||
if (fileattr == INVALID_FILE_ATTRIBUTES)
|
||||
#endif
|
||||
; // was the file (re)moved? can't stat it
|
||||
else // is a file or directory
|
||||
{
|
||||
|
|
@ -474,20 +530,28 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
|
|||
UINT8 ext = EXT_FOLDER;
|
||||
UINT8 folder;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (!S_ISDIR(fsstat.st_mode)) // file
|
||||
#else
|
||||
if (!(fileattr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
#endif
|
||||
{
|
||||
if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention
|
||||
if (!((numfolders+pos) < sizecoredirmenu))
|
||||
continue; // crash prevention
|
||||
|
||||
if (replayhut)
|
||||
{
|
||||
if (strcasecmp(".lmp", dent->d_name+len-5)) continue; // Not a replay
|
||||
if (strcasecmp(".lmp", dent->d_name+len-5))
|
||||
continue; // Not a replay
|
||||
ext = EXT_TXT; // This isn't used anywhere but better safe than sorry for messing with this...
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; ext < NUM_EXT_TABLE; ext++)
|
||||
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
|
||||
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
|
||||
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0])))
|
||||
break; // extension comparison
|
||||
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value)
|
||||
continue; // not an addfile-able (or exec-able) file
|
||||
ext += EXT_START; // moving to be appropriate position
|
||||
|
||||
if (ext >= EXT_LOADSTART)
|
||||
|
|
@ -504,6 +568,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
|
|||
|
||||
if (strcmp(dent->d_name, filenamebuf[i]))
|
||||
continue;
|
||||
|
||||
if (cv_addons_md5.value && !checkfilehash(menupath, wadfiles[i]->hash))
|
||||
continue;
|
||||
|
||||
|
|
@ -530,9 +595,11 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
|
|||
|
||||
if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL)))
|
||||
I_Error("preparefilemenu(): could not create file entry.");
|
||||
|
||||
temp[DIR_TYPE] = ext;
|
||||
temp[DIR_LEN] = (UINT8)(len);
|
||||
strlcpy(temp+DIR_STRING, dent->d_name, len);
|
||||
|
||||
if (folder)
|
||||
{
|
||||
strcpy(temp+len, PATHSEP);
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ char configfile[MAX_WADPATH];
|
|||
// ==========================================================================
|
||||
// CONFIGURATION
|
||||
// ==========================================================================
|
||||
static boolean gameconfig_loaded = false; // true once config.cfg loaded AND executed
|
||||
boolean gameconfig_loaded = false; // true once config.cfg loaded AND executed
|
||||
|
||||
/** Saves a player's config, possibly to a particular file.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue