summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/file_sys/nca_metadata.cpp11
-rw-r--r--src/core/file_sys/registered_cache.cpp13
-rw-r--r--src/core/file_sys/vfs_real.cpp16
3 files changed, 22 insertions, 18 deletions
diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp
index 234d70199..449244444 100644
--- a/src/core/file_sys/nca_metadata.cpp
+++ b/src/core/file_sys/nca_metadata.cpp
@@ -103,7 +103,10 @@ bool CNMT::UnionRecords(const CNMT& other) {
103std::vector<u8> CNMT::Serialize() const { 103std::vector<u8> CNMT::Serialize() const {
104 const bool has_opt_header = 104 const bool has_opt_header =
105 header.type >= TitleType::Application && header.type <= TitleType::AOC; 105 header.type >= TitleType::Application && header.type <= TitleType::AOC;
106 std::vector<u8> out(sizeof(CNMTHeader) + (has_opt_header ? sizeof(OptionalHeader) : 0)); 106 const auto dead_zone = header.table_offset + sizeof(CNMTHeader);
107 std::vector<u8> out(
108 std::max(sizeof(CNMTHeader) + (has_opt_header ? sizeof(OptionalHeader) : 0), dead_zone) +
109 content_records.size() * sizeof(ContentRecord) + meta_records.size() * sizeof(MetaRecord));
107 memcpy(out.data(), &header, sizeof(CNMTHeader)); 110 memcpy(out.data(), &header, sizeof(CNMTHeader));
108 111
109 // Optional Header 112 // Optional Header
@@ -113,17 +116,11 @@ std::vector<u8> CNMT::Serialize() const {
113 116
114 auto offset = header.table_offset; 117 auto offset = header.table_offset;
115 118
116 const auto dead_zone = offset + sizeof(CNMTHeader) - out.size();
117 if (dead_zone > 0)
118 out.resize(offset + sizeof(CNMTHeader));
119
120 out.resize(out.size() + content_records.size() * sizeof(ContentRecord));
121 for (const auto& rec : content_records) { 119 for (const auto& rec : content_records) {
122 memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(ContentRecord)); 120 memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(ContentRecord));
123 offset += sizeof(ContentRecord); 121 offset += sizeof(ContentRecord);
124 } 122 }
125 123
126 out.resize(out.size() + content_records.size() * sizeof(MetaRecord));
127 for (const auto& rec : meta_records) { 124 for (const auto& rec : meta_records) {
128 memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(MetaRecord)); 125 memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(MetaRecord));
129 offset += sizeof(MetaRecord); 126 offset += sizeof(MetaRecord);
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index e916d5610..a5e935f64 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -29,8 +29,8 @@ static bool FollowsTwoDigitDirFormat(std::string_view name) {
29} 29}
30 30
31static bool FollowsNcaIdFormat(std::string_view name) { 31static bool FollowsNcaIdFormat(std::string_view name) {
32 static const std::regex nca_id_regex("[0-9A-F]{32}.nca", std::regex_constants::ECMAScript | 32 static const std::regex nca_id_regex("[0-9A-F]{32}\\.nca", std::regex_constants::ECMAScript |
33 std::regex_constants::icase); 33 std::regex_constants::icase);
34 return name.size() == 36 && std::regex_match(name.begin(), name.end(), nca_id_regex); 34 return name.size() == 36 && std::regex_match(name.begin(), name.end(), nca_id_regex);
35} 35}
36 36
@@ -59,8 +59,10 @@ static std::string GetCNMTName(TitleType type, u64 title_id) {
59 59
60 auto index = static_cast<size_t>(type); 60 auto index = static_cast<size_t>(type);
61 // If the index is after the jump in TitleType, subtract it out. 61 // If the index is after the jump in TitleType, subtract it out.
62 if (index >= static_cast<size_t>(TitleType::Application)) 62 if (index >= static_cast<size_t>(TitleType::Application)) {
63 index -= 0x7B; 63 index -= static_cast<size_t>(TitleType::Application) -
64 static_cast<size_t>(TitleType::FirmwarePackageB);
65 }
64 return fmt::format("{}_{:016x}.cnmt", TITLE_TYPE_NAMES[index], title_id); 66 return fmt::format("{}_{:016x}.cnmt", TITLE_TYPE_NAMES[index], title_id);
65} 67}
66 68
@@ -96,7 +98,8 @@ VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
96 file = files[0]; 98 file = files[0];
97 } else { 99 } else {
98 std::vector<VirtualFile> concat; 100 std::vector<VirtualFile> concat;
99 for (u8 i = 0; i < 0x10; ++i) { 101 // Since the files are a two-digit hex number, max is FF.
102 for (size_t i = 0; i < 0x100; ++i) {
100 auto next = nca_dir->GetFile(fmt::format("{:02X}", i)); 103 auto next = nca_dir->GetFile(fmt::format("{:02X}", i));
101 if (next != nullptr) { 104 if (next != nullptr) {
102 concat.push_back(std::move(next)); 105 concat.push_back(std::move(next));
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 02cdb039a..0afe515f0 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -84,9 +84,11 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
84VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { 84VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
85 const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); 85 const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
86 const auto path_fwd = FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash); 86 const auto path_fwd = FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash);
87 if (!FileUtil::Exists(path) && !FileUtil::CreateFullPath(path_fwd) && 87 if (!FileUtil::Exists(path)) {
88 !FileUtil::CreateEmptyFile(path)) 88 FileUtil::CreateFullPath(path_fwd);
89 return nullptr; 89 if (!FileUtil::CreateEmptyFile(path))
90 return nullptr;
91 }
90 return OpenFile(path, perms); 92 return OpenFile(path, perms);
91} 93}
92 94
@@ -143,9 +145,11 @@ VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms)
143VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) { 145VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) {
144 const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); 146 const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
145 const auto path_fwd = FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash); 147 const auto path_fwd = FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash);
146 if (!FileUtil::Exists(path) && !FileUtil::CreateFullPath(path_fwd) && 148 if (!FileUtil::Exists(path)) {
147 !FileUtil::CreateEmptyFile(path)) 149 FileUtil::CreateFullPath(path_fwd);
148 return nullptr; 150 if (!FileUtil::CreateDir(path))
151 return nullptr;
152 }
149 // Cannot use make_shared as RealVfsDirectory constructor is private 153 // Cannot use make_shared as RealVfsDirectory constructor is private
150 return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); 154 return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
151} 155}