diff --git a/src/gamedata/resourcefiles/file_directory.cpp b/src/gamedata/resourcefiles/file_directory.cpp index 22b3456fb..c721779b9 100644 --- a/src/gamedata/resourcefiles/file_directory.cpp +++ b/src/gamedata/resourcefiles/file_directory.cpp @@ -35,15 +35,11 @@ #include -#ifdef _WIN32 -#include -#else -#include -#endif #include "resourcefile.h" #include "cmdlib.h" #include "doomtype.h" +#include "i_system.h" @@ -71,12 +67,13 @@ struct FDirectoryLump : public FResourceLump class FDirectory : public FResourceFile { TArray Lumps; + const bool nosubdir; int AddDirectory(const char *dirpath); void AddEntry(const char *fullpath, int size); public: - FDirectory(const char * dirname); + FDirectory(const char * dirname, bool nosubdirflag = false); bool Open(bool quiet); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } }; @@ -89,8 +86,8 @@ public: // //========================================================================== -FDirectory::FDirectory(const char * directory) -: FResourceFile(NULL) +FDirectory::FDirectory(const char * directory, bool nosubdirflag) +: FResourceFile(NULL), nosubdir(nosubdirflag) { FString dirname; @@ -100,16 +97,15 @@ FDirectory::FDirectory(const char * directory) // Todo for Linux: Resolve the path before using it #endif dirname = directory; - #ifdef _WIN32 - free((void *)directory); - #endif - FixPathSeperator(dirname); +#ifdef _WIN32 + free((void *)directory); +#endif + dirname.Substitute("\\", "/"); if (dirname[dirname.Len()-1] != '/') dirname += '/'; FileName = dirname; } -#ifdef _WIN32 //========================================================================== // // Windows version @@ -118,15 +114,15 @@ FDirectory::FDirectory(const char * directory) int FDirectory::AddDirectory(const char *dirpath) { - struct _finddata_t fileinfo; - intptr_t handle; - FString dirmatch; + void * handle; int count = 0; - dirmatch = dirpath; + FString dirmatch = dirpath; + findstate_t find; dirmatch += '*'; - if ((handle = _findfirst(dirmatch, &fileinfo)) == -1) + handle = I_FindFirst(dirmatch.GetChars(), &find); + if (handle == ((void *)(-1))) { Printf("Could not scan '%s': %s\n", dirpath, strerror(errno)); } @@ -134,113 +130,50 @@ int FDirectory::AddDirectory(const char *dirpath) { do { - if (fileinfo.attrib & _A_HIDDEN) + // I_FindName only returns the file's name and not its full path + auto attr = I_FindAttr(&find); + if (attr & FA_HIDDEN) { // Skip hidden files and directories. (Prevents SVN bookkeeping // info from being included.) continue; } - if (fileinfo.attrib & _A_SUBDIR) + FString fi = I_FindName(&find); + if (attr & FA_DIREC) { - - if (fileinfo.name[0] == '.' && - (fileinfo.name[1] == '\0' || - (fileinfo.name[1] == '.' && fileinfo.name[2] == '\0'))) + if (nosubdir || (fi[0] == '.' && + (fi[1] == '\0' || + (fi[1] == '.' && fi[2] == '\0')))) { // Do not record . and .. directories. continue; } FString newdir = dirpath; - newdir << fileinfo.name << '/'; + newdir << fi << '/'; count += AddDirectory(newdir); } else { - if (strstr(fileinfo.name, ".orig") || strstr(fileinfo.name, ".bak")) + if (strstr(fi, ".orig") || strstr(fi, ".bak")) { - // We shouldn't add backup files to the lump directory + // We shouldn't add backup files to the file system continue; } - - AddEntry(FString(dirpath) + fileinfo.name, fileinfo.size); - count++; + size_t size = 0; + FString fn = FString(dirpath) + fi; + if (GetFileInfo(fn, &size, nullptr)) + { + AddEntry(fn, size); + count++; + } } - } while (_findnext(handle, &fileinfo) == 0); - _findclose(handle); + + } while (I_FindNext (handle, &find) == 0); + I_FindClose (handle); } return count; } -#else - -//========================================================================== -// -// add_dirs -// 4.4BSD version -// -//========================================================================== - -int FDirectory::AddDirectory(const char *dirpath) -{ - char *argv [2] = { NULL, NULL }; - argv[0] = new char[strlen(dirpath)+1]; - strcpy(argv[0], dirpath); - FTS *fts; - FTSENT *ent; - int count = 0; - - fts = fts_open(argv, FTS_LOGICAL, NULL); - if (fts == NULL) - { - Printf("Failed to start directory traversal: %s\n", strerror(errno)); - return 0; - } - - const size_t namepos = strlen(FileName); - FString pathfix; - - while ((ent = fts_read(fts)) != NULL) - { - if (ent->fts_info == FTS_D && ent->fts_name[0] == '.') - { - // Skip hidden directories. (Prevents SVN bookkeeping - // info from being included.) - fts_set(fts, ent, FTS_SKIP); - } - if (ent->fts_info == FTS_D && ent->fts_level == 0) - { - continue; - } - if (ent->fts_info != FTS_F) - { - // We're only interested in remembering files. - continue; - } - - // Some implementations add an extra separator between - // root of the hierarchy and entity's path. - // It needs to be removed in order to resolve - // lumps' relative paths properly. - const char* path = ent->fts_path; - - if ('/' == path[namepos]) - { - pathfix = FString(path, namepos); - pathfix.AppendCStrPart(&path[namepos + 1], ent->fts_pathlen - namepos - 1); - - path = pathfix.GetChars(); - } - - AddEntry(path, ent->fts_statp->st_size); - count++; - } - fts_close(fts); - delete[] argv[0]; - return count; -} -#endif - - //========================================================================== // // diff --git a/src/gamedata/textures/image.cpp b/src/gamedata/textures/image.cpp index 3c1e9de5a..9c524c56b 100644 --- a/src/gamedata/textures/image.cpp +++ b/src/gamedata/textures/image.cpp @@ -371,6 +371,8 @@ FImageSource * FImageSource::GetImage(int lumpnum, ETextureType usetype) if (ImageForLump[lumpnum] != nullptr) return ImageForLump[lumpnum]; auto data = Wads.OpenLumpReader(lumpnum); + if (!data.isOpen()) + return nullptr; for (size_t i = 0; i < countof(CreateInfo); i++) { diff --git a/src/utility/cmdlib.cpp b/src/utility/cmdlib.cpp index 9901a4060..50eeb67a4 100644 --- a/src/utility/cmdlib.cpp +++ b/src/utility/cmdlib.cpp @@ -35,6 +35,7 @@ #endif #endif #include "cmdlib.h" +#include "i_system.h" #include #include @@ -192,13 +193,41 @@ bool DirEntryExists(const char *pathname, bool *isdir) #else // Windows must use the wide version of stat to preserve non-standard paths. auto wstr = WideString(pathname); - struct _stat64i32 info; - bool res = _wstat64i32(wstr.c_str(), &info) == 0; + struct _stat64 info; + bool res = _wstat64(wstr.c_str(), &info) == 0; #endif if (isdir) *isdir = !!(info.st_mode & S_IFDIR); return res; } +//========================================================================== +// +// DirEntryExists +// +// Returns true if the given path exists, be it a directory or a file. +// +//========================================================================== + +bool GetFileInfo(const char* pathname, size_t *size, time_t *time) +{ + if (pathname == NULL || *pathname == 0) + return false; + +#ifndef _WIN32 + struct stat info; + bool res = stat(pathname, &info) == 0; +#else + // Windows must use the wide version of stat to preserve non-standard paths. + auto wstr = WideString(pathname); + struct _stat64 info; + bool res = _wstat64(wstr.c_str(), &info) == 0; +#endif + if (!res || (info.st_mode & S_IFDIR)) return false; + if (size) *size = info.st_size; + if (time) *time = info.st_mtime; + return res; +} + //========================================================================== // // DefaultExtension -- FString version @@ -269,7 +298,7 @@ FString ExtractFileBase (const char *path, bool include_extension) src--; // Check for files with drive specification but no path -#if defined(_WIN32) || defined(DOS) +#if defined(_WIN32) if (src == path && src[0] != 0) { if (src[1] == ':') @@ -828,8 +857,6 @@ FString NicePath(const char *path) } -#ifdef _WIN32 - //========================================================================== // // ScanDirectory @@ -838,13 +865,13 @@ FString NicePath(const char *path) bool ScanDirectory(TArray &list, const char *dirpath) { - struct _finddata_t fileinfo; - intptr_t handle; + findstate_t find; FString dirmatch; dirmatch << dirpath << "*"; - if ((handle = _findfirst(dirmatch, &fileinfo)) == -1) + auto handle = I_FindFirst(dirmatch.GetChars(), &find); + if (handle == ((void*)(-1))) { return false; } @@ -852,25 +879,27 @@ bool ScanDirectory(TArray &list, const char *dirpath) { do { - if (fileinfo.attrib & _A_HIDDEN) + 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 (fileinfo.attrib & _A_SUBDIR) + if (attr & FA_DIREC) { - if (fileinfo.name[0] == '.' && - (fileinfo.name[1] == '\0' || - (fileinfo.name[1] == '.' && fileinfo.name[2] == '\0'))) + 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 << fileinfo.name; + FFileList* fl = &list[list.Reserve(1)]; + fl->Filename << dirpath << fn; fl->isDirectory = true; FString newdir = fl->Filename; newdir << "/"; @@ -878,107 +907,17 @@ bool ScanDirectory(TArray &list, const char *dirpath) } else { - FFileList *fl = &list[list.Reserve(1)]; - fl->Filename << dirpath << fileinfo.name; + FFileList* fl = &list[list.Reserve(1)]; + fl->Filename << dirpath << fn; fl->isDirectory = false; } } - while (_findnext(handle, &fileinfo) == 0); - _findclose(handle); + while (I_FindNext(handle, &find) == 0); + I_FindClose(handle); } return true; } -#elif defined(__sun) || defined(__linux__) - -//========================================================================== -// -// ScanDirectory -// Solaris version -// -// Given NULL-terminated array of directory paths, create trees for them. -// -//========================================================================== - -bool ScanDirectory(TArray &list, const char *dirpath) -{ - DIR *directory = opendir(dirpath); - if(directory == NULL) - return false; - - struct dirent *file; - while((file = readdir(directory)) != NULL) - { - if(file->d_name[0] == '.') //File is hidden or ./.. directory so ignore it. - continue; - - FFileList *fl = &list[list.Reserve(1)]; - fl->Filename << dirpath << file->d_name; - - fl->isDirectory = DirExists(fl->Filename); - if(fl->isDirectory) - { - FString newdir = fl->Filename; - newdir += "/"; - ScanDirectory(list, newdir); - continue; - } - } - - closedir(directory); - return true; -} - -#else - -//========================================================================== -// -// ScanDirectory -// 4.4BSD version -// -//========================================================================== - -bool ScanDirectory(TArray &list, const char *dirpath) -{ - char * const argv[] = {new char[strlen(dirpath)+1], NULL }; - memcpy(argv[0], dirpath, strlen(dirpath)+1); - FTS *fts; - FTSENT *ent; - - fts = fts_open(argv, FTS_LOGICAL, NULL); - if (fts == NULL) - { - delete[] argv[0]; - return false; - } - while ((ent = fts_read(fts)) != NULL) - { - if (ent->fts_info == FTS_D && ent->fts_name[0] == '.') - { - // Skip hidden directories. (Prevents SVN bookkeeping - // info from being included.) - fts_set(fts, ent, FTS_SKIP); - } - if (ent->fts_info == FTS_D && ent->fts_level == 0) - { - FFileList *fl = &list[list.Reserve(1)]; - fl->Filename = ent->fts_path; - fl->isDirectory = true; - } - if (ent->fts_info == FTS_F) - { - // We're only interested in remembering files. - FFileList *fl = &list[list.Reserve(1)]; - fl->Filename = ent->fts_path; - fl->isDirectory = false; - } - } - fts_close(fts); - delete[] argv[0]; - return true; -} -#endif - //========================================================================== // diff --git a/src/utility/cmdlib.h b/src/utility/cmdlib.h index 7f42370e4..66ff9c728 100644 --- a/src/utility/cmdlib.h +++ b/src/utility/cmdlib.h @@ -30,6 +30,7 @@ typedef struct _GUID bool FileExists (const char *filename); bool DirExists(const char *filename); bool DirEntryExists (const char *pathname, bool *isdir = nullptr); +bool GetFileInfo(const char* pathname, size_t* size, time_t* time); extern FString progdir;