diff --git a/renderdoc/os/os_specific.h b/renderdoc/os/os_specific.h index e1d7d2abb..2ea5f238d 100644 --- a/renderdoc/os/os_specific.h +++ b/renderdoc/os/os_specific.h @@ -264,6 +264,27 @@ uint64_t GetModifiedTimestamp(const string &filename); void Copy(const char *from, const char *to, bool allowOverwrite); void Delete(const char *path); +enum +{ + eFileProp_Directory = 0x1, + eFileProp_Hidden = 0x2, + eFileProp_Executable = 0x4, + + eFileProp_ErrorUnknown = 0x2000, + eFileProp_ErrorAccessDenied = 0x4000, + eFileProp_ErrorInvalidPath = 0x8000, +}; + +struct FoundFile +{ + FoundFile() : flags(0) {} + FoundFile(string fn, uint32_t f) : filename(fn), flags(f) {} + string filename; + uint32_t flags; +}; + +vector GetFilesInDirectory(const char *path); + FILE *fopen(const char *filename, const char *mode); size_t fread(void *buf, size_t elementSize, size_t count, FILE *f); diff --git a/renderdoc/os/posix/posix_stringio.cpp b/renderdoc/os/posix/posix_stringio.cpp index a0c32c770..8ea3b6cb8 100644 --- a/renderdoc/os/posix/posix_stringio.cpp +++ b/renderdoc/os/posix/posix_stringio.cpp @@ -22,6 +22,7 @@ * THE SOFTWARE. ******************************************************************************/ +#include #include // for dladdr #include #include @@ -234,6 +235,70 @@ void Delete(const char *path) unlink(path); } +vector GetFilesInDirectory(const char *path) +{ + vector ret; + + DIR *d = opendir(path); + + if(d == NULL) + { + uint32_t flags = eFileProp_ErrorUnknown; + + if(errno == ENOENT) + flags = eFileProp_ErrorInvalidPath; + else if(errno == EACCES) + flags = eFileProp_ErrorAccessDenied; + + ret.push_back(FoundFile(path, flags)); + return ret; + } + + dirent *ent = NULL; + + for(;;) + { + ent = readdir(d); + + if(!ent) + break; + + // skip "." and ".." + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) + continue; + + string fullpath = path; + fullpath += '/'; + fullpath += ent->d_name; + + struct ::stat st; + int res = stat(fullpath.c_str(), &st); + + // invalid/bad file - skip it + if(res != 0) + continue; + + uint32_t flags = 0; + + // make directory/executable mutually exclusive for clarity's sake + if(S_ISDIR(st.st_mode)) + flags |= eFileProp_Directory; + else if(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) + flags |= eFileProp_Executable; + + if(ent->d_name[0] == '.') + flags |= eFileProp_Hidden; + + ret.push_back(FoundFile(ent->d_name, flags)); + } + + // don't care if we hit an error or enumerated all files, just finish + + closedir(d); + + return ret; +} + FILE *fopen(const char *filename, const char *mode) { return ::fopen(filename, mode); diff --git a/renderdoc/os/win32/win32_stringio.cpp b/renderdoc/os/win32/win32_stringio.cpp index 475fdcf5c..c4ce34487 100644 --- a/renderdoc/os/win32/win32_stringio.cpp +++ b/renderdoc/os/win32/win32_stringio.cpp @@ -333,6 +333,82 @@ void Delete(const char *path) ::DeleteFileW(wpath.c_str()); } +vector GetFilesInDirectory(const char *path) +{ + vector ret; + + string pathstr = path; + + // normalise path to windows style + for(size_t i = 0; i < pathstr.size(); i++) + if(pathstr[i] == '/') + pathstr[i] = '\\'; + + // remove any trailing slash + if(pathstr[pathstr.size() - 1] == '\\') + pathstr.resize(pathstr.size() - 1); + + // append '\*' to do the search we want + pathstr += "\\*"; + + wstring wpath = StringFormat::UTF82Wide(pathstr); + + WIN32_FIND_DATAW findData = {}; + HANDLE find = FindFirstFileW(wpath.c_str(), &findData); + + if(find == INVALID_HANDLE_VALUE) + { + DWORD err = GetLastError(); + + uint32_t flags = eFileProp_ErrorUnknown; + + if(err == ERROR_FILE_NOT_FOUND) + flags = eFileProp_ErrorInvalidPath; + else if(err == ERROR_ACCESS_DENIED) + flags = eFileProp_ErrorAccessDenied; + + ret.push_back(FoundFile(path, flags)); + return ret; + } + + do + { + if(findData.cFileName[0] == L'.' && findData.cFileName[1] == 0) + { + // skip "." + } + else if(findData.cFileName[0] == L'.' && findData.cFileName[1] == L'.' && + findData.cFileName[2] == 0) + { + // skip ".." + } + else + { + uint32_t flags = 0; + + if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + flags |= eFileProp_Directory; + + if(findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + flags |= eFileProp_Hidden; + + if(wcsstr(findData.cFileName, L".EXE") || wcsstr(findData.cFileName, L".exe") || + wcsstr(findData.cFileName, L".Exe")) + { + flags |= eFileProp_Executable; + } + + ret.push_back(FoundFile(StringFormat::Wide2UTF8(findData.cFileName), flags)); + } + } while(FindNextFile(find, &findData) != FALSE); + + // don't care if we hit an error or enumerated all files, just finish + + FindClose(find); + + return ret; +} + FILE *fopen(const char *filename, const char *mode) { wstring wfn = StringFormat::UTF82Wide(string(filename));