From 8d63ebcb645476d8a1efca7957d8308e32b0353c Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 13 Sep 2021 23:02:53 -0400 Subject: [PATCH] vfs: Partially implement GetFileTimeStampRaw Gets rid of homebrew warnings using this func --- src/core/file_sys/vfs.cpp | 4 +++ src/core/file_sys/vfs.h | 3 ++ src/core/file_sys/vfs_real.cpp | 29 +++++++++++++++++++ src/core/file_sys/vfs_real.h | 1 + src/core/file_sys/vfs_types.h | 9 ++++++ .../hle/service/filesystem/filesystem.cpp | 12 ++++++++ src/core/hle/service/filesystem/filesystem.h | 6 ++++ src/core/hle/service/filesystem/fsp_srv.cpp | 20 ++++++++++++- 8 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index 368419ecaf..f5ad10b15f 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp @@ -273,6 +273,10 @@ VirtualFile VfsDirectory::GetFile(std::string_view name) const { return iter == files.end() ? nullptr : *iter; } +FileTimeStampRaw VfsDirectory::GetFileTimeStamp([[maybe_unused]] std::string_view path) const { + return {}; +} + VirtualDir VfsDirectory::GetSubdirectory(std::string_view name) const { const auto& subs = GetSubdirectories(); const auto iter = std::find_if(subs.begin(), subs.end(), diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index afd64e95c5..ff6935da67 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h @@ -199,6 +199,9 @@ public: // file with name. virtual VirtualFile GetFile(std::string_view name) const; + // Returns a struct containing the file's timestamp. + virtual FileTimeStampRaw GetFileTimeStamp(std::string_view path) const; + // Returns a vector containing all of the subdirectories in this directory. virtual std::vector GetSubdirectories() const = 0; // Returns the directory with name matching name. Returns nullptr if directory dosen't have a diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 3dad54f493..f4073b76ab 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -13,6 +13,13 @@ #include "common/logging/log.h" #include "core/file_sys/vfs_real.h" +// For FileTimeStampRaw +#include + +#ifdef _MSC_VER +#define stat _stat64 +#endif + namespace FileSys { namespace FS = Common::FS; @@ -392,6 +399,28 @@ std::vector RealVfsDirectory::GetFiles() const { return IterateEntries(); } +FileTimeStampRaw RealVfsDirectory::GetFileTimeStamp(std::string_view path_) const { + const auto full_path = FS::SanitizePath(path + '/' + std::string(path_)); + const auto fs_path = std::filesystem::path{FS::ToU8String(full_path)}; + struct stat file_status; + +#ifdef _WIN32 + const auto stat_result = _wstat64(fs_path.c_str(), &file_status); +#else + const auto stat_result = stat(fs_path.c_str(), &file_status); +#endif + + if (stat_result != 0) { + return {}; + } + + return { + .created{static_cast(file_status.st_ctime)}, + .accessed{static_cast(file_status.st_atime)}, + .modified{static_cast(file_status.st_mtime)}, + }; +} + std::vector RealVfsDirectory::GetSubdirectories() const { return IterateEntries(); } diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index e4d1bba79a..746e624cbf 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h @@ -86,6 +86,7 @@ public: VirtualDir CreateDirectoryRelative(std::string_view relative_path) override; bool DeleteSubdirectoryRecursive(std::string_view name) override; std::vector GetFiles() const override; + FileTimeStampRaw GetFileTimeStamp(std::string_view path) const override; std::vector GetSubdirectories() const override; bool IsWritable() const override; bool IsReadable() const override; diff --git a/src/core/file_sys/vfs_types.h b/src/core/file_sys/vfs_types.h index 6215ed7af2..ed07247178 100644 --- a/src/core/file_sys/vfs_types.h +++ b/src/core/file_sys/vfs_types.h @@ -6,6 +6,8 @@ #include +#include "common/common_types.h" + namespace FileSys { class VfsDirectory; @@ -18,4 +20,11 @@ using VirtualDir = std::shared_ptr; using VirtualFile = std::shared_ptr; using VirtualFilesystem = std::shared_ptr; +struct FileTimeStampRaw { + u64 created{}; + u64 accessed{}; + u64 modified{}; + u64 padding{}; +}; + } // namespace FileSys diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index c8d65f3282..f8f9e32f7d 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -261,6 +261,18 @@ ResultVal VfsDirectoryServiceWrapper::GetEntryType( return FileSys::ERROR_PATH_NOT_FOUND; } +ResultVal VfsDirectoryServiceWrapper::GetFileTimeStampRaw( + const std::string& path) const { + auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); + if (dir == nullptr) { + return FileSys::ERROR_PATH_NOT_FOUND; + } + if (GetEntryType(path).Failed()) { + return FileSys::ERROR_PATH_NOT_FOUND; + } + return MakeResult(dir->GetFileTimeStamp(Common::FS::GetFilename(path))); +} + FileSystemController::FileSystemController(Core::System& system_) : system{system_} {} FileSystemController::~FileSystemController() = default; diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index d387af3cbe..b155e08113 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -240,6 +240,12 @@ public: */ ResultVal GetEntryType(const std::string& path) const; + /** + * Get the timestamp of the specified path + * @return The timestamp of the specified path or error code + */ + ResultVal GetFileTimeStampRaw(const std::string& path) const; + private: FileSys::VirtualDir backing; }; diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index db4d44c128..50c788dd60 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -326,7 +326,7 @@ public: {11, &IFileSystem::GetFreeSpaceSize, "GetFreeSpaceSize"}, {12, &IFileSystem::GetTotalSpaceSize, "GetTotalSpaceSize"}, {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, - {14, nullptr, "GetFileTimeStampRaw"}, + {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"}, {15, nullptr, "QueryEntry"}, }; RegisterHandlers(functions); @@ -501,6 +501,24 @@ public: rb.Push(size.get_total_size()); } + void GetFileTimeStampRaw(Kernel::HLERequestContext& ctx) { + const auto file_buffer = ctx.ReadBuffer(); + const std::string name = Common::StringFromBuffer(file_buffer); + + LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); + + auto result = backend.GetFileTimeStampRaw(name); + if (result.Failed()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result.Code()); + return; + } + + IPC::ResponseBuilder rb{ctx, 10}; + rb.Push(ResultSuccess); + rb.PushRaw(*result); + } + private: VfsDirectoryServiceWrapper backend; SizeGetter size;