mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 14:00:16 +02:00
FEXCore/FileUtils: Adds a way to walk a directory with callback
We need to walk a directory calling back to the DiskCache, but without recursion. Also fixes a function signature issue on win32.
This commit is contained in:
2 files changed
+83
-1
No files matched your search
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/functional.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
@@ -115,10 +116,87 @@ end:
|
||||
FEX_DEFAULT_VISIBILITY bool RecursiveRemoveDirectory(const fextl::string& Directory) {
|
||||
return RecursiveRemoveDirectory(AT_FDCWD, Directory.c_str()) && unlinkat(AT_FDCWD, Directory.c_str(), true);
|
||||
}
|
||||
|
||||
FEX_DEFAULT_VISIBILITY void WalkDirectory(std::string_view Directory, fextl::move_only_function<void(std::string_view name, bool is_dir)> Callback) {
|
||||
constexpr int DIR_FLAGS = O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC;
|
||||
int dir_fd = ::openat(AT_FDCWD, fextl::string(Directory).c_str(), DIR_FLAGS);
|
||||
if (dir_fd == -1) {
|
||||
if (errno == ENOENT) {
|
||||
// Probably raced something. Non-error.
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Four pages arbitrary chosen to be a balance between NFS wanting to return data in page-size granules and
|
||||
// local filesystems returning arbitrary sizes.
|
||||
size_t dirent_size = 4096 * 4;
|
||||
uint8_t* dirent_buffer = reinterpret_cast<uint8_t*>(FEXCore::Allocator::malloc(dirent_size));
|
||||
|
||||
if (!dirent_buffer) {
|
||||
// Ran out of memory?
|
||||
goto end;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ssize_t read = getdents64(dir_fd, dirent_buffer, dirent_size);
|
||||
|
||||
if (read == -1) {
|
||||
if (errno == EINVAL) {
|
||||
// Buffer too small? Scale and try again.
|
||||
dirent_size *= 2;
|
||||
FEXCore::Allocator::free(dirent_buffer);
|
||||
dirent_buffer = reinterpret_cast<uint8_t*>(FEXCore::Allocator::malloc(dirent_size));
|
||||
if (!dirent_buffer) {
|
||||
// Ran out of memory?
|
||||
goto end;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Anything else just exit.
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (read == 0) {
|
||||
// Done.
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t dirent_offset = 0; dirent_offset < read;) {
|
||||
auto path_dirent = reinterpret_cast<const struct dirent*>(dirent_buffer + dirent_offset);
|
||||
std::string_view path_name_view = path_dirent->d_name;
|
||||
|
||||
if (path_name_view == "." || path_name_view == "..") {
|
||||
// Skip these two special files.
|
||||
dirent_offset += path_dirent->d_reclen;
|
||||
continue;
|
||||
}
|
||||
|
||||
Callback(path_name_view, path_dirent->d_type == DT_DIR);
|
||||
|
||||
// dirent is a VLA so we need to increment by reported size.
|
||||
dirent_offset += path_dirent->d_reclen;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (dirent_buffer) {
|
||||
FEXCore::Allocator::free(dirent_buffer);
|
||||
}
|
||||
|
||||
close(dir_fd);
|
||||
}
|
||||
|
||||
#else
|
||||
FEX_DEFAULT_VISIBILITY bool RecursiveRemoveDirectory(std::string_view Directory) {
|
||||
FEX_DEFAULT_VISIBILITY bool RecursiveRemoveDirectory(const fextl::string& Directory) {
|
||||
std::error_code ec;
|
||||
return std::filesystem::remove_all(Directory, ec) != ~0ULL;
|
||||
}
|
||||
|
||||
FEX_DEFAULT_VISIBILITY void WalkDirectory(std::string_view Directory, fextl::move_only_function<void(std::string_view name, bool is_dir)> Callback) {
|
||||
for (const auto& iter : std::filesystem::directory_iterator(Directory)) {
|
||||
Callback(iter.path().string(), iter.is_directory());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace FEXCore::FileUtils
|
||||
@@ -1,6 +1,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/functional.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
|
||||
namespace FEXCore::FileUtils {
|
||||
@@ -10,4 +12,6 @@ namespace FEXCore::FileUtils {
|
||||
* @return True if the directory didn't exist or was deleted.
|
||||
*/
|
||||
FEX_DEFAULT_VISIBILITY bool RecursiveRemoveDirectory(const fextl::string& Directory);
|
||||
|
||||
FEX_DEFAULT_VISIBILITY void WalkDirectory(std::string_view Directory, fextl::move_only_function<void(std::string_view name, bool is_dir)> Callback);
|
||||
} // namespace FEXCore::FileUtils
|
||||
Reference in new issue
Block a user