From 5f3d25ef44f8c3b7964eb2e0f162bc551d2db08a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Aug 2023 12:18:35 +0200 Subject: [PATCH] - use ScanDirectory in all places where the findfile API was used. This allows to completely hide its implementation details from the rest of the code which only gets a list of file names now. --- src/common/audio/music/i_soundfont.cpp | 24 +-- src/common/audio/music/i_soundfont.h | 2 +- src/common/console/c_enginecmds.cpp | 2 +- src/common/filesystem/file_7z.cpp | 3 +- src/common/filesystem/file_directory.cpp | 84 ++------ src/common/filesystem/fs_findfile.cpp | 188 ++++++++++++++++-- src/common/filesystem/fs_findfile.h | 103 ++-------- src/common/filesystem/resourcefile.h | 11 -- src/common/utility/cmdlib.cpp | 64 +----- src/common/utility/cmdlib.h | 7 - src/common/utility/findfile.cpp | 235 ++--------------------- src/common/utility/findfile.h | 85 -------- src/d_iwad.cpp | 25 ++- src/maploader/glnodes.cpp | 11 +- src/menu/loadsavemenu.cpp | 95 +-------- 15 files changed, 263 insertions(+), 676 deletions(-) diff --git a/src/common/audio/music/i_soundfont.cpp b/src/common/audio/music/i_soundfont.cpp index dd487954c5..72b8ab44d7 100644 --- a/src/common/audio/music/i_soundfont.cpp +++ b/src/common/audio/music/i_soundfont.cpp @@ -42,7 +42,8 @@ #include #include "resourcefile.h" #include "version.h" -#include "findfile.h" +#include "fs_findfile.h" +#include "resourcefile.h" #include "i_interface.h" #include "configfile.h" #include "printf.h" @@ -331,7 +332,7 @@ FileReader FLumpPatchSetReader::OpenFile(const char *name) // //========================================================================== -void FSoundFontManager::ProcessOneFile(const FString &fn) +void FSoundFontManager::ProcessOneFile(const char* fn) { auto fb = ExtractFileBase(fn, false); auto fbe = ExtractFileBase(fn, true); @@ -391,9 +392,6 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) void FSoundFontManager::CollectSoundfonts() { - findstate_t c_file; - void *file; - FConfigFile* GameConfig = sysCallbacks.GetConfig ? sysCallbacks.GetConfig() : nullptr; if (GameConfig != NULL && GameConfig->SetSection ("SoundfontSearch.Directories")) { @@ -404,25 +402,23 @@ void FSoundFontManager::CollectSoundfonts() { if (stricmp (key, "Path") == 0) { + FileList list; + FString dir; dir = NicePath(value); FixPathSeperator(dir); if (dir.IsNotEmpty()) { - if (dir.Back() != '/') dir += '/'; - FString mask = dir + '*'; - if ((file = I_FindFirst(mask, &c_file)) != ((void *)(-1))) + if (ScanDirectory(list, dir.GetChars(), "*", true)) { - do + for(auto& entry : list) { - if (!(I_FindAttr(&c_file) & FA_DIREC)) + if (!entry.isDirectory) { - FStringf name("%s%s", dir.GetChars(), I_FindName(&c_file)); - ProcessOneFile(name); + ProcessOneFile(entry.FilePath.c_str()); } - } while (I_FindNext(file, &c_file) == 0); - I_FindClose(file); + } } } } diff --git a/src/common/audio/music/i_soundfont.h b/src/common/audio/music/i_soundfont.h index ef02950710..45e5b0ffa8 100644 --- a/src/common/audio/music/i_soundfont.h +++ b/src/common/audio/music/i_soundfont.h @@ -148,7 +148,7 @@ class FSoundFontManager { TArray soundfonts; - void ProcessOneFile(const FString & fn); + void ProcessOneFile(const char* fn); public: void CollectSoundfonts(); diff --git a/src/common/console/c_enginecmds.cpp b/src/common/console/c_enginecmds.cpp index 28133669ce..92b8cea539 100644 --- a/src/common/console/c_enginecmds.cpp +++ b/src/common/console/c_enginecmds.cpp @@ -50,7 +50,7 @@ #include "filesystem.h" #include "gstrings.h" #include "version.h" -#include "findfile.h" +#include "fs_findfile.h" #include "md5.h" #include "i_specialpaths.h" #include "i_system.h" diff --git a/src/common/filesystem/file_7z.cpp b/src/common/filesystem/file_7z.cpp index 9b1535be28..5539d54485 100644 --- a/src/common/filesystem/file_7z.cpp +++ b/src/common/filesystem/file_7z.cpp @@ -37,6 +37,7 @@ #include "7z.h" #include "7zCrc.h" #include "resourcefile.h" +#include "fs_findfile.h" @@ -276,8 +277,8 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf) for (size_t c = 0; c < nameLength; ++c) { nameASCII[c] = tolower(static_cast(nameUTF16[c])); - if (nameASCII[c] == '\\') nameASCII[c] = '/'; } + FixPathSeparator(&nameASCII.front()); lump_p->LumpNameSetup(nameASCII.c_str()); lump_p->LumpSize = static_cast(SzArEx_GetFileSize(archPtr, i)); diff --git a/src/common/filesystem/file_directory.cpp b/src/common/filesystem/file_directory.cpp index 51801c1662..7117df7600 100644 --- a/src/common/filesystem/file_directory.cpp +++ b/src/common/filesystem/file_directory.cpp @@ -39,6 +39,8 @@ #include "resourcefile.h" #include "fs_findfile.h" +std::string FS_FullPath(const char* directory); + #ifdef _WIN32 std::wstring toWide(const char* str); #endif @@ -99,95 +101,41 @@ FDirectory::FDirectory(const char * directory, bool nosubdirflag) // //========================================================================== -static bool FS_GetFileInfo(const char* pathname, size_t* size) -{ -#ifndef _WIN32 - struct stat info; - bool res = stat(pathname, &info) == 0; -#else - // Windows must use the wide version of stat to preserve non-ASCII paths. - struct _stat64 info; - bool res = _wstat64(toWide(pathname).c_str(), &info) == 0; -#endif - if (!res || (info.st_mode & S_IFDIR)) return false; - if (size) *size = (size_t)info.st_size; - return res; -} - -//========================================================================== -// -// Windows version -// -//========================================================================== - int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { - void * handle; int count = 0; - std::string dirmatch = dirpath; - dirmatch += '*'; - fs_findstate_t find; - - handle = FS_FindFirst(dirmatch.c_str(), &find); - if (handle == ((void *)(-1))) + FileList list; + if (!ScanDirectory(list, dirpath, "*")) { Printf(FSMessageLevel::Error, "Could not scan '%s': %s\n", dirpath, strerror(errno)); } else { - do + for(auto& entry : list) { - // FS_FindName only returns the file's name and not its full path - auto attr = FS_FindAttr(&find); - if (attr & FA_HIDDEN) + if (!entry.isDirectory) { - // Skip hidden files and directories. (Prevents SVN/Git bookkeeping - // info from being included.) - continue; - } - const char* fi = FS_FindName(&find); - if (attr & FA_DIREC) - { - if (nosubdir || (fi[0] == '.' && - (fi[1] == '\0' || - (fi[1] == '.' && fi[2] == '\0')))) - { - // Do not record . and .. directories. - continue; - } - std::string newdir = dirpath; - newdir += fi; - newdir += '/'; - count += AddDirectory(newdir.c_str(), filter, Printf); - } - else - { - if (strstr(fi, ".orig") || strstr(fi, ".bak") || strstr(fi, ".cache")) + auto fi = entry.FileName; + for (auto& c : fi) c = tolower(c); + if (strstr(fi.c_str(), ".orig") || strstr(fi.c_str(), ".bak") || strstr(fi.c_str(), ".cache")) { // We shouldn't add backup files to the file system continue; } - size_t size = 0; - std::string fn = dirpath; - fn += fi; - if (filter->filenamecheck == nullptr || filter->filenamecheck(fi, fn.c_str())) + if (filter->filenamecheck == nullptr || filter->filenamecheck(fi.c_str(), entry.FilePath.c_str())) { - if (FS_GetFileInfo(fn.c_str(), &size)) + if (entry.Length > 0x7fffffff) { - if (size > 0x7fffffff) - { - Printf(FSMessageLevel::Warning, "%s is larger than 2GB and will be ignored\n", fn.c_str()); - } - AddEntry(fn.c_str(), (int)size); - count++; + Printf(FSMessageLevel::Warning, "%s is larger than 2GB and will be ignored\n", entry.FilePath.c_str()); + continue; } + AddEntry(entry.FilePathRel.c_str(), (int)entry.Length); + count++; } } - - } while (FS_FindNext (handle, &find) == 0); - FS_FindClose (handle); + } } return count; } diff --git a/src/common/filesystem/fs_findfile.cpp b/src/common/filesystem/fs_findfile.cpp index 7e47b33f44..5830d2fca5 100644 --- a/src/common/filesystem/fs_findfile.cpp +++ b/src/common/filesystem/fs_findfile.cpp @@ -33,6 +33,31 @@ */ #include "fs_findfile.h" +#include + + +enum +{ + ZPATH_MAX = 260 +}; + +#ifndef _WIN32 + + +#else + + +enum +{ + FA_RDONLY = 1, + FA_HIDDEN = 2, + FA_SYSTEM = 4, + FA_DIREC = 16, + FA_ARCH = 32, +}; + +#endif + #ifndef _WIN32 @@ -40,6 +65,31 @@ #include #include +#include + +struct findstate_t +{ + std::string path; + struct dirent** namelist; + int current; + int count; +}; + +static const char* FS_FindName(findstate_t* fileinfo) +{ + return (fileinfo->namelist[fileinfo->current]->d_name); +} + +enum +{ + FA_RDONLY = 1, + FA_HIDDEN = 2, + FA_SYSTEM = 4, + FA_DIREC = 8, + FA_ARCH = 16, +}; + + static const char *pattern; static int matchfile(const struct dirent *ent) @@ -47,7 +97,7 @@ static int matchfile(const struct dirent *ent) return fnmatch(pattern, ent->d_name, FNM_NOESCAPE) == 0; } -void *FS_FindFirst(const char *const filespec, fs_findstate_t *const fileinfo) +static void *FS_FindFirst(const char *const filespec, findstate_t *const fileinfo) { const char* dir; @@ -76,9 +126,9 @@ void *FS_FindFirst(const char *const filespec, fs_findstate_t *const fileinfo) return (void *)-1; } -int FS_FindNext(void *const handle, fs_findstate_t *const fileinfo) +static int FS_FindNext(void *const handle, findstate_t *const fileinfo) { - fs_findstate_t *const state = static_cast(handle); + findstate_t *const state = static_cast(handle); if (state->current < fileinfo->count) { @@ -88,9 +138,9 @@ int FS_FindNext(void *const handle, fs_findstate_t *const fileinfo) return -1; } -int FS_FindClose(void *const handle) +static int FS_FindClose(void *const handle) { - fs_findstate_t *const state = static_cast(handle); + findstate_t *const state = static_cast(handle); if (handle != (void *)-1 && state->count > 0) { @@ -116,7 +166,7 @@ static bool DirEntryExists(const char* pathname, bool* isdir) return res; } -int FS_FindAttr(fs_findstate_t *const fileinfo) +static int FS_FindAttr(findstate_t *const fileinfo) { dirent *const ent = fileinfo->namelist[fileinfo->current]; const std::string path = fileinfo->path + ent->d_name; @@ -136,6 +186,15 @@ std::string FS_FullPath(const char* directory) return directory } +static size_t FS_GetFileSize(findstate_t* handle, const char* pathname) +{ + struct stat info; + bool res = stat(pathname, &info) == 0; + if (!res || (info.st_mode & S_IFDIR)) return 0; + return (size_t)info.st_size; +} + + #else #include @@ -161,6 +220,32 @@ static std::string toUtf8(const wchar_t* str) return utf8; } +struct findstate_t +{ + struct FileTime + { + uint32_t lo, hi; + }; + // Mirror WIN32_FIND_DATAW in . We cannot pull in the Windows header here as it would pollute all consumers' symbol space. + struct WinData + { + uint32_t Attribs; + FileTime Times[3]; + uint32_t Size[2]; + uint32_t Reserved[2]; + wchar_t Name[ZPATH_MAX]; + wchar_t AltName[14]; + }; + WinData FindData; + std::string UTF8Name; +}; + + +static int FS_FindAttr(findstate_t* fileinfo) +{ + return fileinfo->FindData.Attribs; +} + //========================================================================== // // FS_FindFirst @@ -170,10 +255,9 @@ static std::string toUtf8(const wchar_t* str) //========================================================================== -void *FS_FindFirst(const char *filespec, fs_findstate_t *fileinfo) +static void *FS_FindFirst(const char *filespec, findstate_t *fileinfo) { static_assert(sizeof(WIN32_FIND_DATAW) == sizeof(fileinfo->FindData), "FindData size mismatch"); - fileinfo->UTF8Name = ""; return FindFirstFileW(toWide(filespec).c_str(), (LPWIN32_FIND_DATAW)&fileinfo->FindData); } @@ -185,9 +269,8 @@ void *FS_FindFirst(const char *filespec, fs_findstate_t *fileinfo) // //========================================================================== -int FS_FindNext(void *handle, fs_findstate_t *fileinfo) +static int FS_FindNext(void *handle, findstate_t *fileinfo) { - fileinfo->UTF8Name = ""; return FindNextFileW((HANDLE)handle, (LPWIN32_FIND_DATAW)&fileinfo->FindData) == 0; } @@ -199,7 +282,7 @@ int FS_FindNext(void *handle, fs_findstate_t *fileinfo) // //========================================================================== -int FS_FindClose(void *handle) +static int FS_FindClose(void *handle) { return FindClose((HANDLE)handle); } @@ -212,12 +295,9 @@ int FS_FindClose(void *handle) // //========================================================================== -const char *FS_FindName(fs_findstate_t *fileinfo) +static const char *FS_FindName(findstate_t *fileinfo) { - if (fileinfo->UTF8Name.empty()) - { - fileinfo->UTF8Name = toUtf8(fileinfo->FindData.Name); - } + fileinfo->UTF8Name = toUtf8(fileinfo->FindData.Name); return fileinfo->UTF8Name.c_str(); } @@ -229,4 +309,80 @@ std::string FS_FullPath(const char* directory) for (auto& c : sdirectory) if (c == '\\') c = '/'; return sdirectory; } + +static size_t FS_GetFileSize(findstate_t* handle, const char* pathname) +{ + return handle->FindData.Size[1] + ((uint64_t)handle->FindData.Size[0] << 32); +} + #endif + + +//========================================================================== +// +// ScanDirectory +// +//========================================================================== + +static bool DoScanDirectory(FileList& list, const char* dirpath, const char* match, const char* relpath, bool nosubdir, bool readhidden) +{ + findstate_t find; + + std::string dirpathn = dirpath; + FixPathSeparator(&dirpathn.front()); + if (dirpathn[dirpathn.length() - 1] != '/') dirpathn += '/'; + + std::string dirmatch = dirpathn; + dirmatch += match; + + auto handle = FS_FindFirst(dirmatch.c_str(), &find); + if (handle == ((void*)(-1))) return false; + FileListEntry fl; + do + { + auto attr = FS_FindAttr(&find); + if (!readhidden && (attr & FA_HIDDEN)) + { + // Skip hidden files and directories. (Prevents SVN/git bookkeeping info from being included.) + continue; + } + auto fn = FS_FindName(&find); + + if (attr & FA_DIREC) + { + if (fn[0] == '.' && + (fn[1] == '\0' || + (fn[1] == '.' && fn[2] == '\0'))) + { + // Do not record . and .. directories. + continue; + } + } + + fl.FileName = fn; + fl.FilePath = dirpathn + fn; + fl.FilePathRel = relpath; + if (fl.FilePathRel.length() > 0) fl.FilePathRel += '/'; + fl.FilePathRel += fn; + fl.isDirectory = !!(attr & FA_DIREC); + fl.isReadonly = !!(attr & FA_RDONLY); + fl.isHidden = !!(attr & FA_HIDDEN); + fl.isSystem = !!(attr & FA_SYSTEM); + fl.Length = FS_GetFileSize(&find, fl.FilePath.c_str()); + list.push_back(fl); + if (!nosubdir && (attr & FA_DIREC)) + { + DoScanDirectory(list, fl.FilePath.c_str(), match, fl.FilePathRel.c_str(), false, readhidden); + fl.Length = 0; + } + } while (FS_FindNext(handle, &find) == 0); + FS_FindClose(handle); + return true; +} + + +bool ScanDirectory(std::vector& list, const char* dirpath, const char* match, bool nosubdir, bool readhidden) +{ + return DoScanDirectory(list, dirpath, match, "", nosubdir, readhidden); +} + diff --git a/src/common/filesystem/fs_findfile.h b/src/common/filesystem/fs_findfile.h index 528c428c3a..3c81009af0 100644 --- a/src/common/filesystem/fs_findfile.h +++ b/src/common/filesystem/fs_findfile.h @@ -2,97 +2,32 @@ // Directory searching routines #include +#include #include -enum +struct FileListEntry { - ZPATH_MAX = 260 + std::string FileName; // file name only + std::string FilePath; // full path to file + std::string FilePathRel; // path relative to the scanned directory. + size_t Length = 0; + bool isDirectory = false; + bool isReadonly = false; + bool isHidden = false; + bool isSystem = false; }; -#ifndef _WIN32 +using FileList = std::vector; -#include +bool ScanDirectory(std::vector& list, const char* dirpath, const char* match, bool nosubdir = false, bool readhidden = false); -struct fs_findstate_t +inline void FixPathSeparator(char* path) { -private: - std::string path; - struct dirent **namelist; - int current; - int count; - - friend void *FS_FindFirst(const char *filespec, fs_findstate_t *fileinfo); - friend int FS_FindNext(void *handle, fs_findstate_t *fileinfo); - friend const char *FS_FindName(fs_findstate_t *fileinfo); - friend int FS_FindAttr(fs_findstate_t *fileinfo); - friend int FS_FindClose(void *handle); -}; - -int FS_FindAttr (fs_findstate_t *fileinfo); - -inline const char *FS_FindName(fs_findstate_t *fileinfo) -{ - return (fileinfo->namelist[fileinfo->current]->d_name); + while (*path) + { + if (*path == '\\') + *path = '/'; + path++; + } } -enum -{ - FA_RDONLY = 1, - FA_HIDDEN = 2, - FA_SYSTEM = 4, - FA_DIREC = 8, - FA_ARCH = 16, -}; - - -#else - - -struct fs_findstate_t -{ -private: - struct FileTime - { - uint32_t lo, hi; - }; - // Mirror WIN32_FIND_DATAW in . We cannot pull in the Windows header here as it would pollute all consumers' symbol space. - struct WinData - { - uint32_t Attribs; - FileTime Times[3]; - uint32_t Size[2]; - uint32_t Reserved[2]; - wchar_t Name[ZPATH_MAX]; - wchar_t AltName[14]; - }; - WinData FindData; - std::string UTF8Name; - - friend void *FS_FindFirst(const char *filespec, fs_findstate_t *fileinfo); - friend int FS_FindNext(void *handle, fs_findstate_t *fileinfo); - friend const char *FS_FindName(fs_findstate_t *fileinfo); - friend int FS_FindAttr(fs_findstate_t *fileinfo); -}; - - -const char *FS_FindName(fs_findstate_t *fileinfo); -inline int FS_FindAttr(fs_findstate_t *fileinfo) -{ - return fileinfo->FindData.Attribs; -} - -enum -{ - FA_RDONLY = 1, - FA_HIDDEN = 2, - FA_SYSTEM = 4, - FA_DIREC = 16, - FA_ARCH = 32, -}; - -#endif - -void *FS_FindFirst (const char *filespec, fs_findstate_t *fileinfo); -int FS_FindNext (void *handle, fs_findstate_t *fileinfo); -int FS_FindClose (void *handle); -std::string FS_FullPath(const char* directory); diff --git a/src/common/filesystem/resourcefile.h b/src/common/filesystem/resourcefile.h index b2a81ac269..df68d7c8de 100644 --- a/src/common/filesystem/resourcefile.h +++ b/src/common/filesystem/resourcefile.h @@ -164,17 +164,6 @@ protected: void GenerateHash(); void PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter); - void FixPathSeparator(char* path) - { - while (*path) - { - if (*path == '\\') - *path = '/'; - path++; - } - } - - private: uint32_t FirstLump; diff --git a/src/common/utility/cmdlib.cpp b/src/common/utility/cmdlib.cpp index a3b2ef4f5d..f37bb6717d 100644 --- a/src/common/utility/cmdlib.cpp +++ b/src/common/utility/cmdlib.cpp @@ -35,7 +35,7 @@ #include "cmdlib.h" -#include "findfile.h" +#include "fs_findfile.h" #include "files.h" #include "md5.h" @@ -894,68 +894,6 @@ FString NicePath(const char *path) } -//========================================================================== -// -// ScanDirectory -// -//========================================================================== - -bool ScanDirectory(TArray &list, const char *dirpath) -{ - findstate_t find; - FString dirmatch; - - dirmatch << dirpath << "*"; - - auto handle = I_FindFirst(dirmatch.GetChars(), &find); - if (handle == ((void*)(-1))) - { - return false; - } - else - { - do - { - auto attr = I_FindAttr(&find); - if (attr & FA_HIDDEN) - { - // Skip hidden files and directories. (Prevents SVN bookkeeping - // info from being included.) - continue; - } - auto fn = I_FindName(&find); - - if (attr & FA_DIREC) - { - if (fn[0] == '.' && - (fn[1] == '\0' || - (fn[1] == '.' && fn[2] == '\0'))) - { - // Do not record . and .. directories. - continue; - } - - FFileList* fl = &list[list.Reserve(1)]; - fl->Filename << dirpath << fn; - fl->isDirectory = true; - FString newdir = fl->Filename; - newdir << "/"; - ScanDirectory(list, newdir); - } - else - { - FFileList* fl = &list[list.Reserve(1)]; - fl->Filename << dirpath << fn; - fl->isDirectory = false; - } - } - while (I_FindNext(handle, &find) == 0); - I_FindClose(handle); - } - return true; -} - - //========================================================================== // // diff --git a/src/common/utility/cmdlib.h b/src/common/utility/cmdlib.h index b319056e8b..e2e4aadbd0 100644 --- a/src/common/utility/cmdlib.h +++ b/src/common/utility/cmdlib.h @@ -69,13 +69,6 @@ void CreatePath(const char * fn); FString ExpandEnvVars(const char *searchpathstring); FString NicePath(const char *path); -struct FFileList -{ - FString Filename; - bool isDirectory; -}; - -bool ScanDirectory(TArray &list, const char *dirpath); bool IsAbsPath(const char*); FString M_ZLibError(int zerrnum); diff --git a/src/common/utility/findfile.cpp b/src/common/utility/findfile.cpp index 0da6a97fff..ab5c4299ce 100644 --- a/src/common/utility/findfile.cpp +++ b/src/common/utility/findfile.cpp @@ -38,160 +38,8 @@ #include "printf.h" #include "configfile.h" #include "i_system.h" +#include "fs_findfile.h" -#ifndef _WIN32 - -#include -#include -#include - -#include "cmdlib.h" - -static const char *pattern; - -static int matchfile(const struct dirent *ent) -{ - return fnmatch(pattern, ent->d_name, FNM_NOESCAPE) == 0; -} - -void *I_FindFirst(const char *const filespec, findstate_t *const fileinfo) -{ - FString dir; - - const char *const slash = strrchr(filespec, '/'); - - if (slash) - { - pattern = slash + 1; - dir = FString(filespec, slash - filespec + 1); - fileinfo->path = dir; - } - else - { - pattern = filespec; - dir = "."; - } - - fileinfo->current = 0; - fileinfo->count = scandir(dir.GetChars(), &fileinfo->namelist, matchfile, alphasort); - - if (fileinfo->count > 0) - { - return fileinfo; - } - - return (void *)-1; -} - -int I_FindNext(void *const handle, findstate_t *const fileinfo) -{ - findstate_t *const state = static_cast(handle); - - if (state->current < fileinfo->count) - { - return ++state->current < fileinfo->count ? 0 : -1; - } - - return -1; -} - -int I_FindClose(void *const handle) -{ - findstate_t *const state = static_cast(handle); - - if (handle != (void *)-1 && state->count > 0) - { - for (int i = 0; i < state->count; ++i) - { - free(state->namelist[i]); - } - - free(state->namelist); - state->namelist = nullptr; - state->count = 0; - } - - return 0; -} - -int I_FindAttr(findstate_t *const fileinfo) -{ - dirent *const ent = fileinfo->namelist[fileinfo->current]; - const FString path = fileinfo->path + ent->d_name; - bool isdir; - - if (DirEntryExists(path, &isdir)) - { - return isdir ? FA_DIREC : 0; - } - - return 0; -} - -#else - -#include -#include - -//========================================================================== -// -// I_FindFirst -// -// Start a pattern matching sequence. -// -//========================================================================== - - -void *I_FindFirst(const char *filespec, findstate_t *fileinfo) -{ - static_assert(sizeof(WIN32_FIND_DATAW) == sizeof(fileinfo->FindData), "FindData size mismatch"); - auto widespec = WideString(filespec); - fileinfo->UTF8Name = ""; - return FindFirstFileW(widespec.c_str(), (LPWIN32_FIND_DATAW)&fileinfo->FindData); -} - -//========================================================================== -// -// I_FindNext -// -// Return the next file in a pattern matching sequence. -// -//========================================================================== - -int I_FindNext(void *handle, findstate_t *fileinfo) -{ - fileinfo->UTF8Name = ""; - return !FindNextFileW((HANDLE)handle, (LPWIN32_FIND_DATAW)&fileinfo->FindData); -} - -//========================================================================== -// -// I_FindClose -// -// Finish a pattern matching sequence. -// -//========================================================================== - -int I_FindClose(void *handle) -{ - return FindClose((HANDLE)handle); -} - -//========================================================================== -// -// I_FindName -// -// Returns the name for an entry -// -//========================================================================== - -const char *I_FindName(findstate_t *fileinfo) -{ - if (fileinfo->UTF8Name.IsEmpty()) fileinfo->UTF8Name = fileinfo->FindData.Name; - return fileinfo->UTF8Name.GetChars(); -} - -#endif //========================================================================== // @@ -288,45 +136,20 @@ void D_AddWildFile(TArray& wadfiles, const char* value, const char *ext { D_AddFile(wadfiles, wadfile, true, -1, config); } - else - { // Try pattern matching - findstate_t findstate; - char path[ZPATH_MAX]; - char* sep; - void* handle = I_FindFirst(value, &findstate); - - strcpy(path, value); - sep = strrchr(path, '/'); - if (sep == nullptr) - { - sep = strrchr(path, '\\'); -#ifdef _WIN32 - if (sep == nullptr && path[1] == ':') + else + { + // Try pattern matching + FileList list; + auto path = ExtractFilePath(value); + auto name = ExtractFileBase(value, true); + if (path.IsEmpty()) path = "."; + if (ScanDirectory(list, path, name, true)) + { + for(auto& entry : list) { - sep = path + 1; + D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config); } -#endif } - - if (handle != ((void*)-1)) - { - do - { - if (!(I_FindAttr(&findstate) & FA_DIREC)) - { - if (sep == nullptr) - { - D_AddFile(wadfiles, I_FindName(&findstate), true, -1, config); - } - else - { - strcpy(sep + 1, I_FindName(&findstate)); - D_AddFile(wadfiles, path, true, -1, config); - } - } - } while (I_FindNext(handle, &findstate) == 0); - } - I_FindClose(handle); } } @@ -370,40 +193,16 @@ void D_AddConfigFiles(TArray& wadfiles, const char* section, const char void D_AddDirectory(TArray& wadfiles, const char* dir, const char *filespec, FConfigFile* config) { - FString curdir = I_GetCWD(); - if (curdir.IsNotEmpty()) + FileList list; + if (ScanDirectory(list, dir, "*.wad", true)) { - char skindir[ZPATH_MAX]; - findstate_t findstate; - void* handle; - size_t stuffstart; - - stuffstart = strlen(dir); - memcpy(skindir, dir, stuffstart * sizeof(*dir)); - skindir[stuffstart] = 0; - - if (skindir[stuffstart - 1] == '/') + for (auto& entry : list) { - skindir[--stuffstart] = 0; - } - - if (I_ChDir(skindir)) - { - skindir[stuffstart++] = '/'; - if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1) + if (!entry.isDirectory) { - do - { - if (!(I_FindAttr(&findstate) & FA_DIREC)) - { - strcpy(skindir + stuffstart, I_FindName(&findstate)); - D_AddFile(wadfiles, skindir, true, -1, config); - } - } while (I_FindNext(handle, &findstate) == 0); - I_FindClose(handle); + D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config); } } - I_ChDir(curdir); } } diff --git a/src/common/utility/findfile.h b/src/common/utility/findfile.h index 44bee1a35a..31f8bd65bb 100644 --- a/src/common/utility/findfile.h +++ b/src/common/utility/findfile.h @@ -4,91 +4,6 @@ #include #include "zstring.h" -enum -{ - ZPATH_MAX = 260 -}; - -#ifndef _WIN32 - -#include - -struct findstate_t -{ -private: - FString path; - struct dirent **namelist; - int current; - int count; - - friend void *I_FindFirst(const char *filespec, findstate_t *fileinfo); - friend int I_FindNext(void *handle, findstate_t *fileinfo); - friend const char *I_FindName(findstate_t *fileinfo); - friend int I_FindAttr(findstate_t *fileinfo); - friend int I_FindClose(void *handle); -}; - -int I_FindAttr (findstate_t *fileinfo); - -inline const char *I_FindName(findstate_t *fileinfo) -{ - return (fileinfo->namelist[fileinfo->current]->d_name); -} - -#define FA_RDONLY 1 -#define FA_HIDDEN 2 -#define FA_SYSTEM 4 -#define FA_DIREC 8 -#define FA_ARCH 16 - - -#else - -// Mirror WIN32_FIND_DATAW in - -struct findstate_t -{ -private: - struct FileTime - { - uint32_t lo, hi; - }; - struct WinData - { - uint32_t Attribs; - FileTime Times[3]; - uint32_t Size[2]; - uint32_t Reserved[2]; - wchar_t Name[ZPATH_MAX]; - wchar_t AltName[14]; - }; - WinData FindData; - FString UTF8Name; - - friend void *I_FindFirst(const char *filespec, findstate_t *fileinfo); - friend int I_FindNext(void *handle, findstate_t *fileinfo); - friend const char *I_FindName(findstate_t *fileinfo); - friend int I_FindAttr(findstate_t *fileinfo); -}; - - -const char *I_FindName(findstate_t *fileinfo); -inline int I_FindAttr(findstate_t *fileinfo) -{ - return fileinfo->FindData.Attribs; -} - -#define FA_RDONLY 0x00000001 -#define FA_HIDDEN 0x00000002 -#define FA_SYSTEM 0x00000004 -#define FA_DIREC 0x00000010 -#define FA_ARCH 0x00000020 - -#endif - -void *I_FindFirst (const char *filespec, findstate_t *fileinfo); -int I_FindNext (void *handle, findstate_t *fileinfo); -int I_FindClose (void *handle); class FConfigFile; diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 27bcb7276e..bfa67961a3 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -46,6 +46,7 @@ #include "version.h" #include "engineerrors.h" #include "v_text.h" +#include "fs_findfile.h" #include "findfile.h" #include "i_interface.h" @@ -471,36 +472,32 @@ void FIWadManager::CollectSearchPaths() void FIWadManager::AddIWADCandidates(const char *dir) { - void *handle; - findstate_t findstate; - FStringf slasheddir("%s/", dir); - FString findmask = slasheddir + "*.*"; - if ((handle = I_FindFirst(findmask, &findstate)) != (void *)-1) + FileList list; + + if (ScanDirectory(list, dir, "*", true)) { - do + for(auto& entry : list) { - if (!(I_FindAttr(&findstate) & FA_DIREC)) + if (!entry.isDirectory) { - auto FindName = I_FindName(&findstate); - auto p = strrchr(FindName, '.'); + auto p = strrchr(entry.FileName.c_str(), '.'); if (p != nullptr) { // special IWAD extension. if (!stricmp(p, ".iwad") || !stricmp(p, ".ipk3") || !stricmp(p, ".ipk7")) { - mFoundWads.Push(FFoundWadInfo{ slasheddir + FindName, "", -1 }); + mFoundWads.Push(FFoundWadInfo{ entry.FilePath.c_str(), "", -1 }); } } for (auto &name : mIWadNames) { - if (!stricmp(name, FindName)) + if (!stricmp(name, entry.FileName.c_str())) { - mFoundWads.Push(FFoundWadInfo{ slasheddir + FindName, "", -1 }); + mFoundWads.Push(FFoundWadInfo{ entry.FilePath.c_str(), "", -1 }); } } } - } while (I_FindNext(handle, &findstate) == 0); - I_FindClose(handle); + } } } diff --git a/src/maploader/glnodes.cpp b/src/maploader/glnodes.cpp index b7d773f03d..38fa976fd6 100644 --- a/src/maploader/glnodes.cpp +++ b/src/maploader/glnodes.cpp @@ -60,6 +60,7 @@ #include "g_levellocals.h" #include "i_time.h" #include "maploader.h" +#include "fs_findfile.h" EXTERN_CVAR(Bool, gl_cachenodes) EXTERN_CVAR(Float, gl_cachetime) @@ -1198,11 +1199,11 @@ bool MapLoader::CheckCachedNodes(MapData *map) UNSAFE_CCMD(clearnodecache) { - TArray list; + FileList list; FString path = M_GetCachePath(false); path += "/"; - if (!ScanDirectory(list, path)) + if (!ScanDirectory(list, path, "*", false)) { Printf("Unable to scan node cache directory %s\n", path.GetChars()); return; @@ -1210,15 +1211,15 @@ UNSAFE_CCMD(clearnodecache) // Scan list backwards so that when we reach a directory // all files within are already deleted. - for(int i = list.Size()-1; i >= 0; i--) + for(int i = (int)list.size()-1; i >= 0; i--) { if (list[i].isDirectory) { - rmdir(list[i].Filename); + rmdir(list[i].FilePath.c_str()); } else { - remove(list[i].Filename); + remove(list[i].FilePath.c_str()); } } diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index aaeb5ccbf0..e6ed52e9e2 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -44,7 +44,7 @@ #include "vm.h" #include "i_system.h" #include "v_video.h" -#include "findfile.h" +#include "fs_findfile.h" #include "v_draw.h" // Save name length limit for old binary formats. @@ -62,22 +62,16 @@ void FSavegameManager::ReadSaveStrings() { if (SaveGames.Size() == 0) { - void *filefirst; - findstate_t c_file; FString filter; LastSaved = LastAccessed = -1; quickSaveSlot = nullptr; - filter = G_BuildSaveName("*"); - filefirst = I_FindFirst(filter.GetChars(), &c_file); - if (filefirst != ((void *)(-1))) + FileList list; + if (ScanDirectory(list, G_GetSavegamesFolder().GetChars(), "*." SAVEGAME_EXT, true)) { - do + for (auto& entry : list) { - // I_FindName only returns the file's name and not its full path - FString filepath = G_BuildSaveName(I_FindName(&c_file)); - - std::unique_ptr savegame(FResourceFile::OpenResourceFile(filepath, true)); + std::unique_ptr savegame(FResourceFile::OpenResourceFile(entry.FilePath.c_str(), true)); if (savegame != nullptr) { bool oldVer = false; @@ -122,89 +116,14 @@ void FSavegameManager::ReadSaveStrings() } FSaveGameNode *node = new FSaveGameNode; - node->Filename = filepath; + node->Filename = entry.FilePath.c_str(); node->bOldVersion = oldVer; node->bMissingWads = missing; node->SaveTitle = title; InsertSaveNode(node); } - } - else // check for old formats. - { - FileReader file; - if (file.OpenFile(filepath)) - { - PNGHandle *png; - char sig[16]; - char title[OLDSAVESTRINGSIZE + 1]; - bool oldVer = true; - bool addIt = false; - bool missing = false; - - // ZDoom 1.23 betas 21-33 have the savesig first. - // Earlier versions have the savesig second. - // Later versions have the savegame encapsulated inside a PNG. - // - // Old savegame versions are always added to the menu so - // the user can easily delete them if desired. - - title[OLDSAVESTRINGSIZE] = 0; - - if (nullptr != (png = M_VerifyPNG(file))) - { - char *ver = M_GetPNGText(png, "ZDoom Save Version"); - if (ver != nullptr) - { - // An old version - if (!M_GetPNGText(png, "Title", title, OLDSAVESTRINGSIZE)) - { - strncpy(title, I_FindName(&c_file), OLDSAVESTRINGSIZE); - } - addIt = true; - delete[] ver; - } - delete png; - } - else - { - file.Seek(0, FileReader::SeekSet); - if (file.Read(sig, 16) == 16) - { - - if (strncmp(sig, "ZDOOMSAVE", 9) == 0) - { - if (file.Read(title, OLDSAVESTRINGSIZE) == OLDSAVESTRINGSIZE) - { - addIt = true; - } - } - else - { - memcpy(title, sig, 16); - if (file.Read(title + 16, OLDSAVESTRINGSIZE - 16) == OLDSAVESTRINGSIZE - 16 && - file.Read(sig, 16) == 16 && - strncmp(sig, "ZDOOMSAVE", 9) == 0) - { - addIt = true; - } - } - } - } - - if (addIt) - { - FSaveGameNode *node = new FSaveGameNode; - node->Filename = filepath; - node->bOldVersion = true; - node->bMissingWads = false; - node->SaveTitle = title; - InsertSaveNode(node); - } - } - } - } while (I_FindNext(filefirst, &c_file) == 0); - I_FindClose(filefirst); + } } } }