FS: pass down program ID for archive operation

To eliminate System::GetInstance usage. Archive type like SelfNCCH and SaveData changes the actual reference path for different client, so archive backend interface should accept client information from the service interface. Currently we only pass the program ID as the client information.
This commit is contained in:
Weiyi Wang 2019-02-02 20:14:01 -05:00
parent bad2e084e3
commit a6d9baa05a
24 changed files with 165 additions and 99 deletions

View file

@ -167,24 +167,28 @@ public:
/**
* Tries to open the archive of this type with the specified path
* @param path Path to the archive
* @param program_id the program ID of the client that requests the operation
* @return An ArchiveBackend corresponding operating specified archive path.
*/
virtual ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) = 0;
virtual ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) = 0;
/**
* Deletes the archive contents and then re-creates the base folder
* @param path Path to the archive
* @param format_info Format information for the new archive
* @param program_id the program ID of the client that requests the operation
* @return ResultCode of the operation, 0 on success
*/
virtual ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) = 0;
virtual ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) = 0;
/**
* Retrieves the format info about the archive with the specified path
* @param path Path to the archive
* @param program_id the program ID of the client that requests the operation
* @return Format information about the archive or error code
*/
virtual ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const = 0;
virtual ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const = 0;
};
} // namespace FileSys

View file

@ -220,7 +220,8 @@ Path ArchiveFactory_ExtSaveData::GetCorrectedPath(const Path& path) {
return {binary_data};
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) {
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path,
u64 program_id) {
std::string fullpath = GetExtSaveDataPath(mount_point, GetCorrectedPath(path)) + "user/";
if (!FileUtil::Exists(fullpath)) {
// TODO(Subv): Verify the archive behavior of SharedExtSaveData compared to ExtSaveData.
@ -236,7 +237,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons
}
ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path,
const FileSys::ArchiveFormatInfo& format_info) {
const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) {
auto corrected_path = GetCorrectedPath(path);
// These folders are always created with the ExtSaveData
@ -258,7 +260,8 @@ ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path,
return RESULT_SUCCESS;
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Path& path) const {
ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Path& path,
u64 program_id) const {
std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata";
FileUtil::IOFile file(metadata_path, "rb");

View file

@ -24,9 +24,10 @@ public:
return "ExtSaveData";
}
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
const std::string& GetMountPoint() const {
return mount_point;

View file

@ -269,7 +269,8 @@ bool NCCHFile::SetSize(const u64 size) const {
ArchiveFactory_NCCH::ArchiveFactory_NCCH() {}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path& path) {
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path& path,
u64 program_id) {
if (path.GetType() != LowPathType::Binary) {
LOG_ERROR(Service_FS, "Path need to be Binary");
return ERROR_INVALID_PATH;
@ -290,14 +291,16 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path&
}
ResultCode ArchiveFactory_NCCH::Format(const Path& path,
const FileSys::ArchiveFormatInfo& format_info) {
const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) {
LOG_ERROR(Service_FS, "Attempted to format a NCCH archive.");
// TODO: Verify error code
return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported,
ErrorLevel::Permanent);
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_NCCH::GetFormatInfo(const Path& path) const {
ResultVal<ArchiveFormatInfo> ArchiveFactory_NCCH::GetFormatInfo(const Path& path,
u64 program_id) const {
// TODO(Subv): Implement
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
return ResultCode(-1);

View file

@ -97,9 +97,10 @@ public:
return "NCCH";
}
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
};
} // namespace FileSys

View file

@ -64,7 +64,7 @@ ArchiveFactory_OtherSaveDataPermitted::ArchiveFactory_OtherSaveDataPermitted(
: sd_savedata_source(std::move(sd_savedata)) {}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_OtherSaveDataPermitted::Open(
const Path& path) {
const Path& path, u64 /*client_program_id*/) {
MediaType media_type;
u64 program_id;
CASCADE_RESULT(std::tie(media_type, program_id), ParsePathPermitted(path));
@ -78,13 +78,13 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_OtherSaveDataPermitted
}
ResultCode ArchiveFactory_OtherSaveDataPermitted::Format(
const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
const Path& path, const FileSys::ArchiveFormatInfo& format_info, u64 program_id) {
LOG_ERROR(Service_FS, "Attempted to format a OtherSaveDataPermitted archive.");
return ERROR_INVALID_PATH;
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_OtherSaveDataPermitted::GetFormatInfo(
const Path& path) const {
const Path& path, u64 /*client_program_id*/) const {
MediaType media_type;
u64 program_id;
CASCADE_RESULT(std::tie(media_type, program_id), ParsePathPermitted(path));
@ -102,7 +102,7 @@ ArchiveFactory_OtherSaveDataGeneral::ArchiveFactory_OtherSaveDataGeneral(
: sd_savedata_source(std::move(sd_savedata)) {}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_OtherSaveDataGeneral::Open(
const Path& path) {
const Path& path, u64 /*client_program_id*/) {
MediaType media_type;
u64 program_id;
CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path));
@ -116,7 +116,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_OtherSaveDataGeneral::
}
ResultCode ArchiveFactory_OtherSaveDataGeneral::Format(
const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
const Path& path, const FileSys::ArchiveFormatInfo& format_info, u64 /*client_program_id*/) {
MediaType media_type;
u64 program_id;
CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path));
@ -130,7 +130,7 @@ ResultCode ArchiveFactory_OtherSaveDataGeneral::Format(
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_OtherSaveDataGeneral::GetFormatInfo(
const Path& path) const {
const Path& path, u64 /*client_program_id*/) const {
MediaType media_type;
u64 program_id;
CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path));

View file

@ -21,9 +21,10 @@ public:
return "OtherSaveDataPermitted";
}
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
private:
std::string mount_point;
@ -40,9 +41,10 @@ public:
return "OtherSaveDataGeneral";
}
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
private:
std::string mount_point;

