Fixes and testing

This commit is contained in:
Zach Hilman
2018-06-26 20:58:46 -04:00
parent 275abf35cf
commit 80f2c08f31
19 changed files with 185 additions and 135 deletions

View File

@@ -19,6 +19,7 @@
#include "core/loader/loader.h"
#include "core/memory_setup.h"
#include "core/settings.h"
#include "file_sys/vfs_real.h"
#include "video_core/video_core.h"
namespace Core {
@@ -84,7 +85,7 @@ System::ResultStatus System::SingleStep() {
}
System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
app_loader = Loader::GetLoader(filepath);
app_loader = Loader::GetLoader(std::make_shared<FileSys::RealVfsFile>(filepath));
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);

View File

@@ -44,7 +44,7 @@ static_assert(sizeof(NCAHeader) == 0x400, "NCAHeader has incorrect size.");
static bool IsDirectoryExeFS(std::shared_ptr<FileSys::VfsDirectory> pfs) {
// According to switchbrew, an exefs must only contain these two files:
return pfs->GetFile("main") != nullptr && pfs->GetFile("main.ndpm") != nullptr;
return pfs->GetFile("main") != nullptr && pfs->GetFile("main.npdm") != nullptr;
}
static bool IsValidNCA(const NCAHeader& header) {

View File

@@ -21,7 +21,7 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) {
// For cartridges, HFSs can get very large, so we need to calculate the size up to
// the actual content itself instead of just blindly reading in the entire file.
Header pfs_header;
if (!file->ReadObject(&pfs_header)) {
if (sizeof(Header) != file->ReadObject(&pfs_header)) {
status = Loader::ResultStatus::Error;
return;
}
@@ -52,7 +52,7 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) {
return;
}
memcpy(&pfs_header, &file_data, sizeof(Header));
memcpy(&pfs_header, file_data.data(), sizeof(Header));
if (pfs_header.magic != Common::MakeMagic('H', 'F', 'S', '0') &&
pfs_header.magic != Common::MakeMagic('P', 'F', 'S', '0')) {
status = Loader::ResultStatus::ErrorInvalidFormat;

View File

@@ -54,7 +54,7 @@ std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(const filesystem::path& p
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 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)
@@ -69,11 +69,23 @@ std::shared_ptr<VfsFile> VfsDirectory::GetFileAbsolute(const filesystem::path& p
return GetParentDirectory()->GetFileAbsolute(path);
}
std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(const filesystem::path& path) const {
return "";
std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(
const filesystem::path& path) const {
if (path.parent_path() == path.root_path())
return GetSubdirectory(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->GetDirectoryRelative(path.root_path().string() + rest);
}
std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryAbsolute(const filesystem::path& path) const {
std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryAbsolute(
const filesystem::path& path) const {
if (IsRoot())
return GetDirectoryRelative(path);
@@ -113,6 +125,23 @@ size_t VfsDirectory::GetSize() const {
return file_total + subdir_total;
}
bool VfsDirectory::DeleteSubdirectoryRecursive(const std::string& name) {
auto dir = GetSubdirectory(name);
if (dir == nullptr)
return false;
bool success = true;
for (const auto& file : dir->GetFiles())
if (!DeleteFile(file->GetName()))
success = false;
for (const auto& sdir : dir->GetSubdirectories())
if (!dir->DeleteSubdirectoryRecursive(sdir->GetName()))
success = false;
return success;
}
bool VfsDirectory::Copy(const std::string& src, const std::string& dest) {
const auto f1 = CreateFile(src);
auto f2 = CreateFile(dest);

View File

@@ -119,6 +119,7 @@ struct VfsDirectory : NonCopyable {
virtual std::shared_ptr<VfsFile> CreateFile(const std::string& name) = 0;
virtual bool DeleteSubdirectory(const std::string& name) = 0;
virtual bool DeleteSubdirectoryRecursive(const std::string& name);
virtual bool DeleteFile(const std::string& name) = 0;
virtual bool Rename(const std::string& name) = 0;

View File

@@ -7,17 +7,21 @@
namespace FileSys {
static const char* PermissionsToCharArray(filesystem::perms perms) {
static std::string PermissionsToCharArray(filesystem::perms perms) {
std::string out;
if ((perms & filesystem::perms::owner_read) != filesystem::perms::none)
out += "r";
if ((perms & filesystem::perms::owner_write) != filesystem::perms::none)
out += "w";
return out.c_str();
out += "+";
if (out == "+")
out = "w";
return out + "b";
}
RealVfsFile::RealVfsFile(const filesystem::path& path_, filesystem::perms perms_)
: backing(path_.string(), PermissionsToCharArray(perms_)), path(path_), perms(perms_) {}
: backing(path_.string(), PermissionsToCharArray(perms_).c_str()), path(path_), perms(perms_) {
path.make_preferred();
}
std::string RealVfsFile::GetName() const {
return path.filename().string();
@@ -58,12 +62,13 @@ size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) {
bool RealVfsFile::Rename(const std::string& name) {
const auto out = FileUtil::Rename(GetName(), name);
path = path.parent_path() / name;
backing = FileUtil::IOFile(path.string(), PermissionsToCharArray(perms));
backing = FileUtil::IOFile(path.string(), PermissionsToCharArray(perms).c_str());
return out;
}
RealVfsDirectory::RealVfsDirectory(const filesystem::path& path_, filesystem::perms perms_)
: path(path_), perms(perms_) {
path.make_preferred();
for (const auto& entry : filesystem::directory_iterator(path)) {
if (filesystem::is_directory(entry.path()))
subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(entry.path(), perms));

View File

@@ -11,7 +11,8 @@
namespace FileSys {
struct RealVfsFile : public VfsFile {
RealVfsFile(const filesystem::path& name, filesystem::perms perms);
RealVfsFile(const filesystem::path& name,
filesystem::perms perms = filesystem::perms::owner_read);
std::string GetName() const override;
size_t GetSize() const override;

View File

@@ -621,7 +621,7 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
FileSys::Path unused;
auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData, unused);
auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData);
if (savedata.Failed()) {
// Create the save data and return an error indicating that the operation was performed.
FileSystem::FormatFileSystem(FileSystem::Type::SaveData);

View File

@@ -7,116 +7,132 @@
#include "common/file_util.h"
#include "core/file_sys/filesystem.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_offset.h"
#include "core/file_sys/vfs_real.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_srv.h"
namespace Service::FileSystem {
VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(v_dir backing_) : backing(backing_) { }
VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(v_dir backing_) : backing(backing_) {}
std::string VfsDirectoryServiceWrapper::GetName() const {
return backing->GetName();
}
// TODO(DarkLordZach): Verify path usage.
ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 size) const {
filesystem::path s_path(path);
auto dir = backing->GetDirectoryRelative(s_path.parent_path());
auto file = dir->CreateFile(path.filename().string());
if (file == nullptr) return ResultCode(-1);
if (!file->Resize(size)) return ResultCode(-1);
auto file = dir->CreateFile(s_path.filename().string());
if (file == nullptr)
return ResultCode(-1);
if (!file->Resize(size))
return ResultCode(-1);
return RESULT_SUCCESS;
}
// TODO(DarkLordZach): Verify path usage.
ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const {
filesystem::path s_path(path);
auto dir = backing->GetDirectoryRelative(s_path.parent_path());
if (!backing->DeleteFile(s_path.filename().string())) return ResultCode(-1);
if (!backing->DeleteFile(s_path.filename().string()))
return ResultCode(-1);
return RESULT_SUCCESS;
}
// TODO(DarkLordZach): Verify path usage.
ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) const {
filesystem::path s_path(path);
auto dir = backing->GetDirectoryRelative(s_path.parent_path());
auto new_dir = dir->CreateSubdirectory(path.filename().name);
if (new_dir == nullptr) return ResultCode(-1);
auto new_dir = dir->CreateSubdirectory(s_path.filename().string());
if (new_dir == nullptr)
return ResultCode(-1);
return RESULT_SUCCESS;
}
// TODO(DarkLordZach): Verify path usage.
ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) const {
filesystem::path s_path(path);
auto dir = backing->GetDirectoryRelative(s_path.parent_path());
if (!dir->DeleteSubdirectory(path.filename().string())) return ResultCode(-1);
if (!dir->DeleteSubdirectory(s_path.filename().string()))
return ResultCode(-1);
return RESULT_SUCCESS;
}
// TODO(DarkLordZach): Verify path usage.
ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path) const {
filesystem::path s_path(path);
auto dir = backing->GetDirectoryRelative(s_path.parent_path());
if (!dir->DeleteSubdirectoryRecursive(path.filename().string())) return ResultCode(-1);
if (!dir->DeleteSubdirectoryRecursive(s_path.filename().string()))
return ResultCode(-1);
return RESULT_SUCCESS;
}
// TODO(DarkLordZach): Verify path usage.
ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path, const std::string& dest_path) const {
ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path,
const std::string& dest_path) const {
filesystem::path s_path(src_path);
auto file = backing->GetFileRelative(s_path);
file->GetContainingDirectory()->DeleteFile(file->GetName());
auto res_code = CreateFile(dest_path, file->GetSize());
if (res_code != RESULT_SUCCESS) return res_code;
if (res_code != RESULT_SUCCESS)
return res_code;
auto file2 = backing->GetFileRelative(filesystem::path(dest_path));
if (file2->WriteBytes(file->ReadAllBytes() != file->GetSize()) return ResultCode(-1);
if (file2->WriteBytes(file->ReadAllBytes()) != file->GetSize())
return ResultCode(-1);
return RESULT_SUCCESS;
}
// TODO(DarkLordZach): Verify path usage.
ResultCode
VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path, const std::string& dest_path) const {
ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path,
const std::string& dest_path) const {
filesystem::path s_path(src_path);
auto file = backing->GetFileRelative(s_path);
file->GetContainingDirectory()->DeleteFile(file->GetName());
auto res_code = CreateFile(dest_path, file->GetSize());
if (res_code != RESULT_SUCCESS) return res_code;
if (res_code != RESULT_SUCCESS)
return res_code;
auto file2 = backing->GetFileRelative(filesystem::path(dest_path));
if (file2->WriteBytes(file->ReadAllBytes() != file->GetSize())) return ResultCode(-1);
if (file2->WriteBytes(file->ReadAllBytes()) != file->GetSize())
return ResultCode(-1);
return RESULT_SUCCESS;
}
// TODO(DarkLordZach): Verify path usage.
ResultVal<v_file> VfsDirectoryServiceWrapper::OpenFile(const std::string& path, FileSys::Mode mode) const {
ResultVal<v_file> VfsDirectoryServiceWrapper::OpenFile(const std::string& path,
FileSys::Mode mode) const {
auto file = backing->GetFileRelative(filesystem::path(path));
if (file == nullptr) return ResultVal<v_file>(-1);
if (mode == FileSys::Mode::Append) return MakeResult(std::make_shared<OffsetVfsFile>(file, 0, file->GetSize()));
else if (mode == FileSys::Mode::Write && file->IsWritable()) return file;
else if (mode == FileSys::Mode::Read && file->IsReadable()) return file;
return ResultVal<v_file>(-1);
if (file == nullptr)
return ResultCode(-1);
if (mode == FileSys::Mode::Append)
return MakeResult<v_file>(
std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()));
else if (mode == FileSys::Mode::Write && file->IsWritable())
return MakeResult<v_file>(file);
else if (mode == FileSys::Mode::Read && file->IsReadable())
return MakeResult<v_file>(file);
return ResultCode(-1);
}
// TODO(DarkLordZach): Verify path usage.
ResultVal<v_dir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) const {
auto dir = backing->GetDirectoryRelative(filesystem::path(path));
if (dir == nullptr) return ResultVal<v_dir>(-1);
return MakeResult(RESULT_SUCCESS, dir);
if (dir == nullptr)
return ResultCode(-1);
return MakeResult(dir);
}
u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const {
// TODO(DarkLordZach): Infinite? Actual? Is this actually used productively or...?
if (backing->IsWritable())
return -1;
return 0;
}
// TODO(DarkLordZach): Verify path usage.
ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(const std::string& path) const {
ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
const std::string& path) const {
filesystem::path r_path(path);
auto dir = backing->GetDirectoryRelative(r_path.parent_path());
if (dir == nullptr) return ResultVal<FileSys::EntryType>(-1);
if (dir->GetFile(r_path.filename().string()) != nullptr) return MakeResult(FileSys::EntryType::File);
if (dir->GetSubdirectory(r_path.filename().string()) != nullptr) return MakeResult(FileSys::EntryType::Directory);
return ResultVal<FileSys::EntryType>(-1);
if (dir == nullptr)
return ResultCode(-1);
if (dir->GetFile(r_path.filename().string()) != nullptr)
return MakeResult(FileSys::EntryType::File);
if (dir->GetSubdirectory(r_path.filename().string()) != nullptr)
return MakeResult(FileSys::EntryType::Directory);
return ResultCode(-1);
}
/**
@@ -161,7 +177,8 @@ ResultVal<v_dir> OpenFileSystem(Type type) {
}
ResultVal<v_file> OpenRomFS() {
if (filesystem_romfs == nullptr) return ResultVal<v_file>(-1);
if (filesystem_romfs == nullptr)
return ResultCode(-1);
return MakeResult(filesystem_romfs);
}

View File

@@ -6,6 +6,7 @@
#include <memory>
#include "common/common_types.h"
#include "core/file_sys/filesystem.h"
#include "core/file_sys/vfs.h"
#include "core/hle/result.h"
@@ -121,10 +122,6 @@ public:
ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const;
};
class VfsFileServiceWrapper {
v_file backing;
};
/**
* Registers a FileSystem, instances of which can later be opened using its IdCode.
* @param factory FileSystem backend interface to use

View File

@@ -137,8 +137,10 @@ private:
return;
}
std::vector<u8> data = ctx.ReadBuffer();
data.resize(length);
// Write the data to the Storage backend
auto res = MakeResult<size_t>(backend->WriteBytes(ctx.ReadBuffer(), length, offset));
auto res = MakeResult<size_t>(backend->WriteBytes(data, offset));
if (res.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res.Code());
@@ -180,17 +182,37 @@ private:
class IDirectory final : public ServiceFramework<IDirectory> {
public:
explicit IDirectory(std::unique_ptr<FileSys::DirectoryBackend>&& backend)
: ServiceFramework("IDirectory"), backend(std::move(backend)) {
explicit IDirectory(v_dir backend_) : ServiceFramework("IDirectory"), backend(backend_) {
static const FunctionInfo functions[] = {
{0, &IDirectory::Read, "Read"},
{1, &IDirectory::GetEntryCount, "GetEntryCount"},
};
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);
}
}
private:
std::unique_ptr<FileSys::DirectoryBackend> backend;
v_dir backend;
std::vector<FileSys::Entry> entries;
u64 next_entry_index = 0;
void Read(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -201,26 +223,29 @@ private:
// Calculate how many entries we can fit in the output buffer
u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry);
// Cap at total number of entries.
u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index);
// Read the data from the Directory backend
std::vector<FileSys::Entry> entries(count_entries);
u64 read_entries = backend->Read(count_entries, entries.data());
std::vector<FileSys::Entry> entry_data(entries.begin() + next_entry_index,
entries.begin() + next_entry_index + actual_entries);
// Convert the data into a byte array
std::vector<u8> output(entries.size() * sizeof(FileSys::Entry));
std::memcpy(output.data(), entries.data(), output.size());
std::vector<u8> output(entry_data.size() * sizeof(FileSys::Entry));
std::memcpy(output.data(), entry_data.data(), output.size());
// Write the data to memory
ctx.WriteBuffer(output);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(read_entries);
rb.Push(actual_entries);
}
void GetEntryCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
u64 count = backend->GetEntryCount();
u64 count = entries.size() - next_entry_index;
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -265,12 +290,7 @@ public:
LOG_DEBUG(Service_FS, "called file {} mode 0x{:X} size 0x{:08X}", name, mode, size);
IPC::ResponseBuilder rb{ctx, 2};
auto b1 = backend->CreateFile(name);
if (b1 == nullptr) {
}
auto b2 = b1->Res
rb.Push(? RESULT_SUCCESS : ResultCode(-1));
rb.Push(backend.CreateFile(name, size));
}
void DeleteFile(Kernel::HLERequestContext& ctx) {
@@ -282,7 +302,7 @@ public:
LOG_DEBUG(Service_FS, "called file {}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->DeleteFile(name));
rb.Push(backend.DeleteFile(name));
}
void CreateDirectory(Kernel::HLERequestContext& ctx) {
@@ -294,8 +314,7 @@ public:
LOG_DEBUG(Service_FS, "called directory {}", name);
IPC::ResponseBuilder rb{ctx, 2};
auto dir = backend->CreateSubdirectory(name);
rb.Push(dir == nullptr ? -1 : 0);
rb.Push(backend.CreateDirectory(name));
}
void RenameFile(Kernel::HLERequestContext& ctx) {
@@ -313,7 +332,7 @@ public:
LOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->RenameFile(src_name, dst_name));
rb.Push(backend.RenameFile(src_name, dst_name));
}
void OpenFile(Kernel::HLERequestContext& ctx) {
@@ -326,14 +345,14 @@ public:
LOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode));
auto result = backend->OpenFile(name, mode);
auto result = backend.OpenFile(name, mode);
if (result.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result.Code());
return;
}
auto file = std::move(result.Unwrap());
IFile file(result.Unwrap());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -351,14 +370,14 @@ public:
LOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags);
auto result = backend->OpenDirectory(name);
auto result = backend.OpenDirectory(name);
if (result.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result.Code());
return;
}
auto directory = std::move(result.Unwrap());
IDirectory directory(result.Unwrap());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -373,7 +392,7 @@ public:
LOG_DEBUG(Service_FS, "called file {}", name);
auto result = backend->GetEntryType(name);
auto result = backend.GetEntryType(name);
if (result.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result.Code());
@@ -393,7 +412,7 @@ public:
}
private:
v_dir backend;
VfsDirectoryServiceWrapper backend;
};
FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
@@ -510,7 +529,7 @@ void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) {
void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
auto filesystem = OpenFileSystem(Type::SDMC).Unwrap();
IFileSystem filesystem(OpenFileSystem(Type::SDMC).Unwrap());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -533,8 +552,7 @@ void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {
void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called");
FileSys::Path unused;
auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap();
IFileSystem filesystem(OpenFileSystem(Type::SaveData).Unwrap());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -561,9 +579,11 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
return;
}
IStorage storage(romfs);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IStorage>(std::move(storage.Unwrap()));
rb.PushIpcInterface<IStorage>(std::move(storage));
}
void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {

View File

@@ -102,27 +102,19 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
metadata.GetMainThreadStackSize());
// Find the RomFS by searching for a ".romfs" file in this directory
const auto romfs_iter =
std::find_if(dir->GetFiles().begin(), dir->GetFiles().end(), [](const v_file& file) {
return file->GetName().find(".romfs") != std::string::npos;
});
const auto& files = dir->GetFiles();
const auto romfs_iter = std::find_if(files.begin(), files.end(), [](const v_file& file) {
return file->GetName().find(".romfs") != std::string::npos;
});
// TODO(DarkLordZach): Identify RomFS if its a subdirectory.
romfs = (romfs_iter == dir->GetFiles().end()) ? nullptr : *romfs_iter;
const auto romfs = (romfs_iter == files.end()) ? nullptr : *romfs_iter;
if (romfs != nullptr)
Service::FileSystem::RegisterRomFS(romfs);
is_loaded = true;
return ResultStatus::Success;
}
ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(v_file& file) {
if (romfs == nullptr) {
LOG_DEBUG(Loader, "No RomFS available");
return ResultStatus::ErrorNotUsed;
}
file = romfs;
return ResultStatus::Success;
}
} // namespace Loader

View File

@@ -35,10 +35,7 @@ public:
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
ResultStatus ReadRomFS(v_file& file) override;
private:
v_file romfs;
FileSys::ProgramMetadata metadata;
};

View File

@@ -6,6 +6,7 @@
#include <string>
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/file_sys/vfs_real.h"
#include "core/hle/kernel/process.h"
#include "core/loader/deconstructed_rom_directory.h"
#include "core/loader/elf.h"
@@ -41,25 +42,19 @@ FileType IdentifyFile(v_file file) {
}
FileType IdentifyFile(const std::string& file_name) {
FileUtil::IOFile file(file_name, "rb");
if (!file.IsOpen()) {
LOG_ERROR(Loader, "Failed to load file {}", file_name);
return FileType::Unknown;
}
return IdentifyFile(file, file_name);
return IdentifyFile(v_file(std::make_shared<FileSys::RealVfsFile>(file_name)));
}
FileType GuessFromExtension(const std::string& extension_) {
std::string extension = Common::ToLower(extension_);
if (extension == ".elf")
if (extension == "elf")
return FileType::ELF;
else if (extension == ".nro")
else if (extension == "nro")
return FileType::NRO;
else if (extension == ".nso")
else if (extension == "nso")
return FileType::NSO;
else if (extension == ".nca")
else if (extension == "nca")
return FileType::NCA;
return FileType::Unknown;

View File

@@ -37,10 +37,9 @@ enum class FileType {
/**
* Identifies the type of a bootable file based on the magic value in its header.
* @param file open file
* @param filepath Path of the file that we are opening.
* @return FileType of file
*/
FileType IdentifyFile(FileUtil::IOFile& file, const std::string& filepath);
FileType IdentifyFile(v_file file);
/**
* Identifies the type of a bootable file based on the magic value in its header.
@@ -197,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(const std::string& filename);
std::unique_ptr<AppLoader> GetLoader(v_file file);
} // namespace Loader

View File

@@ -66,6 +66,7 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
"subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
const VAddr load_addr = next_load_addr;
next_load_addr = AppLoader_NSO::LoadModule(exefs->GetFile(module), load_addr);
if (next_load_addr) {
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
@@ -83,18 +84,10 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
metadata.GetMainThreadStackSize());
is_loaded = true;
return ResultStatus::Success;
}
ResultStatus AppLoader_NCA::ReadRomFS(v_file& file) {
const auto romfs = nca->GetRomFS();
if (romfs == nullptr) {
NGLOG_DEBUG(Loader, "No RomFS available");
return ResultStatus::ErrorNotUsed;
}
file = romfs;
if (romfs != nullptr)
Service::FileSystem::RegisterRomFS(romfs);
return ResultStatus::Success;
}

View File

@@ -31,8 +31,6 @@ public:
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
ResultStatus ReadRomFS(v_file& file) override;
~AppLoader_NCA();
private:

View File

@@ -96,6 +96,9 @@ static constexpr u32 PageAlignSize(u32 size) {
}
VAddr AppLoader_NSO::LoadModule(v_file file, VAddr load_base) {
if (file == nullptr)
return {};
if (file->GetSize() < sizeof(NsoHeader))
return {};

View File

@@ -12,6 +12,7 @@
#include "common/common_paths.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/file_sys/vfs_real.h"
#include "core/loader/loader.h"
#include "game_list.h"
#include "game_list_p.h"
@@ -404,7 +405,8 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
bool is_dir = FileUtil::IsDirectory(physical_name);
if (!is_dir &&
(HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name);
std::unique_ptr<Loader::AppLoader> loader =
Loader::GetLoader(std::make_unique<FileSys::RealVfsFile>(physical_name));
if (!loader)
return true;