Most review changes
This commit is contained in:
@@ -803,12 +803,12 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
|
||||
std::vector<std::string> SplitPathComponents(const std::string& filename) {
|
||||
auto copy(filename);
|
||||
std::replace(copy.begin(), copy.end(), '\\', '/');
|
||||
std::vector<std::string> out{};
|
||||
std::vector<std::string> out;
|
||||
|
||||
std::stringstream stream(filename);
|
||||
std::string item;
|
||||
while (std::getline(stream, item, '/'))
|
||||
out.push_back(item);
|
||||
out.push_back(std::move(item));
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -826,16 +826,17 @@ std::string GetParentPath(const std::string& path) {
|
||||
return out.erase(name_index);
|
||||
}
|
||||
|
||||
std::string GetFilename(const std::string& path) {
|
||||
auto out = path;
|
||||
std::replace(out.begin(), out.end(), '\\', '/');
|
||||
auto name_index = out.find_last_of('/');
|
||||
std::string GetFilename(std::string path) {
|
||||
std::replace(path.begin(), path.end(), '\\', '/');
|
||||
auto name_index = path.find_last_of('/');
|
||||
if (name_index == std::string::npos)
|
||||
return "";
|
||||
return out.substr(name_index + 1);
|
||||
return path.substr(name_index + 1);
|
||||
}
|
||||
|
||||
std::string RemoveTrailingSlash(const std::string& path) {
|
||||
if (path.empty())
|
||||
return path;
|
||||
if (path.back() == '\\' || path.back() == '/')
|
||||
return path.substr(0, path.size() - 1);
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ std::vector<std::string> SplitPathComponents(const std::string& filename);
|
||||
std::string GetParentPath(const std::string& path);
|
||||
|
||||
// Gets the filename of the path
|
||||
std::string GetFilename(const std::string& path);
|
||||
std::string GetFilename(std::string path);
|
||||
|
||||
// Removes the final '/' or '\' if one exists
|
||||
std::string RemoveTrailingSlash(const std::string& path);
|
||||
|
||||
@@ -7,15 +7,16 @@
|
||||
#include "core/file_sys/vfs_offset.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
// Media offsets in headers are stored divided by 512. Mult. by this to get real offset.
|
||||
constexpr u64 MEDIA_OFFSET_MULTIPLIER = 0x200;
|
||||
|
||||
constexpr u64 SECTION_HEADER_SIZE = 0x200;
|
||||
constexpr u64 SECTION_HEADER_OFFSET = 0x400;
|
||||
|
||||
constexpr unsigned IVFC_MAX_LEVEL = 6;
|
||||
constexpr u32 IVFC_MAX_LEVEL = 6;
|
||||
|
||||
namespace FileSys {
|
||||
enum class NCASectionFilesystemType : u8 { PFS0 = 0x2, ROMFS = 0x3 };
|
||||
|
||||
struct NCASectionHeaderBlock {
|
||||
@@ -66,11 +67,11 @@ NCA::NCA(VirtualFile file_) : file(file_) {
|
||||
return;
|
||||
}
|
||||
|
||||
int number_sections =
|
||||
std::ptrdiff_t number_sections =
|
||||
std::count_if(std::begin(header.section_tables), std::end(header.section_tables),
|
||||
[](NCASectionTableEntry entry) { return entry.media_offset > 0; });
|
||||
|
||||
for (int i = 0; i < number_sections; ++i) {
|
||||
for (std::ptrdiff_t i = 0; i < number_sections; ++i) {
|
||||
// Seek to beginning of this section.
|
||||
NCASectionHeaderBlock block{};
|
||||
if (sizeof(NCASectionHeaderBlock) !=
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "partition_filesystem.h"
|
||||
#include "core/file_sys/partition_filesystem.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
@@ -55,17 +55,6 @@ static bool IsValidNCA(const NCAHeader& header) {
|
||||
// An implementation of VfsDirectory that represents a Nintendo Content Archive (NCA) conatiner.
|
||||
// After construction, use GetStatus to determine if the file is valid and ready to be used.
|
||||
class NCA : public ReadOnlyVfsDirectory {
|
||||
std::vector<VirtualDir> dirs{};
|
||||
std::vector<VirtualFile> files{};
|
||||
|
||||
VirtualFile romfs = nullptr;
|
||||
VirtualDir exefs = nullptr;
|
||||
VirtualFile file;
|
||||
|
||||
NCAHeader header{};
|
||||
|
||||
Loader::ResultStatus status{};
|
||||
|
||||
public:
|
||||
explicit NCA(VirtualFile file);
|
||||
Loader::ResultStatus GetStatus() const;
|
||||
@@ -83,6 +72,18 @@ public:
|
||||
|
||||
protected:
|
||||
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
|
||||
|
||||
private:
|
||||
std::vector<VirtualDir> dirs;
|
||||
std::vector<VirtualFile> files;
|
||||
|
||||
VirtualFile romfs = nullptr;
|
||||
VirtualDir exefs = nullptr;
|
||||
VirtualFile file;
|
||||
|
||||
NCAHeader header{};
|
||||
|
||||
Loader::ResultStatus status{};
|
||||
};
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include "common/file_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/partition_filesystem.h"
|
||||
#include "core/file_sys/vfs_offset.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "vfs_offset.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ std::string VfsFile::GetExtension() const {
|
||||
size_t index = GetName().find_last_of('.');
|
||||
if (index == std::string::npos)
|
||||
return "";
|
||||
else
|
||||
return GetName().substr(index + 1);
|
||||
|
||||
return GetName().substr(index + 1);
|
||||
}
|
||||
|
||||
VfsDirectory::~VfsDirectory() = default;
|
||||
@@ -41,7 +41,7 @@ std::vector<u8> VfsFile::ReadAllBytes() const {
|
||||
}
|
||||
|
||||
bool VfsFile::WriteByte(u8 data, size_t offset) {
|
||||
return 1 == Write(&data, 1, offset);
|
||||
return Write(&data, 1, offset) == 1;
|
||||
}
|
||||
|
||||
size_t VfsFile::WriteBytes(std::vector<u8> data, size_t offset) {
|
||||
@@ -57,7 +57,7 @@ std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(const std::string& path)
|
||||
if (vec.size() == 1)
|
||||
return GetFile(vec[0]);
|
||||
auto dir = GetSubdirectory(vec[0]);
|
||||
for (auto i = 1u; i < vec.size() - 1; ++i) {
|
||||
for (size_t i = 1; i < vec.size() - 1; ++i) {
|
||||
if (dir == nullptr)
|
||||
return nullptr;
|
||||
dir = dir->GetSubdirectory(vec[i]);
|
||||
@@ -82,7 +82,7 @@ std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(const std::stri
|
||||
// return std::shared_ptr<VfsDirectory>(this);
|
||||
return nullptr;
|
||||
auto dir = GetSubdirectory(vec[0]);
|
||||
for (auto i = 1u; i < vec.size(); ++i) {
|
||||
for (size_t i = 1; i < vec.size(); ++i) {
|
||||
dir = dir->GetSubdirectory(vec[i]);
|
||||
}
|
||||
return dir;
|
||||
@@ -97,19 +97,16 @@ std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryAbsolute(const std::stri
|
||||
|
||||
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();
|
||||
});
|
||||
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 {
|
||||
// if (name == "" || name == "." || name == "/" || name == "\\")
|
||||
// return std::shared_ptr<VfsDirectory>(const_cast<VfsDirectory*>(this));
|
||||
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);
|
||||
const auto iter = std::find_if(subs.begin(), subs.end(),
|
||||
[&name](const auto& file1) { return name == file1->GetName(); });
|
||||
return iter == subs.end() ? nullptr : *iter;
|
||||
}
|
||||
|
||||
bool VfsDirectory::IsRoot() const {
|
||||
@@ -136,13 +133,15 @@ bool VfsDirectory::DeleteSubdirectoryRecursive(const std::string& name) {
|
||||
return false;
|
||||
|
||||
bool success = true;
|
||||
for (const auto& file : dir->GetFiles())
|
||||
for (const auto& file : dir->GetFiles()) {
|
||||
if (!DeleteFile(file->GetName()))
|
||||
success = false;
|
||||
}
|
||||
|
||||
for (const auto& sdir : dir->GetSubdirectories())
|
||||
for (const auto& sdir : dir->GetSubdirectories()) {
|
||||
if (!dir->DeleteSubdirectoryRecursive(sdir->GetName()))
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -15,14 +15,11 @@
|
||||
namespace FileSys {
|
||||
struct VfsFile;
|
||||
struct VfsDirectory;
|
||||
} // namespace FileSys
|
||||
|
||||
// Convenience typedefs to use VfsDirectory and VfsFile
|
||||
using VirtualDir = std::shared_ptr<FileSys::VfsDirectory>;
|
||||
using VirtualFile = std::shared_ptr<FileSys::VfsFile>;
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
// A class representing a file in an abstract filesystem.
|
||||
struct VfsFile : NonCopyable {
|
||||
virtual ~VfsFile();
|
||||
|
||||
@@ -84,9 +84,11 @@ RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_)
|
||||
if (!FileUtil::Exists(path) && (perms == Mode::Write || perms == Mode::Append))
|
||||
FileUtil::CreateDir(path);
|
||||
unsigned size;
|
||||
if (perms != Mode::Append)
|
||||
if (perms != Mode::Append) {
|
||||
FileUtil::ForeachDirectoryEntry(
|
||||
&size, path, [this](auto x1, auto directory, auto filename) {
|
||||
&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(
|
||||
@@ -95,6 +97,7 @@ RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_)
|
||||
files.emplace_back(std::make_shared<RealVfsFile>(full_path, perms));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const {
|
||||
@@ -147,9 +150,6 @@ bool RealVfsDirectory::DeleteFile(const std::string& name) {
|
||||
}
|
||||
|
||||
bool RealVfsDirectory::Rename(const std::string& name) {
|
||||
/* TODO(DarkLordZach): cppreference says for files, MSVC docs say for files/dirs.
|
||||
* Does C rename(const char*, const char*) work on dirs?
|
||||
*/
|
||||
return FileUtil::Rename(path, parent_path + DIR_SEP + name);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,14 +18,16 @@
|
||||
|
||||
namespace Service::FileSystem {
|
||||
|
||||
static VirtualDir GetDirectoryRelativeWrapped(VirtualDir base, const std::string& dir_name) {
|
||||
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
|
||||
const std::string& dir_name) {
|
||||
if (dir_name == "." || dir_name == "" || dir_name == "/" || dir_name == "\\")
|
||||
return base;
|
||||
|
||||
return base->GetDirectoryRelative(dir_name);
|
||||
}
|
||||
|
||||
VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(VirtualDir backing_) : backing(backing_) {}
|
||||
VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(FileSys::VirtualDir backing_)
|
||||
: backing(backing_) {}
|
||||
|
||||
std::string VfsDirectoryServiceWrapper::GetName() const {
|
||||
return backing->GetName();
|
||||
@@ -122,16 +124,16 @@ ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_pa
|
||||
return ResultCode(-1);
|
||||
}
|
||||
|
||||
ResultVal<VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path,
|
||||
FileSys::Mode mode) const {
|
||||
ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path,
|
||||
FileSys::Mode mode) const {
|
||||
auto file = backing->GetFileRelative(path);
|
||||
if (file == nullptr)
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
// TODO(DarkLordZach): Error checking/result modification with different modes.
|
||||
return MakeResult<VirtualFile>(file);
|
||||
return MakeResult<FileSys::VirtualFile>(file);
|
||||
}
|
||||
|
||||
ResultVal<VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) {
|
||||
ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) {
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, path);
|
||||
if (dir == nullptr)
|
||||
return ResultCode(-1);
|
||||
@@ -141,7 +143,7 @@ ResultVal<VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::strin
|
||||
u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const {
|
||||
// TODO(DarkLordZach): Infinite? Actual? Is this actually used productively or...?
|
||||
if (backing->IsWritable())
|
||||
return -1;
|
||||
return std::numeric_limits<u64>::max();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -164,7 +166,7 @@ ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
|
||||
// registration time.
|
||||
struct SaveDataDeferredFilesystem : DeferredFilesystem {
|
||||
protected:
|
||||
VirtualDir CreateFilesystem() override {
|
||||
FileSys::VirtualDir CreateFilesystem() override {
|
||||
u64 title_id = Core::CurrentProcess()->program_id;
|
||||
// TODO(DarkLordZach): Users
|
||||
u32 user_id = 0;
|
||||
@@ -182,7 +184,7 @@ protected:
|
||||
* is never removed until UnregisterFileSystems is called.
|
||||
*/
|
||||
static boost::container::flat_map<Type, std::unique_ptr<DeferredFilesystem>> filesystem_map;
|
||||
static VirtualFile filesystem_romfs = nullptr;
|
||||
static FileSys::VirtualFile filesystem_romfs = nullptr;
|
||||
|
||||
ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& factory, Type type) {
|
||||
auto result = filesystem_map.emplace(type, std::move(factory));
|
||||
@@ -195,7 +197,7 @@ ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& factory, Typ
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode RegisterRomFS(VirtualFile filesystem) {
|
||||
ResultCode RegisterRomFS(FileSys::VirtualFile filesystem) {
|
||||
ASSERT_MSG(filesystem_romfs == nullptr,
|
||||
"Tried to register more than one system with same id code");
|
||||
|
||||
@@ -205,7 +207,7 @@ ResultCode RegisterRomFS(VirtualFile filesystem) {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultVal<VirtualDir> OpenFileSystem(Type type) {
|
||||
ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type) {
|
||||
LOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type));
|
||||
|
||||
auto itr = filesystem_map.find(type);
|
||||
@@ -217,7 +219,7 @@ ResultVal<VirtualDir> OpenFileSystem(Type type) {
|
||||
return MakeResult(itr->second->Get());
|
||||
}
|
||||
|
||||
ResultVal<VirtualFile> OpenRomFS() {
|
||||
ResultVal<FileSys::VirtualFile> OpenRomFS() {
|
||||
if (filesystem_romfs == nullptr)
|
||||
return ResultCode(-1);
|
||||
return MakeResult(filesystem_romfs);
|
||||
|
||||
@@ -35,10 +35,8 @@ enum class Type {
|
||||
// pointers and booleans. This makes using a VfsDirectory with switch services much easier and
|
||||
// avoids repetitive code.
|
||||
class VfsDirectoryServiceWrapper {
|
||||
VirtualDir backing;
|
||||
|
||||
public:
|
||||
explicit VfsDirectoryServiceWrapper(VirtualDir backing);
|
||||
explicit VfsDirectoryServiceWrapper(FileSys::VirtualDir backing);
|
||||
|
||||
/**
|
||||
* Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
|
||||
@@ -103,14 +101,14 @@ public:
|
||||
* @param mode Mode to open the file with
|
||||
* @return Opened file, or error code
|
||||
*/
|
||||
ResultVal<VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const;
|
||||
ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const;
|
||||
|
||||
/**
|
||||
* Open a directory specified by its path
|
||||
* @param path Path relative to the archive
|
||||
* @return Opened directory, or error code
|
||||
*/
|
||||
ResultVal<VirtualDir> OpenDirectory(const std::string& path);
|
||||
ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path);
|
||||
|
||||
/**
|
||||
* Get the free space
|
||||
@@ -123,6 +121,9 @@ public:
|
||||
* @return The type of the specified path or error code
|
||||
*/
|
||||
ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const;
|
||||
|
||||
private:
|
||||
FileSys::VirtualDir backing;
|
||||
};
|
||||
|
||||
// A class that deferres the creation of a filesystem until a later time.
|
||||
@@ -130,26 +131,26 @@ public:
|
||||
// Construct this with a filesystem (VirtualDir) to avoid the deferrence feature or override the
|
||||
// CreateFilesystem method which will be called on first use.
|
||||
struct DeferredFilesystem {
|
||||
DeferredFilesystem(){};
|
||||
DeferredFilesystem() = default;
|
||||
|
||||
explicit DeferredFilesystem(VirtualDir vfs_directory) : fs(vfs_directory) {}
|
||||
explicit DeferredFilesystem(FileSys::VirtualDir vfs_directory) : fs(std::move(vfs_directory)) {}
|
||||
|
||||
VirtualDir Get() {
|
||||
FileSys::VirtualDir Get() {
|
||||
if (fs == nullptr)
|
||||
fs = CreateFilesystem();
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
~DeferredFilesystem() = default;
|
||||
virtual ~DeferredFilesystem() = default;
|
||||
|
||||
protected:
|
||||
virtual VirtualDir CreateFilesystem() {
|
||||
virtual FileSys::VirtualDir CreateFilesystem() {
|
||||
return fs;
|
||||
}
|
||||
|
||||
private:
|
||||
VirtualDir fs;
|
||||
FileSys::VirtualDir fs;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -159,7 +160,7 @@ private:
|
||||
*/
|
||||
ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& fs, Type type);
|
||||
|
||||
ResultCode RegisterRomFS(VirtualFile fs);
|
||||
ResultCode RegisterRomFS(FileSys::VirtualFile fs);
|
||||
|
||||
/**
|
||||
* Opens a file system
|
||||
@@ -167,9 +168,9 @@ ResultCode RegisterRomFS(VirtualFile fs);
|
||||
* @param path Path to the file system, used with Binary paths
|
||||
* @return FileSys::FileSystemBackend interface to the file system
|
||||
*/
|
||||
ResultVal<VirtualDir> OpenFileSystem(Type type);
|
||||
ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type);
|
||||
|
||||
ResultVal<VirtualFile> OpenRomFS();
|
||||
ResultVal<FileSys::VirtualFile> OpenRomFS();
|
||||
|
||||
/**
|
||||
* Formats a file system
|
||||
|
||||
@@ -19,7 +19,8 @@ namespace Service::FileSystem {
|
||||
|
||||
class IStorage final : public ServiceFramework<IStorage> {
|
||||
public:
|
||||
IStorage(VirtualFile backend_) : ServiceFramework("IStorage"), backend(backend_) {
|
||||
IStorage(FileSys::VirtualFile backend_)
|
||||
: ServiceFramework("IStorage"), backend(std::move(backend_)) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, {2, nullptr, "Flush"},
|
||||
{3, nullptr, "SetSize"}, {4, nullptr, "GetSize"}, {5, nullptr, "OperateRange"},
|
||||
@@ -28,7 +29,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
VirtualFile backend;
|
||||
FileSys::VirtualFile backend;
|
||||
|
||||
void Read(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
@@ -68,7 +69,8 @@ private:
|
||||
|
||||
class IFile final : public ServiceFramework<IFile> {
|
||||
public:
|
||||
explicit IFile(VirtualFile backend_) : ServiceFramework("IFile"), backend(backend_) {
|
||||
explicit IFile(FileSys::VirtualFile backend_)
|
||||
: ServiceFramework("IFile"), backend(std::move(backend_)) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"},
|
||||
{2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"},
|
||||
@@ -78,7 +80,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
VirtualFile backend;
|
||||
FileSys::VirtualFile backend;
|
||||
|
||||
void Read(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
@@ -180,9 +182,23 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data,
|
||||
FileSys::EntryType type) {
|
||||
for (const auto& new_entry : new_data) {
|
||||
FileSys::Entry entry;
|
||||
entry.filename[0] = '\0';
|
||||
std::strncat(entry.filename, new_entry->GetName().c_str(), FileSys::FILENAME_LENGTH - 1);
|
||||
entry.type = type;
|
||||
entry.file_size = new_entry->GetSize();
|
||||
entries.emplace_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
class IDirectory final : public ServiceFramework<IDirectory> {
|
||||
public:
|
||||
explicit IDirectory(VirtualDir backend_) : ServiceFramework("IDirectory"), backend(backend_) {
|
||||
explicit IDirectory(FileSys::VirtualDir backend_)
|
||||
: ServiceFramework("IDirectory"), backend(std::move(backend_)) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IDirectory::Read, "Read"},
|
||||
{1, &IDirectory::GetEntryCount, "GetEntryCount"},
|
||||
@@ -190,27 +206,12 @@ public:
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// Build entry index now to save time later.
|
||||
for (const auto& file : backend->GetFiles()) {
|
||||
FileSys::Entry entry;
|
||||
entry.filename[0] = '\0';
|
||||
strncat(entry.filename, file->GetName().c_str(), FileSys::FILENAME_LENGTH - 1);
|
||||
entry.type = FileSys::File;
|
||||
entry.file_size = file->GetSize();
|
||||
entries.emplace_back(entry);
|
||||
}
|
||||
|
||||
for (const auto& dir : backend->GetSubdirectories()) {
|
||||
FileSys::Entry entry;
|
||||
entry.filename[0] = '\0';
|
||||
strncat(entry.filename, dir->GetName().c_str(), FileSys::FILENAME_LENGTH - 1);
|
||||
entry.type = FileSys::Directory;
|
||||
entry.file_size = dir->GetSize();
|
||||
entries.emplace_back(entry);
|
||||
}
|
||||
BuildEntryIndex(entries, backend->GetFiles(), FileSys::File);
|
||||
BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::Directory);
|
||||
}
|
||||
|
||||
private:
|
||||
VirtualDir backend;
|
||||
FileSys::VirtualDir backend;
|
||||
std::vector<FileSys::Entry> entries;
|
||||
u64 next_entry_index = 0;
|
||||
|
||||
@@ -257,7 +258,7 @@ private:
|
||||
|
||||
class IFileSystem final : public ServiceFramework<IFileSystem> {
|
||||
public:
|
||||
explicit IFileSystem(VirtualDir backend)
|
||||
explicit IFileSystem(FileSys::VirtualDir backend)
|
||||
: ServiceFramework("IFileSystem"), backend(std::move(backend)) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IFileSystem::CreateFile, "CreateFile"},
|
||||
@@ -517,7 +518,7 @@ void FSP_SRV::TryLoadRomFS() {
|
||||
}
|
||||
auto res = OpenRomFS();
|
||||
if (res.Succeeded()) {
|
||||
romfs = res.Unwrap();
|
||||
romfs = std::move(res.Unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ private:
|
||||
void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
|
||||
void OpenRomStorage(Kernel::HLERequestContext& ctx);
|
||||
|
||||
VirtualFile romfs;
|
||||
FileSys::VirtualFile romfs;
|
||||
};
|
||||
|
||||
} // namespace Service::FileSystem
|
||||
|
||||
@@ -45,10 +45,10 @@ static std::string FindRomFS(const std::string& directory) {
|
||||
return filepath_romfs;
|
||||
}
|
||||
|
||||
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(VirtualFile file)
|
||||
: AppLoader(file) {}
|
||||
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file)
|
||||
: AppLoader(std::move(file)) {}
|
||||
|
||||
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(VirtualFile file) {
|
||||
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
if (FileSys::IsDirectoryExeFS(file->GetContainingDirectory())) {
|
||||
return FileType::DeconstructedRomDirectory;
|
||||
}
|
||||
@@ -62,8 +62,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
|
||||
return ResultStatus::ErrorAlreadyLoaded;
|
||||
}
|
||||
|
||||
const VirtualDir dir = file->GetContainingDirectory();
|
||||
const VirtualFile npdm = dir->GetFile("main.npdm");
|
||||
const FileSys::VirtualDir dir = file->GetContainingDirectory();
|
||||
const FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
|
||||
if (npdm == nullptr)
|
||||
return ResultStatus::ErrorInvalidFormat;
|
||||
|
||||
@@ -83,7 +83,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
|
||||
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
|
||||
"subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
|
||||
const VAddr load_addr = next_load_addr;
|
||||
const VirtualFile module_file = dir->GetFile(module);
|
||||
const FileSys::VirtualFile module_file = dir->GetFile(module);
|
||||
if (module_file != nullptr)
|
||||
next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr);
|
||||
if (next_load_addr) {
|
||||
@@ -103,9 +103,10 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
|
||||
|
||||
// Find the RomFS by searching for a ".romfs" file in this directory
|
||||
const auto& files = dir->GetFiles();
|
||||
const auto romfs_iter = std::find_if(files.begin(), files.end(), [](const VirtualFile& file) {
|
||||
return file->GetName().find(".romfs") != std::string::npos;
|
||||
});
|
||||
const auto romfs_iter =
|
||||
std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
|
||||
return file->GetName().find(".romfs") != std::string::npos;
|
||||
});
|
||||
|
||||
// TODO(DarkLordZach): Identify RomFS if its a subdirectory.
|
||||
const auto romfs = (romfs_iter == files.end()) ? nullptr : *romfs_iter;
|
||||
|
||||
@@ -20,14 +20,14 @@ namespace Loader {
|
||||
*/
|
||||
class AppLoader_DeconstructedRomDirectory final : public AppLoader {
|
||||
public:
|
||||
AppLoader_DeconstructedRomDirectory(VirtualFile main_file);
|
||||
explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file);
|
||||
|
||||
/**
|
||||
* Returns the type of the file
|
||||
* @param file std::shared_ptr<VfsFile> open file
|
||||
* @return FileType found, or FileType::Error if this loader doesn't know it
|
||||
*/
|
||||
static FileType IdentifyType(VirtualFile file);
|
||||
static FileType IdentifyType(const FileSys::VirtualFile& file);
|
||||
|
||||
FileType GetFileType() override {
|
||||
return IdentifyType(file);
|
||||
|
||||
@@ -365,9 +365,9 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const
|
||||
|
||||
namespace Loader {
|
||||
|
||||
AppLoader_ELF::AppLoader_ELF(VirtualFile file) : AppLoader(file) {}
|
||||
AppLoader_ELF::AppLoader_ELF(FileSys::VirtualFile file) : AppLoader(std::move(file)) {}
|
||||
|
||||
FileType AppLoader_ELF::IdentifyType(VirtualFile file) {
|
||||
FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
static constexpr u16 ELF_MACHINE_ARM{0x28};
|
||||
|
||||
u32 magic = 0;
|
||||
|
||||
@@ -16,14 +16,14 @@ namespace Loader {
|
||||
/// Loads an ELF/AXF file
|
||||
class AppLoader_ELF final : public AppLoader {
|
||||
public:
|
||||
AppLoader_ELF(VirtualFile file);
|
||||
explicit AppLoader_ELF(FileSys::VirtualFile file);
|
||||
|
||||
/**
|
||||
* Returns the type of the file
|
||||
* @param file std::shared_ptr<VfsFile> open file
|
||||
* @return FileType found, or FileType::Error if this loader doesn't know it
|
||||
*/
|
||||
static FileType IdentifyType(VirtualFile file);
|
||||
static FileType IdentifyType(const FileSys::VirtualFile& file);
|
||||
|
||||
FileType GetFileType() override {
|
||||
return IdentifyType(file);
|
||||
|
||||
@@ -22,7 +22,7 @@ const std::initializer_list<Kernel::AddressMapping> default_address_mappings = {
|
||||
{0x1F000000, 0x600000, false}, // entire VRAM
|
||||
};
|
||||
|
||||
FileType IdentifyFile(VirtualFile file) {
|
||||
FileType IdentifyFile(FileSys::VirtualFile file) {
|
||||
FileType type;
|
||||
|
||||
#define CHECK_TYPE(loader) \
|
||||
@@ -42,7 +42,7 @@ FileType IdentifyFile(VirtualFile file) {
|
||||
}
|
||||
|
||||
FileType IdentifyFile(const std::string& file_name) {
|
||||
return IdentifyFile(VirtualFile(std::make_shared<FileSys::RealVfsFile>(file_name)));
|
||||
return IdentifyFile(FileSys::VirtualFile(std::make_shared<FileSys::RealVfsFile>(file_name)));
|
||||
}
|
||||
|
||||
FileType GuessFromExtension(const std::string& extension_) {
|
||||
@@ -88,35 +88,35 @@ const char* GetFileTypeString(FileType type) {
|
||||
* @param filepath the file full path (with name)
|
||||
* @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
|
||||
*/
|
||||
static std::unique_ptr<AppLoader> GetFileLoader(VirtualFile file, FileType type) {
|
||||
static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileType type) {
|
||||
switch (type) {
|
||||
|
||||
// Standard ELF file format.
|
||||
case FileType::ELF:
|
||||
return std::make_unique<AppLoader_ELF>(file);
|
||||
return std::make_unique<AppLoader_ELF>(std::move(file));
|
||||
|
||||
// NX NSO file format.
|
||||
case FileType::NSO:
|
||||
return std::make_unique<AppLoader_NSO>(file);
|
||||
return std::make_unique<AppLoader_NSO>(std::move(file));
|
||||
|
||||
// NX NRO file format.
|
||||
case FileType::NRO:
|
||||
return std::make_unique<AppLoader_NRO>(file);
|
||||
return std::make_unique<AppLoader_NRO>(std::move(file));
|
||||
|
||||
// NX NCA file format.
|
||||
case FileType::NCA:
|
||||
return std::make_unique<AppLoader_NCA>(file);
|
||||
return std::make_unique<AppLoader_NCA>(std::move(file));
|
||||
|
||||
// NX deconstructed ROM directory.
|
||||
case FileType::DeconstructedRomDirectory:
|
||||
return std::make_unique<AppLoader_DeconstructedRomDirectory>(file);
|
||||
return std::make_unique<AppLoader_DeconstructedRomDirectory>(std::move(file));
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<AppLoader> GetLoader(VirtualFile file) {
|
||||
std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file) {
|
||||
FileType type = IdentifyFile(file);
|
||||
FileType filename_type = GuessFromExtension(file->GetExtension());
|
||||
|
||||
@@ -128,7 +128,7 @@ std::unique_ptr<AppLoader> GetLoader(VirtualFile file) {
|
||||
|
||||
LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type));
|
||||
|
||||
return GetFileLoader(file, type);
|
||||
return GetFileLoader(std::move(file), type);
|
||||
}
|
||||
|
||||
} // namespace Loader
|
||||
|
||||
@@ -39,7 +39,7 @@ enum class FileType {
|
||||
* @param file open file
|
||||
* @return FileType of file
|
||||
*/
|
||||
FileType IdentifyFile(VirtualFile file);
|
||||
FileType IdentifyFile(FileSys::VirtualFile file);
|
||||
|
||||
/**
|
||||
* Identifies the type of a bootable file based on the magic value in its header.
|
||||
@@ -79,7 +79,7 @@ enum class ResultStatus {
|
||||
/// Interface for loading an application
|
||||
class AppLoader : NonCopyable {
|
||||
public:
|
||||
AppLoader(VirtualFile file) : file(std::move(file)) {}
|
||||
AppLoader(FileSys::VirtualFile file) : file(std::move(file)) {}
|
||||
virtual ~AppLoader() {}
|
||||
|
||||
/**
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
* @param file The file containing the RomFS
|
||||
* @return ResultStatus result of function
|
||||
*/
|
||||
virtual ResultStatus ReadRomFS(VirtualFile& dir) {
|
||||
virtual ResultStatus ReadRomFS(FileSys::VirtualFile& dir) {
|
||||
return ResultStatus::ErrorNotImplemented;
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
* @param file The file containing the RomFS
|
||||
* @return ResultStatus result of function
|
||||
*/
|
||||
virtual ResultStatus ReadUpdateRomFS(VirtualFile& file) {
|
||||
virtual ResultStatus ReadUpdateRomFS(FileSys::VirtualFile& file) {
|
||||
return ResultStatus::ErrorNotImplemented;
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
VirtualFile file;
|
||||
FileSys::VirtualFile file;
|
||||
bool is_loaded = false;
|
||||
};
|
||||
|
||||
@@ -196,6 +196,6 @@ extern const std::initializer_list<Kernel::AddressMapping> default_address_mappi
|
||||
* @param filename String filename of bootable file
|
||||
* @return best loader for this file
|
||||
*/
|
||||
std::unique_ptr<AppLoader> GetLoader(VirtualFile file);
|
||||
std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file);
|
||||
|
||||
} // namespace Loader
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
namespace Loader {
|
||||
|
||||
AppLoader_NCA::AppLoader_NCA(VirtualFile file) : AppLoader(file) {}
|
||||
AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file) : AppLoader(file) {}
|
||||
|
||||
FileType AppLoader_NCA::IdentifyType(VirtualFile file) {
|
||||
FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
// TODO(DarkLordZach): Assuming everything is decrypted. Add crypto support.
|
||||
FileSys::NCAHeader header{};
|
||||
if (sizeof(FileSys::NCAHeader) != file->ReadObject(&header))
|
||||
|
||||
@@ -16,14 +16,14 @@ namespace Loader {
|
||||
/// Loads an NCA file
|
||||
class AppLoader_NCA final : public AppLoader {
|
||||
public:
|
||||
AppLoader_NCA(VirtualFile file);
|
||||
explicit AppLoader_NCA(FileSys::VirtualFile file);
|
||||
|
||||
/**
|
||||
* Returns the type of the file
|
||||
* @param file std::shared_ptr<VfsFile> open file
|
||||
* @return FileType found, or FileType::Error if this loader doesn't know it
|
||||
*/
|
||||
static FileType IdentifyType(VirtualFile file);
|
||||
static FileType IdentifyType(const FileSys::VirtualFile& file);
|
||||
|
||||
FileType GetFileType() override {
|
||||
return IdentifyType(file);
|
||||
|
||||
@@ -47,9 +47,9 @@ struct ModHeader {
|
||||
};
|
||||
static_assert(sizeof(ModHeader) == 0x1c, "ModHeader has incorrect size.");
|
||||
|
||||
AppLoader_NRO::AppLoader_NRO(VirtualFile file) : AppLoader(file) {}
|
||||
AppLoader_NRO::AppLoader_NRO(FileSys::VirtualFile file) : AppLoader(file) {}
|
||||
|
||||
FileType AppLoader_NRO::IdentifyType(VirtualFile file) {
|
||||
FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
// Read NSO header
|
||||
NroHeader nro_header{};
|
||||
if (sizeof(NroHeader) != file->ReadObject(&nro_header)) {
|
||||
@@ -65,7 +65,7 @@ static constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
|
||||
}
|
||||
|
||||
bool AppLoader_NRO::LoadNro(VirtualFile file, VAddr load_base) {
|
||||
bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) {
|
||||
// Read NSO header
|
||||
NroHeader nro_header{};
|
||||
if (sizeof(NroHeader) != file->ReadObject(&nro_header)) {
|
||||
|
||||
@@ -15,14 +15,14 @@ namespace Loader {
|
||||
/// Loads an NRO file
|
||||
class AppLoader_NRO final : public AppLoader, Linker {
|
||||
public:
|
||||
AppLoader_NRO(VirtualFile file);
|
||||
AppLoader_NRO(FileSys::VirtualFile file);
|
||||
|
||||
/**
|
||||
* Returns the type of the file
|
||||
* @param file std::shared_ptr<VfsFile> open file
|
||||
* @return FileType found, or FileType::Error if this loader doesn't know it
|
||||
*/
|
||||
static FileType IdentifyType(VirtualFile file);
|
||||
static FileType IdentifyType(const FileSys::VirtualFile& file);
|
||||
|
||||
FileType GetFileType() override {
|
||||
return IdentifyType(file);
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
|
||||
|
||||
private:
|
||||
bool LoadNro(VirtualFile file, VAddr load_base);
|
||||
bool LoadNro(FileSys::VirtualFile file, VAddr load_base);
|
||||
};
|
||||
|
||||
} // namespace Loader
|
||||
|
||||
@@ -37,7 +37,7 @@ struct NsoHeader {
|
||||
std::array<u32_le, 3> segments_compressed_size;
|
||||
};
|
||||
static_assert(sizeof(NsoHeader) == 0x6c, "NsoHeader has incorrect size.");
|
||||
static_assert(std::is_trivially_copyable<NsoHeader>::value, "NsoHeader isn't trivially copyable.");
|
||||
static_assert(std::is_trivially_copyable_v<NsoHeader>, "NsoHeader isn't trivially copyable.");
|
||||
|
||||
struct ModHeader {
|
||||
u32_le magic;
|
||||
@@ -50,9 +50,9 @@ struct ModHeader {
|
||||
};
|
||||
static_assert(sizeof(ModHeader) == 0x1c, "ModHeader has incorrect size.");
|
||||
|
||||
AppLoader_NSO::AppLoader_NSO(VirtualFile file) : AppLoader(file) {}
|
||||
AppLoader_NSO::AppLoader_NSO(FileSys::VirtualFile file) : AppLoader(std::move(file)) {}
|
||||
|
||||
FileType AppLoader_NSO::IdentifyType(VirtualFile file) {
|
||||
FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
u32 magic = 0;
|
||||
file->ReadObject(&magic);
|
||||
|
||||
@@ -95,7 +95,7 @@ static constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
|
||||
}
|
||||
|
||||
VAddr AppLoader_NSO::LoadModule(VirtualFile file, VAddr load_base) {
|
||||
VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base) {
|
||||
if (file == nullptr)
|
||||
return {};
|
||||
|
||||
|
||||
@@ -15,20 +15,20 @@ namespace Loader {
|
||||
/// Loads an NSO file
|
||||
class AppLoader_NSO final : public AppLoader, Linker {
|
||||
public:
|
||||
AppLoader_NSO(VirtualFile file);
|
||||
explicit AppLoader_NSO(FileSys::VirtualFile file);
|
||||
|
||||
/**
|
||||
* Returns the type of the file
|
||||
* @param file std::shared_ptr<VfsFile> open file
|
||||
* @return FileType found, or FileType::Error if this loader doesn't know it
|
||||
*/
|
||||
static FileType IdentifyType(VirtualFile file);
|
||||
static FileType IdentifyType(const FileSys::VirtualFile& file);
|
||||
|
||||
FileType GetFileType() override {
|
||||
return IdentifyType(file);
|
||||
}
|
||||
|
||||
static VAddr LoadModule(VirtualFile file, VAddr load_base);
|
||||
static VAddr LoadModule(FileSys::VirtualFile file, VAddr load_base);
|
||||
|
||||
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user