Major refactor

This commit is contained in:
Zach Hilman
2018-06-23 16:11:38 -04:00
parent 994f0de11d
commit 008337c585
8 changed files with 307 additions and 309 deletions

View File

@@ -388,7 +388,7 @@ u64 GetSize(FILE* f) {
bool CreateEmptyFile(const std::string& filename) {
NGLOG_TRACE(Common_Filesystem, "{}", filename);
if (!FileUtil::IOFile(filename, "wb")) {
if (!FileUtil::IOFile(filename, "wb").IsOpen()) {
NGLOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg());
return false;
}
@@ -750,7 +750,7 @@ size_t WriteStringToFile(bool text_file, const std::string& str, const char* fil
size_t ReadFileToString(bool text_file, const char* filename, std::string& str) {
IOFile file(filename, text_file ? "r" : "rb");
if (!file)
if (!file.IsOpen())
return false;
str.resize(static_cast<u32>(file.GetSize()));
@@ -820,7 +820,6 @@ IOFile& IOFile::operator=(IOFile&& other) noexcept {
void IOFile::Swap(IOFile& other) noexcept {
std::swap(m_file, other.m_file);
std::swap(m_good, other.m_good);
}
bool IOFile::Open(const std::string& filename, const char openmode[]) {
@@ -832,16 +831,15 @@ bool IOFile::Open(const std::string& filename, const char openmode[]) {
m_file = fopen(filename.c_str(), openmode);
#endif
m_good = IsOpen();
return m_good;
return IsOpen();
}
bool IOFile::Close() {
if (!IsOpen() || 0 != std::fclose(m_file))
m_good = false;
return false;
m_file = nullptr;
return m_good;
return true;
}
u64 IOFile::GetSize() const {
@@ -851,11 +849,8 @@ u64 IOFile::GetSize() const {
return 0;
}
bool IOFile::Seek(s64 off, int origin) {
if (!IsOpen() || 0 != fseeko(m_file, off, origin))
m_good = false;
return m_good;
bool IOFile::Seek(s64 off, int origin) const {
return IsOpen() && 0 == fseeko(m_file, off, origin);
}
u64 IOFile::Tell() const {
@@ -866,26 +861,20 @@ u64 IOFile::Tell() const {
}
bool IOFile::Flush() {
if (!IsOpen() || 0 != std::fflush(m_file))
m_good = false;
return m_good;
return IsOpen() && 0 == std::fflush(m_file);
}
bool IOFile::Resize(u64 size) {
if (!IsOpen() || 0 !=
return IsOpen() && 0 ==
#ifdef _WIN32
// ector: _chsize sucks, not 64-bit safe
// F|RES: changed to _chsize_s. i think it is 64-bit safe
_chsize_s(_fileno(m_file), size)
// ector: _chsize sucks, not 64-bit safe
// F|RES: changed to _chsize_s. i think it is 64-bit safe
_chsize_s(_fileno(m_file), size)
#else
// TODO: handle 64bit and growing
ftruncate(fileno(m_file), size)
// TODO: handle 64bit and growing
ftruncate(fileno(m_file), size)
#endif
)
m_good = false;
return m_good;
;
}
} // namespace FileUtil

View File

@@ -169,41 +169,27 @@ public:
bool Close();
template <typename T>
size_t ReadArray(T* data, size_t length) {
size_t ReadArray(T* data, size_t length) const {
static_assert(std::is_trivially_copyable<T>(),
"Given array does not consist of trivially copyable objects");
if (!IsOpen()) {
m_good = false;
if (!IsOpen())
return -1;
}
size_t items_read = std::fread(data, sizeof(T), length, m_file);
if (items_read != length)
m_good = false;
return items_read;
return std::fread(data, sizeof(T), length, m_file);
}
template <typename T>
size_t WriteArray(const T* data, size_t length) {
static_assert(std::is_trivially_copyable<T>(),
"Given array does not consist of trivially copyable objects");
if (!IsOpen()) {
m_good = false;
if (!IsOpen())
return -1;
}
size_t items_written = std::fwrite(data, sizeof(T), length, m_file);
if (items_written != length)
m_good = false;
return items_written;
return std::fwrite(data, sizeof(T), length, m_file);
}
template <typename T>
size_t ReadBytes(T* data, size_t length) {
size_t ReadBytes(T* data, size_t length) const {
static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable");
return ReadArray(reinterpret_cast<char*>(data), length);
}
@@ -220,19 +206,11 @@ public:
return WriteArray(&object, 1);
}
bool IsOpen() const {
bool IsOpen() const const {
return nullptr != m_file;
}
// m_good is set to false when a read, write or other function fails
bool IsGood() const {
return m_good;
}
explicit operator bool() const {
return IsGood();
}
bool Seek(s64 off, int origin);
bool Seek(s64 off, int origin) const;
u64 Tell() const;
u64 GetSize() const;
bool Resize(u64 size);
@@ -240,13 +218,11 @@ public:
// clear error state
void Clear() {
m_good = true;
std::clearerr(m_file);
}
private:
std::FILE* m_file = nullptr;
bool m_good = true;
};
} // namespace FileUtil

View File

@@ -2,72 +2,110 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <numeric>
#include "core/file_sys/vfs.h"
namespace FileSys {
VfsFile::operator bool() {
return IsGood();
VfsFile::~VfsFile() = default;
VfsDirectory::~VfsDirectory() = default;
boost::optional<u8> VfsFile::ReadByte(size_t offset) const {
u8 out{};
size_t size = Read(&out, 1, offset);
if (size == 1)
return out;
return boost::none;
}
boost::optional<u8> VfsFile::ReadByte(u64 offset) {
auto vec = ReadBytes(offset, 1);
if (vec.empty())
return boost::none;
return vec[0];
std::vector<u8> VfsFile::ReadBytes(size_t size, size_t offset) const {
std::vector<u8> out(size);
size_t read_size = Read(out.data(), size, offset);
out.resize(read_size);
return out;
}
std::vector<u8> VfsFile::ReadAllBytes() {
return ReadBytes(0, GetSize());
std::vector<u8> VfsFile::ReadAllBytes() const {
return ReadBytes(GetSize());
}
u64 VfsFile::ReplaceBytes(const std::vector<u8>& data) {
if (!Resize(data.size()))
return 0;
return WriteBytes(data, 0);
bool VfsFile::WriteByte(u8 data, size_t offset) {
return 1 == Write(&data, 1, offset);
}
VfsDirectory::operator bool() {
return IsGood();
size_t VfsFile::WriteBytes(std::vector<u8> data, size_t offset) {
return Write(data.data(), data.size(), offset);
}
std::shared_ptr<VfsFile> VfsDirectory::GetFile(const std::string& name) {
auto files = GetFiles();
auto iter = std::find_if(files.begin(), files.end(),
[&name](auto file1) { return name == file1->GetName(); });
return iter == files.end() ? nullptr : std::move(*iter);
std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(const std::filesystem::path& path) const {
if (path.parent_path() == path.root_path())
return GetFile(path.filename().string());
auto parent = path.parent_path().string();
parent.replace(path.root_path().string().begin(), path.root_path().string().end(), "");
const auto index = parent.find_first_of('\\');
const auto first_dir = parent.substr(0, index), rest = parent.substr(index + 1);
const auto sub = GetSubdirectory(first_dir);
if (sub == nullptr)
return nullptr;
return sub->GetFileRelative(path.root_path().string() + rest);
}
std::shared_ptr<VfsDirectory> VfsDirectory::GetSubdirectory(const std::string& name) {
auto subs = GetSubdirectories();
auto iter = std::find_if(subs.begin(), subs.end(),
[&name](auto file1) { return name == file1->GetName(); });
std::shared_ptr<VfsFile> VfsDirectory::GetFileAbsolute(const std::filesystem::path& path) const {
if (IsRoot())
return GetFileRelative(path);
return GetParentDirectory()->GetFileAbsolute(path);
}
std::shared_ptr<VfsFile> VfsDirectory::GetFile(const std::string& name) const {
const auto& files = GetFiles();
const auto& iter = std::find_if(files.begin(), files.end(), [&name](const auto& file1) {
return name == file1->GetName();
});
return iter == files.end() ? nullptr : *iter;
}
std::shared_ptr<VfsDirectory> VfsDirectory::GetSubdirectory(const std::string& name) const {
const auto& subs = GetSubdirectories();
const auto& iter = std::find_if(
subs.begin(), subs.end(), [&name](const auto& file1) { return name == file1->GetName(); });
return iter == subs.end() ? nullptr : std::move(*iter);
}
u64 VfsDirectory::GetSize() {
auto files = GetFiles();
auto file_total = std::accumulate(files.begin(), files.end(), 0ull,
[](auto f1, auto f2) { return f1 + f2->GetSize(); });
bool VfsDirectory::IsRoot() const {
return GetParentDirectory() == nullptr;
}
auto sub_dir = GetSubdirectories();
auto subdir_total = std::accumulate(sub_dir.begin(), sub_dir.end(), 0ull,
[](auto f1, auto f2) { return f1 + f2->GetSize(); });
size_t VfsDirectory::GetSize() const {
const auto& files = GetFiles();
const auto file_total =
std::accumulate(files.begin(), files.end(), 0ull,
[](const auto& f1, const auto& f2) { return f1 + f2->GetSize(); });
const auto& sub_dir = GetSubdirectories();
const auto subdir_total =
std::accumulate(sub_dir.begin(), sub_dir.end(), 0ull,
[](const auto& f1, const auto& f2) { return f1 + f2->GetSize(); });
return file_total + subdir_total;
}
bool VfsDirectory::Copy(const std::string& src, const std::string& dest) {
auto f1 = CreateFile(src), f2 = CreateFile(dest);
const auto f1 = CreateFile(src);
auto f2 = CreateFile(dest);
if (f1 == nullptr || f2 == nullptr)
return false;
return f2->ReplaceBytes(f1->ReadAllBytes()) == f1->GetSize();
if (!f2->Resize(f1->GetSize())) {
DeleteFile(dest);
return false;
}
return f2->WriteBytes(f1->ReadAllBytes()) == f1->GetSize();
}
VfsFile::~VfsFile() {}
VfsDirectory::~VfsDirectory() {}
} // namespace FileSys

View File

@@ -4,7 +4,9 @@
#pragma once
#include <filesystem>
#include <string>
#include <type_traits>
#include <vector>
#include "boost/optional.hpp"
#include "common/common_types.h"
@@ -13,82 +15,93 @@ namespace FileSys {
struct VfsDirectory;
struct VfsFile : NonCopyable {
virtual bool IsReady() = 0;
virtual bool IsGood() = 0;
virtual operator bool();
virtual void ResetState() = 0;
virtual ~VfsFile();
virtual std::string GetName() = 0;
virtual u64 GetSize() = 0;
virtual bool Resize(u64 new_size) = 0;
virtual std::shared_ptr<VfsDirectory> GetContainingDirectory() = 0;
virtual std::string GetName() const = 0;
virtual size_t GetSize() const = 0;
virtual bool Resize(size_t new_size) = 0;
virtual std::shared_ptr<VfsDirectory> GetContainingDirectory() const = 0;
virtual bool IsWritable() = 0;
virtual bool IsReadable() = 0;
virtual bool IsWritable() const = 0;
virtual bool IsReadable() const = 0;
virtual boost::optional<u8> ReadByte(u64 offset);
virtual std::vector<u8> ReadBytes(u64 offset, u64 length) = 0;
virtual size_t Read(u8* data, size_t length, size_t offset = 0) const = 0;
virtual size_t Write(const u8* data, size_t length, size_t offset = 0) = 0;
virtual boost::optional<u8> ReadByte(size_t offset = 0) const;
virtual std::vector<u8> ReadBytes(size_t size, size_t offset = 0) const;
virtual std::vector<u8> ReadAllBytes() const;
template <typename T>
u64 ReadBytes(T* data, u64 offset, u64 length) {
static_assert(std::is_trivially_copyable<T>(),
"Given array does not consist of trivially copyable objects");
return ReadArray<u8>(reinterpret_cast<u8*>(data), offset, length);
size_t ReadArray(T* data, size_t number_elements, size_t offset = 0) const {
static_assert(std::is_trivially_copyable<T>::value,
"Data type must be trivially copyable.");
return Read(data, number_elements * sizeof(T), offset);
}
template <typename T>
std::vector<T> ReadArray(u64 offset, u64 number_elements) {
static_assert(std::is_trivially_copyable<T>(),
"Given array does not consist of trivially copyable objects");
auto vec = ReadBytes(offset, number_elements * sizeof(T));
std::vector<T> out_vec(number_elements);
memcpy(out_vec.data(), vec.data(), vec.size());
return out_vec;
size_t ReadBytes(T* data, size_t size, size_t offset = 0) const {
static_assert(std::is_trivially_copyable<T>::value,
"Data type must be trivially copyable.");
return Read(reinterpret_cast<u8*>(data), size, offset);
}
template <typename T>
u64 ReadArray(T* data, u64 offset, u64 number_elements) {
static_assert(std::is_trivially_copyable<T>(),
"Given array does not consist of trivially copyable objects");
std::vector<T> vec = ReadArray<T>(offset, number_elements);
for (size_t i = 0; i < vec.size(); ++i)
data[i] = vec[i];
return vec.size();
size_t ReadObject(T& data, size_t offset = 0) const {
static_assert(std::is_trivially_copyable<T>::value,
"Data type must be trivially copyable.");
return Read(&data, sizeof(T), offset);
}
virtual std::vector<u8> ReadAllBytes();
virtual bool WriteByte(u8 data, size_t offset = 0);
virtual size_t WriteBytes(std::vector<u8> data, size_t offset = 0);
virtual u64 WriteBytes(const std::vector<u8>& data, u64 offset) = 0;
virtual u64 ReplaceBytes(const std::vector<u8>& data);
template <typename T>
size_t WriteArray(T* data, size_t number_elements, size_t offset = 0) {
static_assert(std::is_trivially_copyable<T>::value,
"Data type must be trivially copyable.");
return Write(data, number_elements * sizeof(T), offset);
}
template <typename T>
size_t WriteBytes(T* data, size_t size, size_t offset = 0) {
static_assert(std::is_trivially_copyable<T>::value,
"Data type must be trivially copyable.");
return Write(reinterpret_cast<u8*>(data), size, offset);
}
template <typename T>
size_t WriteObject(T& data, size_t offset = 0) {
static_assert(std::is_trivially_copyable<T>::value,
"Data type must be trivially copyable.");
return Write(&data, sizeof(T), offset);
}
virtual bool Rename(const std::string& name) = 0;
~VfsFile();
};
struct VfsDirectory : NonCopyable {
virtual bool IsReady() = 0;
virtual bool IsGood() = 0;
virtual operator bool();
virtual void ResetState() = 0;
virtual ~VfsDirectory();
virtual std::vector<std::shared_ptr<VfsFile>> GetFiles() = 0;
virtual std::shared_ptr<VfsFile> GetFile(const std::string& name);
virtual std::shared_ptr<VfsFile> GetFileRelative(const std::filesystem::path& path) const;
virtual std::shared_ptr<VfsFile> GetFileAbsolute(const std::filesystem::path& path) const;
virtual std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() = 0;
virtual std::shared_ptr<VfsDirectory> GetSubdirectory(const std::string& name);
virtual std::vector<std::shared_ptr<VfsFile>> GetFiles() const = 0;
virtual std::shared_ptr<VfsFile> GetFile(const std::string& name) const;
virtual bool IsWritable() = 0;
virtual bool IsReadable() = 0;
virtual std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const = 0;
virtual std::shared_ptr<VfsDirectory> GetSubdirectory(const std::string& name) const;
virtual bool IsRoot() = 0;
virtual bool IsWritable() const = 0;
virtual bool IsReadable() const = 0;
virtual std::string GetName() = 0;
virtual u64 GetSize();
virtual std::shared_ptr<VfsDirectory> GetParentDirectory() = 0;
virtual bool IsRoot() const;
virtual std::string GetName() const = 0;
virtual size_t GetSize() const;
virtual std::shared_ptr<VfsDirectory> GetParentDirectory() const = 0;
virtual std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) = 0;
virtual std::shared_ptr<VfsFile> CreateFile(const std::string& name) = 0;
@@ -99,7 +112,5 @@ struct VfsDirectory : NonCopyable {
virtual bool Rename(const std::string& name) = 0;
virtual bool Copy(const std::string& src, const std::string& dest);
~VfsDirectory();
};
} // namespace FileSys

View File

@@ -6,26 +6,14 @@
namespace FileSys {
OffsetVfsFile::OffsetVfsFile(std::unique_ptr<VfsFile>&& file, u64 offset, u64 size)
: file(std::move(file)), offset(offset), size(size) {}
OffsetVfsFile::OffsetVfsFile(std::unique_ptr<VfsFile>&& file_, u64 offset_, u64 size_)
: file(std::move(file_)), offset(offset_), size(size_) {}
bool OffsetVfsFile::IsReady() {
return file->IsReady();
}
bool OffsetVfsFile::IsGood() {
return file->IsGood();
}
void OffsetVfsFile::ResetState() {
file->ResetState();
}
std::string OffsetVfsFile::GetName() {
std::string OffsetVfsFile::GetName() const {
return file->GetName();
}
u64 OffsetVfsFile::GetSize() {
u64 OffsetVfsFile::GetSize() const {
return size;
}
@@ -38,32 +26,58 @@ bool OffsetVfsFile::Resize(u64 new_size) {
return false;
}
std::shared_ptr<VfsDirectory> OffsetVfsFile::GetContainingDirectory() {
std::shared_ptr<VfsDirectory> OffsetVfsFile::GetContainingDirectory() const {
return file->GetContainingDirectory();
}
bool OffsetVfsFile::IsWritable() {
bool OffsetVfsFile::IsWritable() const {
return file->IsWritable();
}
bool OffsetVfsFile::IsReadable() {
bool OffsetVfsFile::IsReadable() const {
return file->IsReadable();
}
std::vector<u8> OffsetVfsFile::ReadBytes(u64 r_offset, u64 r_length) {
return file->ReadBytes(offset + r_offset, std::min(r_offset + r_length, size));
size_t OffsetVfsFile::Read(u8* data, size_t length, size_t r_offset) const {
return file->Read(data, TrimToFit(length, r_offset), offset + r_offset);
}
u64 OffsetVfsFile::WriteBytes(const std::vector<u8>& data, u64 r_offset) {
auto end = data.end();
if (data.size() + r_offset > size)
end = data.begin() + size - r_offset;
size_t OffsetVfsFile::Write(const u8* data, size_t length, size_t r_offset) {
return file->Write(data, TrimToFit(length, r_offset), offset + r_offset);
}
return file->WriteBytes(std::vector<u8>(data.begin(), end), r_offset + offset);
boost::optional<u8> OffsetVfsFile::ReadByte(size_t r_offset) const {
if (r_offset < size)
return file->ReadByte(offset + r_offset);
return boost::none;
}
std::vector<u8> OffsetVfsFile::ReadBytes(size_t r_size, size_t r_offset) const {
return file->ReadBytes(TrimToFit(r_size, r_offset), offset + r_offset);
}
std::vector<u8> OffsetVfsFile::ReadAllBytes() const {
return file->ReadBytes(size, offset);
}
bool OffsetVfsFile::WriteByte(u8 data, size_t r_offset) {
if (r_offset < size)
return file->WriteByte(data, offset + r_offset);
return false;
}
size_t OffsetVfsFile::WriteBytes(std::vector<u8> data, size_t r_offset) {
return file->Write(data.data(), TrimToFit(data.size(), r_offset), offset + r_offset);
}
bool OffsetVfsFile::Rename(const std::string& name) {
return file->Rename(name);
}
size_t OffsetVfsFile::TrimToFit(size_t r_size, size_t r_offset) const {
return std::max(std::min(size - r_offset, r_size), 0ull);
}
} // namespace FileSys

View File

@@ -3,30 +3,36 @@
// Refer to the license.txt file included.
#pragma once
#include "core/file_sys/vfs.h"
namespace FileSys {
struct OffsetVfsFile : public VfsFile {
OffsetVfsFile(std::unique_ptr<VfsFile>&& file, u64 offset, u64 size);
OffsetVfsFile(std::unique_ptr<VfsFile>&& file, size_t offset, size_t size);
std::string GetName() const override;
size_t GetSize() const override;
bool Resize(size_t new_size) override;
std::shared_ptr<VfsDirectory> GetContainingDirectory() const override;
bool IsWritable() const override;
bool IsReadable() const override;
size_t Read(u8* data, size_t length, size_t offset) const override;
size_t Write(const u8* data, size_t length, size_t offset) override;
boost::optional<u8> ReadByte(size_t offset) const override;
std::vector<u8> ReadBytes(size_t size, size_t offset) const override;
std::vector<u8> ReadAllBytes() const override;
bool WriteByte(u8 data, size_t offset) override;
size_t WriteBytes(std::vector<u8> data, size_t offset) override;
bool IsReady() override;
bool IsGood() override;
void ResetState() override;
std::string GetName() override;
u64 GetSize() override;
bool Resize(u64 new_size) override;
std::shared_ptr<VfsDirectory> GetContainingDirectory() override;
bool IsWritable() override;
bool IsReadable() override;
std::vector<u8> ReadBytes(u64 offset, u64 length) override;
u64 WriteBytes(const std::vector<u8>& data, u64 offset) override;
bool Rename(const std::string& name) override;
private:
size_t TrimToFit(size_t r_size, size_t r_offset) const;
std::unique_ptr<VfsFile> file;
u64 offset;
u64 size;
size_t offset;
size_t size;
};
} // namespace FileSys

View File

@@ -2,160 +2,128 @@
// 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 {
RealVfsFile::RealVfsFile(const std::string& path, const char openmode[])
: backing(path, openmode), path(path), mode(openmode) {}
bool RealVfsFile::IsReady() {
return backing.IsOpen();
static const char* PermissionsToCharArray(std::filesystem::perms perms) {
std::string out;
if ((perms & std::filesystem::perms::owner_read) != std::filesystem::perms::none)
out += "r";
if ((perms & std::filesystem::perms::owner_write) != std::filesystem::perms::none)
out += "w";
return out.c_str();
}
bool RealVfsFile::IsGood() {
return backing.IsGood();
RealVfsFile::RealVfsFile(const std::filesystem::path& path_, std::filesystem::perms perms_)
: backing(path_.string(), PermissionsToCharArray(perms_)), path(path_), perms(perms_) {}
std::string RealVfsFile::GetName() const {
return path.filename().string();
}
void RealVfsFile::ResetState() {
backing.Clear();
}
std::string RealVfsFile::GetName() {
std::string part_path, name, extention;
Common::SplitPath(path, &part_path, &name, &extention);
return name + "." + extention;
}
u64 RealVfsFile::GetSize() {
size_t RealVfsFile::GetSize() const {
return backing.GetSize();
}
bool RealVfsFile::Resize(u64 new_size) {
bool RealVfsFile::Resize(size_t new_size) {
return backing.Resize(new_size);
}
std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() {
std::string part_path, name, extention;
Common::SplitPath(path, &part_path, &name, &extention);
return std::make_shared<RealVfsDirectory>(part_path, mode.c_str());
std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const {
return std::make_shared<RealVfsDirectory>(path.parent_path(), perms);
}
bool RealVfsFile::IsWritable() {
return mode.find('w') != std::string::npos;
bool RealVfsFile::IsWritable() const {
return (perms & std::filesystem::perms::owner_write) != std::filesystem::perms::none;
}
bool RealVfsFile::IsReadable() {
return mode.find('r') != std::string::npos;
bool RealVfsFile::IsReadable() const {
return (perms & std::filesystem::perms::owner_read) != std::filesystem::perms::none;
}
std::vector<u8> RealVfsFile::ReadBytes(u64 offset, u64 length) {
backing.Seek(offset, SEEK_SET);
std::vector<u8> out(length);
backing.ReadBytes(out.data(), length);
return out;
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);
}
u64 RealVfsFile::WriteBytes(const std::vector<u8>& data, u64 offset) {
backing.Seek(offset, SEEK_SET);
return backing.WriteBytes(data.data(), data.size());
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) {
auto out = FileUtil::Rename(GetName(), name);
std::string part_path, o_name, extention;
Common::SplitPath(path, &part_path, &o_name, &extention);
backing = FileUtil::IOFile(part_path + name, mode.c_str());
const auto out = FileUtil::Rename(GetName(), name);
path = path.parent_path() / name;
backing = FileUtil::IOFile(path.string(), PermissionsToCharArray(perms));
return out;
}
RealVfsDirectory::RealVfsDirectory(const std::string& path, const char openmode[])
: path(path[path.size() - 1] == DIR_SEP_CHR ? path.substr(0, path.size() - 1) : path) {
FileUtil::FSTEntry entry;
if (0 != FileUtil::ScanDirectoryTree(path, entry))
NGLOG_CRITICAL(Service_FS, "Failure to initialize file.");
for (FileUtil::FSTEntry child : entry.children) {
if (child.isDirectory)
subdirectories.emplace_back(
std::make_shared<RealVfsDirectory>(child.physicalName, mode.c_str()));
else
files.emplace_back(std::make_shared<RealVfsFile>(child.physicalName, mode.c_str()));
RealVfsDirectory::RealVfsDirectory(const std::filesystem::path& path_,
std::filesystem::perms perms_)
: path(path_), perms(perms_) {
for (const auto& entry : std::filesystem::directory_iterator(path)) {
if (std::filesystem::is_directory(entry.path()))
subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(entry.path(), perms));
else if (std::filesystem::is_regular_file(entry.path()))
files.emplace_back(std::make_shared<RealVfsFile>(entry.path(), perms));
}
}
bool RealVfsDirectory::IsReady() {
return FileUtil::IsDirectory(path);
}
bool RealVfsDirectory::IsGood() {
return FileUtil::IsDirectory(path);
}
void RealVfsDirectory::ResetState() {}
std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() {
std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const {
return std::vector<std::shared_ptr<VfsFile>>(files);
}
std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() {
std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() const {
return std::vector<std::shared_ptr<VfsDirectory>>(subdirectories);
}
bool RealVfsDirectory::IsWritable() {
return mode.find('w') != std::string::npos;
bool RealVfsDirectory::IsWritable() const {
return (perms & std::filesystem::perms::owner_write) != std::filesystem::perms::none;
}
bool RealVfsDirectory::IsReadable() {
return mode.find('r') != std::string::npos;
bool RealVfsDirectory::IsReadable() const {
return (perms & std::filesystem::perms::owner_read) != std::filesystem::perms::none;
}
bool RealVfsDirectory::IsRoot() {
return path.empty() || (path.size() == 2 && path[1] == ':');
std::string RealVfsDirectory::GetName() const {
return path.filename().string();
}
std::string RealVfsDirectory::GetName() {
size_t last = path.rfind(DIR_SEP_CHR);
return path.substr(last + 1);
}
std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() {
size_t last = path.rfind(DIR_SEP_CHR);
if (last == path.size() - 1)
last = path.rfind(DIR_SEP_CHR, path.size() - 2);
if (last == std::string::npos)
std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const {
if (path.parent_path() == path.root_path())
return nullptr;
return std::make_shared<RealVfsDirectory>(path.substr(0, last), mode.c_str());
return std::make_shared<RealVfsDirectory>(path.parent_path(), perms);
}
std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(const std::string& name) {
FileUtil::CreateDir(path + DIR_SEP + name);
subdirectories.emplace_back(
std::make_shared<RealVfsDirectory>(path + DIR_SEP + name, mode.c_str()));
return subdirectories[subdirectories.size() - 1];
if (!FileUtil::CreateDir((path / name).string()))
return nullptr;
subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(path / name, perms));
return subdirectories.back();
}
std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(const std::string& name) {
FileUtil::CreateEmptyFile(path + DIR_SEP + name);
files.emplace_back(std::make_shared<RealVfsFile>(path + DIR_SEP + name, mode.c_str()));
return files[files.size() - 1];
if (!FileUtil::CreateEmptyFile((path / name).string()))
return nullptr;
files.emplace_back(std::make_shared<RealVfsFile>(path / name, perms));
return files.back();
}
bool RealVfsDirectory::DeleteSubdirectory(const std::string& name) {
return FileUtil::DeleteDirRecursively(path + DIR_SEP + name);
return FileUtil::DeleteDirRecursively((path / name).string());
}
bool RealVfsDirectory::DeleteFile(const std::string& name) {
return FileUtil::Delete(path + DIR_SEP + name);
return FileUtil::Delete((path / name).string());
}
bool RealVfsDirectory::Rename(const std::string& name) {
std::string part, o_name, extention;
Common::SplitPath(name, &part, &o_name, &extention);
return FileUtil::Rename(path, part + DIR_SEP + name);
return FileUtil::Rename(path.string(), (path / name).string());
}
} // namespace FileSys

View File

@@ -3,46 +3,42 @@
// Refer to the license.txt file included.
#pragma once
#include <filesystem>
#include "common/file_util.h"
#include "core/file_sys/vfs.h"
namespace FileSys {
struct RealVfsFile : public VfsFile {
RealVfsFile(const std::string& name, const char openmode[]);
RealVfsFile(const std::filesystem::path& name, std::filesystem::perms perms);
bool IsReady() override;
bool IsGood() override;
void ResetState() override;
std::string GetName() override;
u64 GetSize() override;
bool Resize(u64 new_size) override;
std::shared_ptr<VfsDirectory> GetContainingDirectory() override;
bool IsWritable() override;
bool IsReadable() override;
std::vector<u8> ReadBytes(u64 offset, u64 length) override;
u64 WriteBytes(const std::vector<u8>& data, u64 offset) override;
std::string GetName() const override;
size_t GetSize() const override;
bool Resize(size_t new_size) override;
std::shared_ptr<VfsDirectory> GetContainingDirectory() const override;
bool IsWritable() const override;
bool IsReadable() const override;
size_t Read(u8* data, size_t length, size_t offset) const override;
size_t Write(const u8* data, size_t length, size_t offset) override;
bool Rename(const std::string& name) override;
private:
FileUtil::IOFile backing;
std::string path;
std::string mode;
std::filesystem::path path;
std::filesystem::perms perms;
};
struct RealVfsDirectory : public VfsDirectory {
RealVfsDirectory(const std::string& path, const char openmode[]);
RealVfsDirectory(const std::filesystem::path& path, std::filesystem::perms perms);
bool IsReady() override;
bool IsGood() override;
void ResetState() override;
std::vector<std::shared_ptr<VfsFile>> GetFiles() override;
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() override;
bool IsWritable() override;
bool IsReadable() override;
bool IsRoot() override;
std::string GetName() override;
std::shared_ptr<VfsDirectory> GetParentDirectory() override;
std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
bool IsWritable() const override;
bool IsReadable() const override;
bool IsRoot() const override;
std::string GetName() const override;
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) override;
std::shared_ptr<VfsFile> CreateFile(const std::string& name) override;
bool DeleteSubdirectory(const std::string& name) override;
@@ -50,8 +46,8 @@ struct RealVfsDirectory : public VfsDirectory {
bool Rename(const std::string& name) override;
private:
std::string path;
std::string mode;
std::filesystem::path path;
std::filesystem::perms perms;
std::vector<std::shared_ptr<VfsFile>> files;
std::vector<std::shared_ptr<VfsDirectory>> subdirectories;
};