From 29aff8d5ab46c8d0199aa4bfa7eeff5d4fa2d7ef Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Wed, 18 Jul 2018 21:07:11 -0400 Subject: Virtual Filesystem 2: Electric Boogaloo (#676) * Virtual Filesystem * Fix delete bug and documentate * Review fixes + other stuff * Fix puyo regression --- src/core/file_sys/vfs_real.cpp | 177 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 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..22c858e0d --- /dev/null +++ b/src/core/file_sys/vfs_real.cpp @@ -0,0 +1,177 @@ +// 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; +} + +bool RealVfsFile::Close() { + return backing.Close(); +} + +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) + return; + + 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) { + auto file = GetFile(name); + if (file == nullptr) + return false; + files.erase(std::find(files.begin(), files.end(), file)); + auto real_file = std::static_pointer_cast(file); + real_file->Close(); + 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