diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 4cc73c179c..612e97a325 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -102,6 +102,7 @@ static fs::error to_error(DWORD e) #include #include #include +#include #include #include #include @@ -403,6 +404,45 @@ bool fs::is_dir(const std::string& path) return true; } +bool fs::statfs(const std::string& path, fs::device_stat& info) +{ + if (auto device = get_virtual_device(path)) + { + return device->statfs(path, info); + } + +#ifdef _WIN32 + ULARGE_INTEGER avail_free; + ULARGE_INTEGER total_size; + ULARGE_INTEGER total_free; + + if (!GetDiskFreeSpaceExW(to_wchar(path).get(), &avail_free, &total_size, &total_free)) + { + g_tls_error = to_error(GetLastError()); + return false; + } + + info.block_size = 4096; // TODO + info.total_size = total_size.QuadPart; + info.total_free = total_free.QuadPart; + info.avail_free = avail_free.QuadPart; +#else + struct ::statvfs buf; + if (!::statvfs(path.c_str(), &buf) != 0) + { + g_tls_error = to_error(errno); + return false; + } + + info.block_size = buf.f_frsize; + info.total_size = info.block_size * buf.f_blocks; + info.total_free = info.block_size * buf.f_bfree; + info.avail_free = info.block_size * buf.f_bavail; +#endif + + return true; +} + bool fs::create_dir(const std::string& path) { if (auto device = get_virtual_device(path)) diff --git a/Utilities/File.h b/Utilities/File.h index f9bd852091..8c99fc11ce 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -84,12 +84,22 @@ namespace fs virtual void rewind() = 0; }; + // Device information + struct device_stat + { + u64 block_size; + u64 total_size; + u64 total_free; // Total size of free space + u64 avail_free; // Free space available to unprivileged user + }; + // Virtual device struct device_base { virtual ~device_base(); virtual bool stat(const std::string& path, stat_t& info) = 0; + virtual bool statfs(const std::string& path, device_stat& info) = 0; virtual bool remove_dir(const std::string& path) = 0; virtual bool create_dir(const std::string& path) = 0; virtual bool rename(const std::string& from, const std::string& to) = 0; @@ -122,6 +132,9 @@ namespace fs // Check whether the directory exists and is NOT a file bool is_dir(const std::string& path); + // Get filesystem information + bool statfs(const std::string& path, device_stat& info); + // Delete empty directory bool remove_dir(const std::string& path); diff --git a/rpcs3/Emu/Cell/Modules/cellFs.cpp b/rpcs3/Emu/Cell/Modules/cellFs.cpp index e6fd7c8340..14766ce5fe 100644 --- a/rpcs3/Emu/Cell/Modules/cellFs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFs.cpp @@ -260,7 +260,7 @@ s32 cellFsUtime(vm::cptr path, vm::cptr timep) s32 cellFsGetFreeSize(vm::cptr path, vm::ptr block_size, vm::ptr block_count) { - cellFs.warning("cellFsGetFreeSize(path=%s, block_size=*0x%x, block_count=*0x%x)", path, block_size, block_count); + cellFs.todo("cellFsGetFreeSize(path=%s, block_size=*0x%x, block_count=*0x%x)", path, block_size, block_count); // TODO: Get real values. Currently, it always returns 40 GB of free space divided in 4 KB blocks *block_size = 4096; // ?