mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-01 14:20:55 +00:00
- fixed: The directory scanner for reading a directory into the WAD file system and ScanDirectory were not Unicode capable on Windows.
Both now use the Unicode capable I_Find* interface instead of duplicating all its functionality in multiple platform dependent incarnations.
This commit is contained in:
parent
91589d9799
commit
9e13d3c60d
4 changed files with 86 additions and 211 deletions
|
@ -35,15 +35,11 @@
|
||||||
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#ifdef _WIN32
|
|
||||||
#include <io.h>
|
|
||||||
#else
|
|
||||||
#include <fts.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "resourcefile.h"
|
#include "resourcefile.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "doomtype.h"
|
#include "doomtype.h"
|
||||||
|
#include "i_system.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,12 +67,13 @@ struct FDirectoryLump : public FResourceLump
|
||||||
class FDirectory : public FResourceFile
|
class FDirectory : public FResourceFile
|
||||||
{
|
{
|
||||||
TArray<FDirectoryLump> Lumps;
|
TArray<FDirectoryLump> Lumps;
|
||||||
|
const bool nosubdir;
|
||||||
|
|
||||||
int AddDirectory(const char *dirpath);
|
int AddDirectory(const char *dirpath);
|
||||||
void AddEntry(const char *fullpath, int size);
|
void AddEntry(const char *fullpath, int size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FDirectory(const char * dirname);
|
FDirectory(const char * dirname, bool nosubdirflag = false);
|
||||||
bool Open(bool quiet);
|
bool Open(bool quiet);
|
||||||
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
|
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
|
||||||
};
|
};
|
||||||
|
@ -89,8 +86,8 @@ public:
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FDirectory::FDirectory(const char * directory)
|
FDirectory::FDirectory(const char * directory, bool nosubdirflag)
|
||||||
: FResourceFile(NULL)
|
: FResourceFile(NULL), nosubdir(nosubdirflag)
|
||||||
{
|
{
|
||||||
FString dirname;
|
FString dirname;
|
||||||
|
|
||||||
|
@ -100,16 +97,15 @@ FDirectory::FDirectory(const char * directory)
|
||||||
// Todo for Linux: Resolve the path before using it
|
// Todo for Linux: Resolve the path before using it
|
||||||
#endif
|
#endif
|
||||||
dirname = directory;
|
dirname = directory;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
free((void *)directory);
|
free((void *)directory);
|
||||||
#endif
|
#endif
|
||||||
FixPathSeperator(dirname);
|
dirname.Substitute("\\", "/");
|
||||||
if (dirname[dirname.Len()-1] != '/') dirname += '/';
|
if (dirname[dirname.Len()-1] != '/') dirname += '/';
|
||||||
FileName = dirname;
|
FileName = dirname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Windows version
|
// Windows version
|
||||||
|
@ -118,15 +114,15 @@ FDirectory::FDirectory(const char * directory)
|
||||||
|
|
||||||
int FDirectory::AddDirectory(const char *dirpath)
|
int FDirectory::AddDirectory(const char *dirpath)
|
||||||
{
|
{
|
||||||
struct _finddata_t fileinfo;
|
void * handle;
|
||||||
intptr_t handle;
|
|
||||||
FString dirmatch;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
dirmatch = dirpath;
|
FString dirmatch = dirpath;
|
||||||
|
findstate_t find;
|
||||||
dirmatch += '*';
|
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));
|
Printf("Could not scan '%s': %s\n", dirpath, strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -134,113 +130,50 @@ int FDirectory::AddDirectory(const char *dirpath)
|
||||||
{
|
{
|
||||||
do
|
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
|
// Skip hidden files and directories. (Prevents SVN bookkeeping
|
||||||
// info from being included.)
|
// info from being included.)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fileinfo.attrib & _A_SUBDIR)
|
FString fi = I_FindName(&find);
|
||||||
|
if (attr & FA_DIREC)
|
||||||
{
|
{
|
||||||
|
if (nosubdir || (fi[0] == '.' &&
|
||||||
if (fileinfo.name[0] == '.' &&
|
(fi[1] == '\0' ||
|
||||||
(fileinfo.name[1] == '\0' ||
|
(fi[1] == '.' && fi[2] == '\0'))))
|
||||||
(fileinfo.name[1] == '.' && fileinfo.name[2] == '\0')))
|
|
||||||
{
|
{
|
||||||
// Do not record . and .. directories.
|
// Do not record . and .. directories.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FString newdir = dirpath;
|
FString newdir = dirpath;
|
||||||
newdir << fileinfo.name << '/';
|
newdir << fi << '/';
|
||||||
count += AddDirectory(newdir);
|
count += AddDirectory(newdir);
|
||||||
}
|
}
|
||||||
else
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
size_t size = 0;
|
||||||
AddEntry(FString(dirpath) + fileinfo.name, fileinfo.size);
|
FString fn = FString(dirpath) + fi;
|
||||||
count++;
|
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;
|
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
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -371,6 +371,8 @@ FImageSource * FImageSource::GetImage(int lumpnum, ETextureType usetype)
|
||||||
if (ImageForLump[lumpnum] != nullptr) return ImageForLump[lumpnum];
|
if (ImageForLump[lumpnum] != nullptr) return ImageForLump[lumpnum];
|
||||||
|
|
||||||
auto data = Wads.OpenLumpReader(lumpnum);
|
auto data = Wads.OpenLumpReader(lumpnum);
|
||||||
|
if (!data.isOpen())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
for (size_t i = 0; i < countof(CreateInfo); i++)
|
for (size_t i = 0; i < countof(CreateInfo); i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "i_system.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -192,13 +193,41 @@ bool DirEntryExists(const char *pathname, bool *isdir)
|
||||||
#else
|
#else
|
||||||
// Windows must use the wide version of stat to preserve non-standard paths.
|
// Windows must use the wide version of stat to preserve non-standard paths.
|
||||||
auto wstr = WideString(pathname);
|
auto wstr = WideString(pathname);
|
||||||
struct _stat64i32 info;
|
struct _stat64 info;
|
||||||
bool res = _wstat64i32(wstr.c_str(), &info) == 0;
|
bool res = _wstat64(wstr.c_str(), &info) == 0;
|
||||||
#endif
|
#endif
|
||||||
if (isdir) *isdir = !!(info.st_mode & S_IFDIR);
|
if (isdir) *isdir = !!(info.st_mode & S_IFDIR);
|
||||||
return res;
|
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
|
// DefaultExtension -- FString version
|
||||||
|
@ -269,7 +298,7 @@ FString ExtractFileBase (const char *path, bool include_extension)
|
||||||
src--;
|
src--;
|
||||||
|
|
||||||
// Check for files with drive specification but no path
|
// 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 == path && src[0] != 0)
|
||||||
{
|
{
|
||||||
if (src[1] == ':')
|
if (src[1] == ':')
|
||||||
|
@ -828,8 +857,6 @@ FString NicePath(const char *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ScanDirectory
|
// ScanDirectory
|
||||||
|
@ -838,13 +865,13 @@ FString NicePath(const char *path)
|
||||||
|
|
||||||
bool ScanDirectory(TArray<FFileList> &list, const char *dirpath)
|
bool ScanDirectory(TArray<FFileList> &list, const char *dirpath)
|
||||||
{
|
{
|
||||||
struct _finddata_t fileinfo;
|
findstate_t find;
|
||||||
intptr_t handle;
|
|
||||||
FString dirmatch;
|
FString dirmatch;
|
||||||
|
|
||||||
dirmatch << dirpath << "*";
|
dirmatch << dirpath << "*";
|
||||||
|
|
||||||
if ((handle = _findfirst(dirmatch, &fileinfo)) == -1)
|
auto handle = I_FindFirst(dirmatch.GetChars(), &find);
|
||||||
|
if (handle == ((void*)(-1)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -852,25 +879,27 @@ bool ScanDirectory(TArray<FFileList> &list, const char *dirpath)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (fileinfo.attrib & _A_HIDDEN)
|
auto attr = I_FindAttr(&find);
|
||||||
|
if (attr & FA_HIDDEN)
|
||||||
{
|
{
|
||||||
// Skip hidden files and directories. (Prevents SVN bookkeeping
|
// Skip hidden files and directories. (Prevents SVN bookkeeping
|
||||||
// info from being included.)
|
// info from being included.)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
auto fn = I_FindName(&find);
|
||||||
|
|
||||||
if (fileinfo.attrib & _A_SUBDIR)
|
if (attr & FA_DIREC)
|
||||||
{
|
{
|
||||||
if (fileinfo.name[0] == '.' &&
|
if (fn[0] == '.' &&
|
||||||
(fileinfo.name[1] == '\0' ||
|
(fn[1] == '\0' ||
|
||||||
(fileinfo.name[1] == '.' && fileinfo.name[2] == '\0')))
|
(fn[1] == '.' && fn[2] == '\0')))
|
||||||
{
|
{
|
||||||
// Do not record . and .. directories.
|
// Do not record . and .. directories.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
FFileList *fl = &list[list.Reserve(1)];
|
FFileList* fl = &list[list.Reserve(1)];
|
||||||
fl->Filename << dirpath << fileinfo.name;
|
fl->Filename << dirpath << fn;
|
||||||
fl->isDirectory = true;
|
fl->isDirectory = true;
|
||||||
FString newdir = fl->Filename;
|
FString newdir = fl->Filename;
|
||||||
newdir << "/";
|
newdir << "/";
|
||||||
|
@ -878,107 +907,17 @@ bool ScanDirectory(TArray<FFileList> &list, const char *dirpath)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FFileList *fl = &list[list.Reserve(1)];
|
FFileList* fl = &list[list.Reserve(1)];
|
||||||
fl->Filename << dirpath << fileinfo.name;
|
fl->Filename << dirpath << fn;
|
||||||
fl->isDirectory = false;
|
fl->isDirectory = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (_findnext(handle, &fileinfo) == 0);
|
while (I_FindNext(handle, &find) == 0);
|
||||||
_findclose(handle);
|
I_FindClose(handle);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__sun) || defined(__linux__)
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ScanDirectory
|
|
||||||
// Solaris version
|
|
||||||
//
|
|
||||||
// Given NULL-terminated array of directory paths, create trees for them.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool ScanDirectory(TArray<FFileList> &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<FFileList> &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
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -30,6 +30,7 @@ typedef struct _GUID
|
||||||
bool FileExists (const char *filename);
|
bool FileExists (const char *filename);
|
||||||
bool DirExists(const char *filename);
|
bool DirExists(const char *filename);
|
||||||
bool DirEntryExists (const char *pathname, bool *isdir = nullptr);
|
bool DirEntryExists (const char *pathname, bool *isdir = nullptr);
|
||||||
|
bool GetFileInfo(const char* pathname, size_t* size, time_t* time);
|
||||||
|
|
||||||
extern FString progdir;
|
extern FString progdir;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue