77c684c114
* 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
168 lines
5.3 KiB
C++
168 lines
5.3 KiB
C++
// 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<VfsDirectory> RealVfsFile::GetContainingDirectory() const {
|
|
return std::make_shared<RealVfsDirectory>(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<RealVfsDirectory>(full_path, perms));
|
|
else
|
|
files.emplace_back(std::make_shared<RealVfsFile>(full_path, perms));
|
|
return true;
|
|
});
|
|
}
|
|
}
|
|
|
|
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() const {
|
|
return std::vector<std::shared_ptr<VfsDirectory>>(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<VfsDirectory> RealVfsDirectory::GetParentDirectory() const {
|
|
if (path_components.size() <= 1)
|
|
return nullptr;
|
|
|
|
return std::make_shared<RealVfsDirectory>(parent_path, perms);
|
|
}
|
|
|
|
std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(const std::string& name) {
|
|
if (!FileUtil::CreateDir(path + DIR_SEP + name))
|
|
return nullptr;
|
|
subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(path + DIR_SEP + name, perms));
|
|
return subdirectories.back();
|
|
}
|
|
|
|
std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(const std::string& name) {
|
|
if (!FileUtil::CreateEmptyFile(path + DIR_SEP + name))
|
|
return nullptr;
|
|
files.emplace_back(std::make_shared<RealVfsFile>(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
|