From 0d4f8ca23487adfd4aade4119a9f3a7e7883c562 Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 22 Feb 2020 17:04:35 +0200 Subject: [PATCH] fs: Make fs::get_dir_size able to report an error --- Utilities/File.cpp | 18 ++++++++++++-- rpcs3/Emu/Cell/Modules/cellGame.cpp | 38 +++++++++++++++++++++++------ rpcs3/Emu/System.cpp | 29 ++++++++++++++++------ 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 42e0448de5..5b60f68add 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -1639,7 +1639,14 @@ u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment) { u64 result = 0; - for (const auto& entry : dir(path)) + const auto root_dir = dir(path); + + if (!root_dir) + { + return static_cast(umax); + } + + for (const auto& entry : root_dir) { if (entry.name == "." || entry.name == "..") { @@ -1653,7 +1660,14 @@ u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment) if (entry.is_directory == true) { - result += get_dir_size(path_append(path, entry.name), rounding_alignment); + const u64 size = get_dir_size(path_append(path, entry.name), rounding_alignment); + + if (size == umax) + { + return size; + } + + result += size; } } diff --git a/rpcs3/Emu/Cell/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp index e159e2e18c..b7a7b70468 100644 --- a/rpcs3/Emu/Cell/Modules/cellGame.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp @@ -242,12 +242,21 @@ error_code cellHddGameGetSizeKB(vm::ptr size) const std::string local_dir = vfs::get(Emu.GetDir()); - if (!fs::is_dir(local_dir)) + const auto dirsz = fs::get_dir_size(local_dir, 1024); + + if (dirsz == umax) { + const auto error = fs::g_tls_error; + + if (fs::exists(local_dir)) + { + cellGame.error("cellHddGameGetSizeKB(): Unknown failure on calculating directory '%s' size (%s)", local_dir, error); + } + return CELL_HDDGAME_ERROR_FAILURE; } - *size = ::narrow(fs::get_dir_size(local_dir, 1024) / 1024); + *size = ::narrow(dirsz / 1024); return CELL_OK; } @@ -281,12 +290,21 @@ error_code cellGameDataGetSizeKB(vm::ptr size) const std::string local_dir = vfs::get(Emu.GetDir()); - if (!fs::is_dir(local_dir)) + const auto dirsz = fs::get_dir_size(local_dir, 1024); + + if (dirsz == umax) { + const auto error = fs::g_tls_error; + + if (fs::exists(local_dir)) + { + cellGame.error("cellGameDataGetSizeKB: Unknown failure on calculating directory '%s' size (%s)", local_dir, error); + } + return CELL_GAMEDATA_ERROR_FAILURE; } - *size = ::narrow(fs::get_dir_size(local_dir, 1024) / 1024); + *size = ::narrow(dirsz / 1024); return CELL_OK; } @@ -937,21 +955,25 @@ error_code cellGameGetSizeKB(vm::ptr size) const std::string local_dir = !prm->temp.empty() ? prm->temp : vfs::get("/dev_hdd0/game/" + prm->dir); - if (!fs::is_dir(local_dir)) + const auto dirsz = fs::get_dir_size(local_dir, 1024); + + if (dirsz == umax) { - if (fs::g_tls_error == fs::error::noent) + const auto error = fs::g_tls_error; + + if (!fs::exists(local_dir)) { *size = 0; return CELL_OK; } else { - cellGame.error("cellGameGetSizeKb(): unexpexcted error on path '%s' (%s)", local_dir, fs::g_tls_error); + cellGame.error("cellGameGetSizeKb(): Unknown failure on calculating directory size '%s' (%s)", local_dir, error); return CELL_GAME_ERROR_ACCESS_ERROR; } } - *size = ::narrow(fs::get_dir_size(local_dir, 1024) / 1024); + *size = ::narrow(dirsz / 1024); return CELL_OK; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 9b404c9623..a697f8e160 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -442,6 +442,7 @@ bool Emulator::BootRsxCapture(const std::string& path) void Emulator::LimitCacheSize() { const std::string cache_location = Emulator::GetHdd1Dir() + "/caches"; + if (!fs::is_dir(cache_location)) { sys_log.warning("Cache does not exist (%s)", cache_location); @@ -449,6 +450,13 @@ void Emulator::LimitCacheSize() } const u64 size = fs::get_dir_size(cache_location); + + if (size == umax) + { + sys_log.error("Could not calculate cache directory '%s' size (%s)", cache_location, fs::g_tls_error); + return; + } + const u64 max_size = static_cast(g_cfg.vfs.cache_max_size) * 1024 * 1024; if (max_size == 0) // Everything must go, so no need to do checks @@ -466,10 +474,10 @@ void Emulator::LimitCacheSize() sys_log.success("Cleaning disk cache..."); std::vector file_list{}; - fs::dir cache_dir{}; - if (!cache_dir.open(cache_location)) + fs::dir cache_dir(cache_location); + if (!cache_dir) { - sys_log.error("Could not open cache directory"); + sys_log.error("Could not open cache directory '%s' (%s)", cache_location, fs::g_tls_error); return; } @@ -479,6 +487,7 @@ void Emulator::LimitCacheSize() if (item.name != "." && item.name != "..") file_list.push_back(item); } + cache_dir.close(); // sort oldest first @@ -494,15 +503,19 @@ void Emulator::LimitCacheSize() for (const auto &item : file_list) { const std::string &name = cache_location + "/" + item.name; - const u64 item_size = fs::is_dir(name) ? fs::get_dir_size(name) : item.size; + const bool is_dir = fs::is_dir(name); + const u64 item_size = is_dir ? fs::get_dir_size(name) : item.size; - if (fs::is_dir(name)) + if (is_dir && item_size == umax) { - fs::remove_all(name, true); + sys_log.error("Failed to calculate '%s' item '%s' size (%s)", cache_location, item.name, fs::g_tls_error); + break; } - else + + if (is_dir ? !fs::remove_all(name, true) : !fs::remove_file(name)) { - fs::remove_file(name); + sys_log.error("Could not remove cache directory '%s' item '%s' (%s)", cache_location, item.name, fs::g_tls_error); + break; } removed += item_size;