diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 434edc6ca..9f1e40b84 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -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); diff --git a/src/d_main.cpp b/src/d_main.cpp index bf4f10c2f..7c8b4ffc2 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -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 diff --git a/src/d_main.h b/src/d_main.h index f9f543d85..dad45f4ea 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -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 diff --git a/src/d_netfil.c b/src/d_netfil.c index dafc4a25a..e19009e94 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -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); diff --git a/src/filesrch.c b/src/filesrch.c index 033e0b3da..05448e760 100644 --- a/src/filesrch.c +++ b/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); diff --git a/src/m_misc.cpp b/src/m_misc.cpp index cebdd891e..46a029a13 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -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. *