View file

@ -16,20 +16,20 @@ ArchiveFactory_SaveData::ArchiveFactory_SaveData(
std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata)
: sd_savedata_source(std::move(sd_savedata)) {}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) {
return sd_savedata_source->Open(
Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id);
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path,
u64 program_id) {
return sd_savedata_source->Open(program_id);
}
ResultCode ArchiveFactory_SaveData::Format(const Path& path,
const FileSys::ArchiveFormatInfo& format_info) {
return sd_savedata_source->Format(
Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id, format_info);
const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) {
return sd_savedata_source->Format(program_id, format_info);
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const {
return sd_savedata_source->GetFormatInfo(
Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id);
ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path,
u64 program_id) const {
return sd_savedata_source->GetFormatInfo(program_id);
}
} // namespace FileSys

View file

@ -20,10 +20,11 @@ public:
return "SaveData";
}
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
private:
std::string mount_point;

View file

@ -376,18 +376,21 @@ bool ArchiveFactory_SDMC::Initialize() {
return true;
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path) {
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path,
u64 program_id) {
auto archive = std::make_unique<SDMCArchive>(sdmc_directory);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
ResultCode ArchiveFactory_SDMC::Format(const Path& path,
const FileSys::ArchiveFormatInfo& format_info) {
const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) {
// This is kind of an undesirable operation, so let's just ignore it. :)
return RESULT_SUCCESS;
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_SDMC::GetFormatInfo(const Path& path) const {
ResultVal<ArchiveFormatInfo> ArchiveFactory_SDMC::GetFormatInfo(const Path& path,
u64 program_id) const {
// TODO(Subv): Implement
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
return ResultCode(-1);

View file

@ -55,9 +55,10 @@ public:
return "SDMC";
}
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
private:
std::string sdmc_directory;

View file

@ -49,19 +49,22 @@ bool ArchiveFactory_SDMCWriteOnly::Initialize() {
return true;
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMCWriteOnly::Open(const Path& path) {
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMCWriteOnly::Open(const Path& path,
u64 program_id) {
auto archive = std::make_unique<SDMCWriteOnlyArchive>(sdmc_directory);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
ResultCode ArchiveFactory_SDMCWriteOnly::Format(const Path& path,
const FileSys::ArchiveFormatInfo& format_info) {
const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) {
// TODO(wwylele): hwtest this
LOG_ERROR(Service_FS, "Attempted to format a SDMC write-only archive.");
return ResultCode(-1);
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_SDMCWriteOnly::GetFormatInfo(const Path& path) const {
ResultVal<ArchiveFormatInfo> ArchiveFactory_SDMCWriteOnly::GetFormatInfo(const Path& path,
u64 program_id) const {
// TODO(Subv): Implement
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
return ResultCode(-1);

View file

@ -46,9 +46,10 @@ public:
return "SDMCWriteOnly";
}
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
private:
std::string sdmc_directory;

View file

@ -278,18 +278,20 @@ void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) {
data.banner = std::make_shared<std::vector<u8>>(std::move(buffer));
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) {
auto archive = std::make_unique<SelfNCCHArchive>(
ncch_data[Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id]);
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path,
u64 program_id) {
auto archive = std::make_unique<SelfNCCHArchive>(ncch_data[program_id]);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
ResultCode ArchiveFactory_SelfNCCH::Format(const Path&, const FileSys::ArchiveFormatInfo&) {
ResultCode ArchiveFactory_SelfNCCH::Format(const Path&, const FileSys::ArchiveFormatInfo&,
u64 program_id) {
LOG_ERROR(Service_FS, "Attempted to format a SelfNCCH archive.");
return ERROR_INVALID_PATH;
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_SelfNCCH::GetFormatInfo(const Path&) const {
ResultVal<ArchiveFormatInfo> ArchiveFactory_SelfNCCH::GetFormatInfo(const Path&,
u64 program_id) const {
LOG_ERROR(Service_FS, "Attempted to get format info of a SelfNCCH archive");
return ERROR_INVALID_PATH;
}

View file

@ -37,9 +37,10 @@ public:
std::string GetName() const override {
return "SelfNCCH";
}
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
private:
/// Mapping of ProgramId -> NCCHData

View file

@ -52,7 +52,8 @@ Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low) {
ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path)
: base_path(GetSystemSaveDataContainerPath(nand_path)) {}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) {
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path,
u64 program_id) {
std::string fullpath = GetSystemSaveDataPath(base_path, path);
if (!FileUtil::Exists(fullpath)) {
// TODO(Subv): Check error code, this one is probably wrong
@ -63,14 +64,16 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(c
}
ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path,
const FileSys::ArchiveFormatInfo& format_info) {
const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) {
std::string fullpath = GetSystemSaveDataPath(base_path, path);
FileUtil::DeleteDirRecursively(fullpath);
FileUtil::CreateFullPath(fullpath);
return RESULT_SUCCESS;
}
ResultVal<ArchiveFormatInfo> ArchiveFactory_SystemSaveData::GetFormatInfo(const Path& path) const {
ResultVal<ArchiveFormatInfo> ArchiveFactory_SystemSaveData::GetFormatInfo(const Path& path,
u64 program_id) const {
// TODO(Subv): Implement
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
return ResultCode(-1);

View file

@ -20,9 +20,10 @@ class ArchiveFactory_SystemSaveData final : public ArchiveFactory {
public:
explicit ArchiveFactory_SystemSaveData(const std::string& mount_point);
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path, u64 program_id) override;
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) override;
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
std::string GetName() const override {
return "SystemSaveData";

View file

@ -1362,7 +1362,7 @@ Module::Module(Core::System& system) : system(system) {
// Open the SystemSaveData archive 0x00010026
FileSys::Path archive_path(cecd_system_savedata_id);
auto archive_result = systemsavedata_factory.Open(archive_path);
auto archive_result = systemsavedata_factory.Open(archive_path, 0);
// If the archive didn't exist, create the files inside
if (archive_result.Code() != FileSys::ERR_NOT_FORMATTED) {
@ -1370,10 +1370,10 @@ Module::Module(Core::System& system) : system(system) {
cecd_system_save_data_archive = std::move(archive_result).Unwrap();
} else {
// Format the archive to create the directories
systemsavedata_factory.Format(archive_path, FileSys::ArchiveFormatInfo());
systemsavedata_factory.Format(archive_path, FileSys::ArchiveFormatInfo(), 0);
// Open it again to get a valid archive now that the folder exists
cecd_system_save_data_archive = systemsavedata_factory.Open(archive_path).Unwrap();
cecd_system_save_data_archive = systemsavedata_factory.Open(archive_path, 0).Unwrap();
/// Now that the archive is formatted, we need to create the root CEC directory,
/// eventlog.dat, and CEC/MBoxList____

View file

@ -531,15 +531,15 @@ ResultCode Module::LoadConfigNANDSaveFile() {
// Open the SystemSaveData archive 0x00010017
FileSys::Path archive_path(cfg_system_savedata_id);
auto archive_result = systemsavedata_factory.Open(archive_path);
auto archive_result = systemsavedata_factory.Open(archive_path, 0);
// If the archive didn't exist, create the files inside
if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) {
// Format the archive to create the directories
systemsavedata_factory.Format(archive_path, FileSys::ArchiveFormatInfo());
systemsavedata_factory.Format(archive_path, FileSys::ArchiveFormatInfo(), 0);
// Open it again to get a valid archive now that the folder exists
cfg_system_save_data_archive = systemsavedata_factory.Open(archive_path).Unwrap();
cfg_system_save_data_archive = systemsavedata_factory.Open(archive_path, 0).Unwrap();
} else {
ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!");

View file

@ -36,7 +36,7 @@ ArchiveBackend* ArchiveManager::GetArchive(ArchiveHandle handle) {
}
ResultVal<ArchiveHandle> ArchiveManager::OpenArchive(ArchiveIdCode id_code,
FileSys::Path& archive_path) {
FileSys::Path& archive_path, u64 program_id) {
LOG_TRACE(Service_FS, "Opening archive with id code 0x{:08X}", static_cast<u32>(id_code));
auto itr = id_code_map.find(id_code);
@ -44,7 +44,8 @@ ResultVal<ArchiveHandle> ArchiveManager::OpenArchive(ArchiveIdCode id_code,
return FileSys::ERROR_NOT_FOUND;
}
CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res,
itr->second->Open(archive_path, program_id));
// This should never even happen in the first place with 64-bit handles,
while (handle_map.count(next_handle) != 0) {
@ -193,28 +194,29 @@ ResultVal<u64> ArchiveManager::GetFreeBytesInArchive(ArchiveHandle archive_handl
ResultCode ArchiveManager::FormatArchive(ArchiveIdCode id_code,
const FileSys::ArchiveFormatInfo& format_info,
const FileSys::Path& path) {
const FileSys::Path& path, u64 program_id) {
auto archive_itr = id_code_map.find(id_code);
if (archive_itr == id_code_map.end()) {
return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
}
return archive_itr->second->Format(path, format_info);
return archive_itr->second->Format(path, format_info, program_id);
}
ResultVal<FileSys::ArchiveFormatInfo> ArchiveManager::GetArchiveFormatInfo(
ArchiveIdCode id_code, FileSys::Path& archive_path) {
ArchiveIdCode id_code, FileSys::Path& archive_path, u64 program_id) {
auto archive = id_code_map.find(id_code);
if (archive == id_code_map.end()) {
return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
}
return archive->second->GetFormatInfo(archive_path);
return archive->second->GetFormatInfo(archive_path, program_id);
}
ResultCode ArchiveManager::CreateExtSaveData(MediaType media_type, u32 high, u32 low,
const std::vector<u8>& smdh_icon,
const FileSys::ArchiveFormatInfo& format_info) {
const FileSys::ArchiveFormatInfo& format_info,
u64 program_id) {
// Construct the binary path to the archive first
FileSys::Path path =
FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
@ -228,7 +230,7 @@ ResultCode ArchiveManager::CreateExtSaveData(MediaType media_type, u32 high, u32
auto ext_savedata = static_cast<FileSys::ArchiveFactory_ExtSaveData*>(archive->second.get());
ResultCode result = ext_savedata->Format(path, format_info);
ResultCode result = ext_savedata->Format(path, format_info, program_id);
if (result.IsError())
return result;

View file

@ -60,9 +60,11 @@ public:
* Opens an archive
* @param id_code IdCode of the archive to open
* @param archive_path Path to the archive, used with Binary paths
* @param program_id the program ID of the client that requests the operation
* @return Handle to the opened archive
*/
ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path);
ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path,
u64 program_id);
/**
* Closes an archive
@ -172,20 +174,23 @@ public:
* @param id_code The id of the archive to format
* @param format_info Format information about the new archive
* @param path The path to the archive, if relevant.
* @param program_id the program ID of the client that requests the operation
* @return ResultCode 0 on success or the corresponding code on error
*/
ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info,
const FileSys::Path& path = FileSys::Path());
const FileSys::Path& path, u64 program_id);
/**
* Retrieves the format info about the archive of the specified type and path.
* The format info is supplied by the client code when creating archives.
* @param id_code The id of the archive
* @param archive_path The path of the archive, if relevant
* @param program_id the program ID of the client that requests the operation
* @return The format info of the archive, or the corresponding error code if failed.
*/
ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code,
FileSys::Path& archive_path);
FileSys::Path& archive_path,
u64 program_id);
/**
* Creates a blank SharedExtSaveData archive for the specified extdata ID
@ -194,11 +199,12 @@ public:
* @param low The low word of the extdata id to create
* @param smdh_icon the SMDH icon for this ExtSaveData
* @param format_info Format information about the new archive
* @param program_id the program ID of the client that requests the operation
* @return ResultCode 0 on success or the corresponding code on error
*/
ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low,
const std::vector<u8>& smdh_icon,
const FileSys::ArchiveFormatInfo& format_info);
const FileSys::ArchiveFormatInfo& format_info, u64 program_id);
/**
* Deletes the SharedExtSaveData archive for the specified extdata ID

View file

@ -35,7 +35,10 @@ namespace Service::FS {
void FS_USER::Initialize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x0801, 0, 2);
rp.PopPID();
u32 pid = rp.PopPID();
ClientSlot* slot = GetSessionData(ctx.Session());
slot->program_id = system.Kernel().GetProcessById(pid)->codeset->program_id;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
@ -93,7 +96,10 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
ResultVal<ArchiveHandle> archive_handle = archives.OpenArchive(archive_id, archive_path);
ClientSlot* slot = GetSessionData(ctx.Session());
ResultVal<ArchiveHandle> archive_handle =
archives.OpenArchive(archive_id, archive_path, slot->program_id);
if (archive_handle.Failed()) {
LOG_ERROR(Service_FS,
"Failed to get a handle for archive archive_id=0x{:08X} archive_path={}",
@ -309,7 +315,9 @@ void FS_USER::OpenArchive(Kernel::HLERequestContext& ctx) {
archive_path.DebugStr());
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
ResultVal<ArchiveHandle> handle = archives.OpenArchive(archive_id, archive_path);
ClientSlot* slot = GetSessionData(ctx.Session());
ResultVal<ArchiveHandle> handle =
archives.OpenArchive(archive_id, archive_path, slot->program_id);
rb.Push(handle.Code());
if (handle.Succeeded()) {
rb.PushRaw(*handle);
@ -385,7 +393,9 @@ void FS_USER::FormatSaveData(Kernel::HLERequestContext& ctx) {
format_info.number_files = number_files;
format_info.total_size = block_size * 512;
rb.Push(archives.FormatArchive(ArchiveIdCode::SaveData, format_info));
ClientSlot* slot = GetSessionData(ctx.Session());
rb.Push(archives.FormatArchive(ArchiveIdCode::SaveData, format_info, archive_path,
slot->program_id));
}
void FS_USER::FormatThisUserSaveData(Kernel::HLERequestContext& ctx) {
@ -404,7 +414,9 @@ void FS_USER::FormatThisUserSaveData(Kernel::HLERequestContext& ctx) {
format_info.total_size = block_size * 512;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(archives.FormatArchive(ArchiveIdCode::SaveData, format_info));
ClientSlot* slot = GetSessionData(ctx.Session());
rb.Push(archives.FormatArchive(ArchiveIdCode::SaveData, format_info, FileSys::Path(),
slot->program_id));
LOG_TRACE(Service_FS, "called");
}
@ -446,7 +458,9 @@ void FS_USER::CreateExtSaveData(Kernel::HLERequestContext& ctx) {
format_info.total_size = 0;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(archives.CreateExtSaveData(media_type, save_high, save_low, icon, format_info));
ClientSlot* slot = GetSessionData(ctx.Session());
rb.Push(archives.CreateExtSaveData(media_type, save_high, save_low, icon, format_info,
slot->program_id));
rb.PushMappedBuffer(icon_buffer);
LOG_DEBUG(Service_FS,
@ -535,7 +549,10 @@ void FS_USER::CreateLegacySystemSaveData(Kernel::HLERequestContext& ctx) {
void FS_USER::InitializeWithSdkVersion(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x861, 1, 2);
const u32 version = rp.Pop<u32>();
rp.PopPID();
u32 pid = rp.PopPID();
ClientSlot* slot = GetSessionData(ctx.Session());
slot->program_id = system.Kernel().GetProcessById(pid)->codeset->program_id;
LOG_WARNING(Service_FS, "(STUBBED) called, version: 0x{:08X}", version);
@ -595,8 +612,8 @@ void FS_USER::GetFormatInfo(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "archive_path={}", archive_path.DebugStr());
IPC::RequestBuilder rb = rp.MakeBuilder(5, 0);
auto format_info = archives.GetArchiveFormatInfo(archive_id, archive_path);
ClientSlot* slot = GetSessionData(ctx.Session());
auto format_info = archives.GetArchiveFormatInfo(archive_id, archive_path, slot->program_id);
rb.Push(format_info.Code());
if (format_info.Failed()) {
LOG_ERROR(Service_FS, "Failed to retrieve the format info");
@ -664,7 +681,9 @@ void FS_USER::ObsoletedCreateExtSaveData(Kernel::HLERequestContext& ctx) {
format_info.total_size = 0;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(archives.CreateExtSaveData(media_type, save_high, save_low, icon, format_info));
ClientSlot* slot = GetSessionData(ctx.Session());
rb.Push(archives.CreateExtSaveData(media_type, save_high, save_low, icon, format_info,
slot->program_id));
rb.PushMappedBuffer(icon_buffer);
LOG_DEBUG(Service_FS,

View file

@ -15,7 +15,16 @@ namespace Service::FS {
class ArchiveManager;
class FS_USER final : public ServiceFramework<FS_USER> {
struct ClientSlot : public Kernel::SessionRequestHandler::SessionDataBase {
// We retrieves program ID for client process on FS::Initialize(WithSDKVersion)
// Real 3DS matches program ID and process ID based on data registered by loader via fs:REG, so
// theoretically the program ID for FS client and for process codeset can mismatch if the loader
// behaviour is modified. Since we don't emulate fs:REG mechanism, we assume the program ID is
// the same as codeset ID and fetch from there directly.
u64 program_id = 0;
};
class FS_USER final : public ServiceFramework<FS_USER, ClientSlot> {
public:
explicit FS_USER(Core::System& system);

View file

@ -143,16 +143,16 @@ static void WriteGameCoinData(GameCoin gamecoin_data) {
FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true);
FileSys::Path archive_path(ptm_shared_extdata_id);
auto archive_result = extdata_archive_factory.Open(archive_path);
auto archive_result = extdata_archive_factory.Open(archive_path, 0);
std::unique_ptr<FileSys::ArchiveBackend> archive;
FileSys::Path gamecoin_path("/gamecoin.dat");
// If the archive didn't exist, create the files inside
if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) {
// Format the archive to create the directories
extdata_archive_factory.Format(archive_path, FileSys::ArchiveFormatInfo());
extdata_archive_factory.Format(archive_path, FileSys::ArchiveFormatInfo(), 0);
// Open it again to get a valid archive now that the folder exists
archive = extdata_archive_factory.Open(archive_path).Unwrap();
archive = extdata_archive_factory.Open(archive_path, 0).Unwrap();
// Create the game coin file
archive->CreateFile(gamecoin_path, sizeof(GameCoin));
} else {
@ -176,7 +176,7 @@ static GameCoin ReadGameCoinData() {
FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true);
FileSys::Path archive_path(ptm_shared_extdata_id);
auto archive_result = extdata_archive_factory.Open(archive_path);
auto archive_result = extdata_archive_factory.Open(archive_path, 0);
if (!archive_result.Succeeded()) {
LOG_ERROR(Service_PTM, "Could not open the PTM SharedExtSaveData archive!");
return default_game_coin;
@ -205,7 +205,7 @@ Module::Module() {
std::string nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true);
FileSys::Path archive_path(ptm_shared_extdata_id);
auto archive_result = extdata_archive_factory.Open(archive_path);
auto archive_result = extdata_archive_factory.Open(archive_path, 0);
// If the archive didn't exist, write the default game coin file
if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) {
WriteGameCoinData(default_game_coin);