aboutsummaryrefslogtreecommitdiff
path: root/zencore/filesystem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zencore/filesystem.cpp')
-rw-r--r--zencore/filesystem.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/zencore/filesystem.cpp b/zencore/filesystem.cpp
index 741e3ee19..a03623196 100644
--- a/zencore/filesystem.cpp
+++ b/zencore/filesystem.cpp
@@ -17,6 +17,7 @@
# include <winioctl.h>
# include <winnt.h>
#else
+# include <dirent.h>
# include <fcntl.h>
# include <sys/stat.h>
# include <unistd.h>
@@ -610,6 +611,7 @@ ToUtf8(const std::filesystem::path& Path)
void
FileSystemTraversal::TraverseFileSystem(const std::filesystem::path& RootDir, TreeVisitor& Visitor)
{
+#if ZEN_PLATFORM_WINDOWS
uint64_t FileInfoBuffer[8 * 1024];
FILE_INFO_BY_HANDLE_CLASS FibClass = FileIdBothDirectoryRestartInfo;
@@ -697,8 +699,53 @@ FileSystemTraversal::TraverseFileSystem(const std::filesystem::path& RootDir, Tr
EntryOffset += NextOffset;
}
}
+#else
+ using namespace fmt::literals;
+
+ /* Could also implement this using Linux's getdents() syscall */
+
+ DIR* Dir = opendir(RootDir.c_str());
+ if (Dir == nullptr)
+ {
+ ThrowLastError("Failed to open directory for traversal: {}"_format(RootDir.c_str()));
+ }
+
+ for (struct dirent* Entry; Entry = readdir(Dir);)
+ {
+ const char* FileName = Entry->d_name;
+
+ struct stat Stat;
+ std::filesystem::path FullPath = RootDir / FileName;
+ stat(FullPath.c_str(), &Stat);
+
+ if (S_ISDIR(Stat.st_mode))
+ {
+ if (strcmp(FileName, ".") == 0 || strcmp(FileName, "..") == 0)
+ {
+ /* nop */
+ }
+ else if (Visitor.VisitDirectory(RootDir, FileName))
+ {
+ TraverseFileSystem(FullPath, Visitor);
+ }
+ }
+ else if (S_ISREG(Stat.st_mode))
+ {
+ Visitor.VisitFile(RootDir, FileName, Stat.st_size);
+ }
+ else
+ {
+ ZEN_WARN("encountered non-regular file during file system traversal ({}): {} found in {}",
+ Stat.st_mode, FileName, RootDir.c_str());
+ }
+ }
+
+ closedir(Dir);
+#endif // ZEN_PLATFORM_WINDOWS
}
+
+
std::filesystem::path
PathFromHandle(void* NativeHandle)
{