summaryrefslogtreecommitdiffstats
path: root/src/core/file_sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/file_sys')
-rw-r--r--src/core/file_sys/mode.h9
-rw-r--r--src/core/file_sys/registered_cache.cpp126
-rw-r--r--src/core/file_sys/registered_cache.h6
-rw-r--r--src/core/file_sys/savedata_factory.cpp33
-rw-r--r--src/core/file_sys/savedata_factory.h47
-rw-r--r--src/core/file_sys/vfs_real.cpp30
-rw-r--r--src/core/file_sys/xts_archive.cpp14
7 files changed, 150 insertions, 115 deletions
diff --git a/src/core/file_sys/mode.h b/src/core/file_sys/mode.h
index c95205668..2b4f21073 100644
--- a/src/core/file_sys/mode.h
+++ b/src/core/file_sys/mode.h
@@ -4,6 +4,7 @@
#pragma once
+#include "common/common_funcs.h"
#include "common/common_types.h"
namespace FileSys {
@@ -11,13 +12,11 @@ namespace FileSys {
enum class Mode : u32 {
Read = 1,
Write = 2,
- ReadWrite = 3,
+ ReadWrite = Read | Write,
Append = 4,
- WriteAppend = 6,
+ WriteAppend = Write | Append,
};
-inline u32 operator&(Mode lhs, Mode rhs) {
- return static_cast<u32>(lhs) & static_cast<u32>(rhs);
-}
+DECLARE_ENUM_FLAG_OPERATORS(Mode)
} // namespace FileSys
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 37351c561..f831487dd 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -344,15 +344,18 @@ VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
static std::optional<NcaID> CheckMapForContentRecord(const std::map<u64, CNMT>& map, u64 title_id,
ContentRecordType type) {
- if (map.find(title_id) == map.end())
- return {};
-
- const auto& cnmt = map.at(title_id);
+ const auto cmnt_iter = map.find(title_id);
+ if (cmnt_iter == map.cend()) {
+ return std::nullopt;
+ }
- const auto iter = std::find_if(cnmt.GetContentRecords().begin(), cnmt.GetContentRecords().end(),
+ const auto& cnmt = cmnt_iter->second;
+ const auto& content_records = cnmt.GetContentRecords();
+ const auto iter = std::find_if(content_records.cbegin(), content_records.cend(),
[type](const ContentRecord& rec) { return rec.type == type; });
- if (iter == cnmt.GetContentRecords().end())
- return {};
+ if (iter == content_records.cend()) {
+ return std::nullopt;
+ }
return std::make_optional(iter->nca_id);
}
@@ -467,14 +470,16 @@ VirtualFile RegisteredCache::GetEntryUnparsed(u64 title_id, ContentRecordType ty
std::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
const auto meta_iter = meta.find(title_id);
- if (meta_iter != meta.end())
+ if (meta_iter != meta.cend()) {
return meta_iter->second.GetTitleVersion();
+ }
const auto yuzu_meta_iter = yuzu_meta.find(title_id);
- if (yuzu_meta_iter != yuzu_meta.end())
+ if (yuzu_meta_iter != yuzu_meta.cend()) {
return yuzu_meta_iter->second.GetTitleVersion();
+ }
- return {};
+ return std::nullopt;
}
VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const {
@@ -547,56 +552,6 @@ InstallResult RegisteredCache::InstallEntry(const XCI& xci, bool overwrite_if_ex
return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy);
}
-bool RegisteredCache::RemoveExistingEntry(u64 title_id) {
- const auto delete_nca = [this](const NcaID& id) {
- const auto path = GetRelativePathFromNcaID(id, false, true, false);
-
- if (dir->GetFileRelative(path) == nullptr) {
- return false;
- }
-
- Core::Crypto::SHA256Hash hash{};
- mbedtls_sha256_ret(id.data(), id.size(), hash.data(), 0);
- const auto dirname = fmt::format("000000{:02X}", hash[0]);
-
- const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
-
- const auto res = dir2->DeleteFile(fmt::format("{}.nca", Common::HexToString(id, false)));
-
- return res;
- };
-
- // If an entry exists in the registered cache, remove it
- if (HasEntry(title_id, ContentRecordType::Meta)) {
- LOG_INFO(Loader,
- "Previously installed entry (v{}) for title_id={:016X} detected! "
- "Attempting to remove...",
- GetEntryVersion(title_id).value_or(0), title_id);
- // Get all the ncas associated with the current CNMT and delete them
- const auto meta_old_id =
- GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{});
- const auto program_id =
- GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{});
- const auto data_id =
- GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{});
- const auto control_id =
- GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{});
- const auto html_id =
- GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{});
- const auto legal_id =
- GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{});
-
- delete_nca(meta_old_id);
- delete_nca(program_id);
- delete_nca(data_id);
- delete_nca(control_id);
- delete_nca(html_id);
- delete_nca(legal_id);
- return true;
- }
- return false;
-}
-
InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists,
const VfsCopyFunction& copy) {
const auto ncas = nsp.GetNCAsCollapsed();
@@ -692,6 +647,57 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
}
+bool RegisteredCache::RemoveExistingEntry(u64 title_id) const {
+ const auto delete_nca = [this](const NcaID& id) {
+ const auto path = GetRelativePathFromNcaID(id, false, true, false);
+
+ const bool isFile = dir->GetFileRelative(path) != nullptr;
+ const bool isDir = dir->GetDirectoryRelative(path) != nullptr;
+
+ if (isFile) {
+ return dir->DeleteFile(path);
+ } else if (isDir) {
+ return dir->DeleteSubdirectoryRecursive(path);
+ }
+
+ return false;
+ };
+
+ // If an entry exists in the registered cache, remove it
+ if (HasEntry(title_id, ContentRecordType::Meta)) {
+ LOG_INFO(Loader,
+ "Previously installed entry (v{}) for title_id={:016X} detected! "
+ "Attempting to remove...",
+ GetEntryVersion(title_id).value_or(0), title_id);
+
+ // Get all the ncas associated with the current CNMT and delete them
+ const auto meta_old_id =
+ GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{});
+ const auto program_id =
+ GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{});
+ const auto data_id =
+ GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{});
+ const auto control_id =
+ GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{});
+ const auto html_id =
+ GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{});
+ const auto legal_id =
+ GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{});
+
+ const auto deleted_meta = delete_nca(meta_old_id);
+ const auto deleted_program = delete_nca(program_id);
+ const auto deleted_data = delete_nca(data_id);
+ const auto deleted_control = delete_nca(control_id);
+ const auto deleted_html = delete_nca(html_id);
+ const auto deleted_legal = delete_nca(legal_id);
+
+ return deleted_meta && (deleted_meta || deleted_program || deleted_data ||
+ deleted_control || deleted_html || deleted_legal);
+ }
+
+ return false;
+}
+
InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy,
bool overwrite_if_exists,
std::optional<NcaID> override_id) {
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index 29cf0d40c..ec1d54f27 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -155,9 +155,6 @@ public:
std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
std::optional<u64> title_id = {}) const override;
- // Removes an existing entry based on title id
- bool RemoveExistingEntry(u64 title_id);
-
// Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
// there is a meta NCA and all of them are accessible.
InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false,
@@ -172,6 +169,9 @@ public:
InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false,
const VfsCopyFunction& copy = &VfsRawCopy);
+ // Removes an existing entry based on title id
+ bool RemoveExistingEntry(u64 title_id) const;
+
private:
template <typename T>
void IterateAllMetadata(std::vector<T>& out,
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index adfd2c1a4..ba4efee3a 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -17,23 +17,23 @@ constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
namespace {
-void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
+void PrintSaveDataAttributeWarnings(SaveDataAttribute meta) {
if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) {
if (meta.zero_1 != 0) {
LOG_WARNING(Service_FS,
- "Possibly incorrect SaveDataDescriptor, type is "
+ "Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x28 is non-zero ({:016X}).",
meta.zero_1);
}
if (meta.zero_2 != 0) {
LOG_WARNING(Service_FS,
- "Possibly incorrect SaveDataDescriptor, type is "
+ "Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x30 is non-zero ({:016X}).",
meta.zero_2);
}
if (meta.zero_3 != 0) {
LOG_WARNING(Service_FS,
- "Possibly incorrect SaveDataDescriptor, type is "
+ "Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x38 is non-zero ({:016X}).",
meta.zero_3);
}
@@ -41,33 +41,32 @@ void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
if (meta.type == SaveDataType::SystemSaveData && meta.title_id != 0) {
LOG_WARNING(Service_FS,
- "Possibly incorrect SaveDataDescriptor, type is SystemSaveData but title_id is "
+ "Possibly incorrect SaveDataAttribute, type is SystemSaveData but title_id is "
"non-zero ({:016X}).",
meta.title_id);
}
if (meta.type == SaveDataType::DeviceSaveData && meta.user_id != u128{0, 0}) {
LOG_WARNING(Service_FS,
- "Possibly incorrect SaveDataDescriptor, type is DeviceSaveData but user_id is "
+ "Possibly incorrect SaveDataAttribute, type is DeviceSaveData but user_id is "
"non-zero ({:016X}{:016X})",
meta.user_id[1], meta.user_id[0]);
}
}
-bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataDescriptor& desc) {
- return desc.type == SaveDataType::CacheStorage || desc.type == SaveDataType::TemporaryStorage ||
+bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataAttribute& attr) {
+ return attr.type == SaveDataType::CacheStorage || attr.type == SaveDataType::TemporaryStorage ||
(space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
- (desc.type == SaveDataType::SaveData || desc.type == SaveDataType::DeviceSaveData) &&
- desc.title_id == 0 && desc.save_id == 0);
+ (attr.type == SaveDataType::SaveData || attr.type == SaveDataType::DeviceSaveData) &&
+ attr.title_id == 0 && attr.save_id == 0);
}
} // Anonymous namespace
-std::string SaveDataDescriptor::DebugInfo() const {
- return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, "
- "save_id={:016X}, "
+std::string SaveDataAttribute::DebugInfo() const {
+ return fmt::format("[title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, type={:02X}, "
"rank={}, index={}]",
- static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id,
+ title_id, user_id[1], user_id[0], save_id, static_cast<u8>(type),
static_cast<u8>(rank), index);
}
@@ -80,8 +79,8 @@ SaveDataFactory::SaveDataFactory(VirtualDir save_directory) : dir(std::move(save
SaveDataFactory::~SaveDataFactory() = default;
ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
- const SaveDataDescriptor& meta) const {
- PrintSaveDataDescriptorWarnings(meta);
+ const SaveDataAttribute& meta) const {
+ PrintSaveDataAttributeWarnings(meta);
const auto save_directory =
GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id);
@@ -98,7 +97,7 @@ ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
}
ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
- const SaveDataDescriptor& meta) const {
+ const SaveDataAttribute& meta) const {
const auto save_directory =
GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id);
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index 991e57aa1..6625bbbd8 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -21,6 +21,7 @@ enum class SaveDataSpaceId : u8 {
TemporaryStorage = 3,
SdCardUser = 4,
ProperSystem = 100,
+ SafeMode = 101,
};
enum class SaveDataType : u8 {
@@ -30,28 +31,50 @@ enum class SaveDataType : u8 {
DeviceSaveData = 3,
TemporaryStorage = 4,
CacheStorage = 5,
+ SystemBcat = 6,
};
enum class SaveDataRank : u8 {
- Primary,
- Secondary,
+ Primary = 0,
+ Secondary = 1,
};
-struct SaveDataDescriptor {
- u64_le title_id;
+enum class SaveDataFlags : u32 {
+ None = (0 << 0),
+ KeepAfterResettingSystemSaveData = (1 << 0),
+ KeepAfterRefurbishment = (1 << 1),
+ KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
+ NeedsSecureDelete = (1 << 3),
+};
+
+struct SaveDataAttribute {
+ u64 title_id;
u128 user_id;
- u64_le save_id;
+ u64 save_id;
SaveDataType type;
SaveDataRank rank;
- u16_le index;
+ u16 index;
INSERT_PADDING_BYTES(4);
- u64_le zero_1;
- u64_le zero_2;
- u64_le zero_3;
+ u64 zero_1;
+ u64 zero_2;
+ u64 zero_3;
std::string DebugInfo() const;
};
-static_assert(sizeof(SaveDataDescriptor) == 0x40, "SaveDataDescriptor has incorrect size.");
+static_assert(sizeof(SaveDataAttribute) == 0x40, "SaveDataAttribute has incorrect size.");
+
+struct SaveDataExtraData {
+ SaveDataAttribute attr;
+ u64 owner_id;
+ s64 timestamp;
+ SaveDataFlags flags;
+ INSERT_PADDING_BYTES(4);
+ s64 available_size;
+ s64 journal_size;
+ s64 commit_id;
+ std::array<u8, 0x190> unused;
+};
+static_assert(sizeof(SaveDataExtraData) == 0x200, "SaveDataExtraData has incorrect size.");
struct SaveDataSize {
u64 normal;
@@ -64,8 +87,8 @@ public:
explicit SaveDataFactory(VirtualDir dir);
~SaveDataFactory();
- ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataDescriptor& meta) const;
- ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataDescriptor& meta) const;
+ ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
+ ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 96ce5957c..0db0091f6 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -18,20 +18,22 @@ static std::string ModeFlagsToString(Mode mode) {
std::string mode_str;
// Calculate the correct open mode for the file.
- if (mode & Mode::Read && mode & Mode::Write) {
- if (mode & Mode::Append)
+ if (True(mode & Mode::Read) && True(mode & Mode::Write)) {
+ if (True(mode & Mode::Append)) {
mode_str = "a+";
- else
+ } else {
mode_str = "r+";
+ }
} else {
- if (mode & Mode::Read)
+ if (True(mode & Mode::Read)) {
mode_str = "r";
- else if (mode & Mode::Append)
+ } else if (True(mode & Mode::Append)) {
mode_str = "a";
- else if (mode & Mode::Write)
+ } else if (True(mode & Mode::Write)) {
mode_str = "w";
- else
+ } else {
UNREACHABLE_MSG("Invalid file open mode: {:02X}", static_cast<u8>(mode));
+ }
}
mode_str += "b";
@@ -73,8 +75,9 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
}
}
- if (!FileUtil::Exists(path) && (perms & Mode::WriteAppend) != 0)
+ if (!FileUtil::Exists(path) && True(perms & Mode::WriteAppend)) {
FileUtil::CreateEmptyFile(path);
+ }
auto backing = std::make_shared<FileUtil::IOFile>(path, ModeFlagsToString(perms).c_str());
cache[path] = backing;
@@ -247,11 +250,11 @@ std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const {
}
bool RealVfsFile::IsWritable() const {
- return (perms & Mode::WriteAppend) != 0;
+ return True(perms & Mode::WriteAppend);
}
bool RealVfsFile::IsReadable() const {
- return (perms & Mode::ReadWrite) != 0;
+ return True(perms & Mode::ReadWrite);
}
std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const {
@@ -319,8 +322,9 @@ RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string&
path_components(FileUtil::SplitPathComponents(path)),
parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
perms(perms_) {
- if (!FileUtil::Exists(path) && perms & Mode::WriteAppend)
+ if (!FileUtil::Exists(path) && True(perms & Mode::WriteAppend)) {
FileUtil::CreateDir(path);
+ }
}
RealVfsDirectory::~RealVfsDirectory() = default;
@@ -371,11 +375,11 @@ std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories()
}
bool RealVfsDirectory::IsWritable() const {
- return (perms & Mode::WriteAppend) != 0;
+ return True(perms & Mode::WriteAppend);
}
bool RealVfsDirectory::IsReadable() const {
- return (perms & Mode::ReadWrite) != 0;
+ return True(perms & Mode::ReadWrite);
}
std::string RealVfsDirectory::GetName() const {
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp
index 86e06ccb9..81413c684 100644
--- a/src/core/file_sys/xts_archive.cpp
+++ b/src/core/file_sys/xts_archive.cpp
@@ -70,14 +70,18 @@ NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id)
NAX::~NAX() = default;
Loader::ResultStatus NAX::Parse(std::string_view path) {
- if (file->ReadObject(header.get()) != sizeof(NAXHeader))
+ if (file == nullptr) {
+ return Loader::ResultStatus::ErrorNullFile;
+ }
+ if (file->ReadObject(header.get()) != sizeof(NAXHeader)) {
return Loader::ResultStatus::ErrorBadNAXHeader;
-
- if (header->magic != Common::MakeMagic('N', 'A', 'X', '0'))
+ }
+ if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) {
return Loader::ResultStatus::ErrorBadNAXHeader;
-
- if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size)
+ }
+ if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size) {
return Loader::ResultStatus::ErrorIncorrectNAXFileSize;
+ }
keys.DeriveSDSeedLazy();
std::array<Core::Crypto::Key256, 2> sd_keys{};