From 77c684c1140f6bf3fb7d4560d06d2efb1a2ee5e2 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 6 Jul 2018 10:51:32 -0400 Subject: Virtual Filesystem (#597) * Add VfsFile and VfsDirectory classes * Finish abstract Vfs classes * Implement RealVfsFile (computer fs backend) * Finish RealVfsFile and RealVfsDirectory * Finished OffsetVfsFile * More changes * Fix import paths * Major refactor * Remove double const * Use experimental/filesystem or filesystem depending on compiler * Port partition_filesystem * More changes * More Overhaul * FSP_SRV fixes * Fixes and testing * Try to get filesystem to compile * Filesystem on linux * Remove std::filesystem and document/test * Compile fixes * Missing include * Bug fixes * Fixes * Rename v_file and v_dir * clang-format fix * Rename NGLOG_* to LOG_* * Most review changes * Fix TODO * Guess 'main' to be Directory by filename --- src/core/file_sys/vfs_real.cpp | 168 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/core/file_sys/vfs_real.cpp (limited to 'src/core/file_sys/vfs_real.cpp') diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp new file mode 100644 index 000000000..8b95e8c72 --- /dev/null +++ b/src/core/file_sys/vfs_real.cpp @@ -0,0 +1,168 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_paths.h" +#include "common/logging/log.h" +#include "core/file_sys/vfs_real.h" + +namespace FileSys { + +static std::string PermissionsToCharArray(Mode perms) { + std::string out; + switch (perms) { + case Mode::Read: + out += "r"; + break; + case Mode::Write: + out += "r+"; + break; + case Mode::Append: + out += "a"; + break; + } + return out + "b"; +} + +RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_) + : backing(path_, PermissionsToCharArray(perms_).c_str()), path(path_), + parent_path(FileUtil::GetParentPath(path_)), + path_components(FileUtil::SplitPathComponents(path_)), + parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), + perms(perms_) {} + +std::string RealVfsFile::GetName() const { + return path_components.back(); +} + +size_t RealVfsFile::GetSize() const { + return backing.GetSize(); +} + +bool RealVfsFile::Resize(size_t new_size) { + return backing.Resize(new_size); +} + +std::shared_ptr RealVfsFile::GetContainingDirectory() const { + return std::make_shared(parent_path, perms); +} + +bool RealVfsFile::IsWritable() const { + return perms == Mode::Append || perms == Mode::Write; +} + +bool RealVfsFile::IsReadable() const { + return perms == Mode::Read || perms == Mode::Write; +} + +size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const { + if (!backing.Seek(offset, SEEK_SET)) + return 0; + return backing.ReadBytes(data, length); +} + +size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) { + if (!backing.Seek(offset, SEEK_SET)) + return 0; + return backing.WriteBytes(data, length); +} + +bool RealVfsFile::Rename(const std::string& name) { + const auto out = FileUtil::Rename(GetName(), name); + path = parent_path + DIR_SEP + name; + path_components = parent_components; + path_components.push_back(name); + backing = FileUtil::IOFile(path, PermissionsToCharArray(perms).c_str()); + return out; +} + +RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_) + : path(FileUtil::RemoveTrailingSlash(path_)), parent_path(FileUtil::GetParentPath(path)), + path_components(FileUtil::SplitPathComponents(path)), + parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), + perms(perms_) { + if (!FileUtil::Exists(path) && (perms == Mode::Write || perms == Mode::Append)) + FileUtil::CreateDir(path); + unsigned size; + if (perms != Mode::Append) { + FileUtil::ForeachDirectoryEntry( + &size, path, + [this](unsigned* entries_out, const std::string& directory, + const std::string& filename) { + std::string full_path = directory + DIR_SEP + filename; + if (FileUtil::IsDirectory(full_path)) + subdirectories.emplace_back( + std::make_shared(full_path, perms)); + else + files.emplace_back(std::make_shared(full_path, perms)); + return true; + }); + } +} + +std::vector> RealVfsDirectory::GetFiles() const { + return std::vector>(files); +} + +std::vector> RealVfsDirectory::GetSubdirectories() const { + return std::vector>(subdirectories); +} + +bool RealVfsDirectory::IsWritable() const { + return perms == Mode::Write || perms == Mode::Append; +} + +bool RealVfsDirectory::IsReadable() const { + return perms == Mode::Read || perms == Mode::Write; +} + +std::string RealVfsDirectory::GetName() const { + return path_components.back(); +} + +std::shared_ptr RealVfsDirectory::GetParentDirectory() const { + if (path_components.size() <= 1) + return nullptr; + + return std::make_shared(parent_path, perms); +} + +std::shared_ptr RealVfsDirectory::CreateSubdirectory(const std::string& name) { + if (!FileUtil::CreateDir(path + DIR_SEP + name)) + return nullptr; + subdirectories.emplace_back(std::make_shared(path + DIR_SEP + name, perms)); + return subdirectories.back(); +} + +std::shared_ptr RealVfsDirectory::CreateFile(const std::string& name) { + if (!FileUtil::CreateEmptyFile(path + DIR_SEP + name)) + return nullptr; + files.emplace_back(std::make_shared(path + DIR_SEP + name, perms)); + return files.back(); +} + +bool RealVfsDirectory::DeleteSubdirectory(const std::string& name) { + return FileUtil::DeleteDirRecursively(path + DIR_SEP + name); +} + +bool RealVfsDirectory::DeleteFile(const std::string& name) { + return FileUtil::Delete(path + DIR_SEP + name); +} + +bool RealVfsDirectory::Rename(const std::string& name) { + return FileUtil::Rename(path, parent_path + DIR_SEP + name); +} + +bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { + auto iter = std::find(files.begin(), files.end(), file); + if (iter == files.end()) + return false; + + files[iter - files.begin()] = files.back(); + files.pop_back(); + + subdirectories.emplace_back(dir); + + return true; +} +} // namespace FileSys -- cgit v1.2.3