summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/app/src/main/jni/game_metadata.cpp12
-rw-r--r--src/android/app/src/main/jni/native.cpp15
-rw-r--r--src/common/overflow.h1
-rw-r--r--src/core/file_sys/fs_directory.h2
-rw-r--r--src/core/file_sys/fs_file.h14
-rw-r--r--src/core/file_sys/fs_filesystem.h6
-rw-r--r--src/core/file_sys/fs_memory_management.h20
-rw-r--r--src/core/file_sys/fs_operate_range.h4
-rw-r--r--src/core/file_sys/fs_path.h150
-rw-r--r--src/core/file_sys/fs_path_utility.h249
-rw-r--r--src/core/file_sys/fs_string_util.h29
-rw-r--r--src/core/hle/service/filesystem/filesystem.h1
-rw-r--r--src/core/hle/service/glue/time/manager.cpp2
-rw-r--r--src/core/hle/service/glue/time/manager.h2
-rw-r--r--src/core/hle/service/glue/time/time_zone_binary.cpp2
-rw-r--r--src/frontend_common/content_manager.h9
16 files changed, 249 insertions, 269 deletions
diff --git a/src/android/app/src/main/jni/game_metadata.cpp b/src/android/app/src/main/jni/game_metadata.cpp
index 78f604c70..8f0da1413 100644
--- a/src/android/app/src/main/jni/game_metadata.cpp
+++ b/src/android/app/src/main/jni/game_metadata.cpp
@@ -1,12 +1,12 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <core/core.h> 4#include "core/core.h"
5#include <core/file_sys/mode.h> 5#include "core/file_sys/fs_filesystem.h"
6#include <core/file_sys/patch_manager.h> 6#include "core/file_sys/patch_manager.h"
7#include <core/loader/nro.h>
8#include <jni.h>
9#include "core/loader/loader.h" 7#include "core/loader/loader.h"
8#include "core/loader/nro.h"
9#include "jni.h"
10#include "jni/android_common/android_common.h" 10#include "jni/android_common/android_common.h"
11#include "native.h" 11#include "native.h"
12 12
@@ -79,7 +79,7 @@ extern "C" {
79jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj, 79jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj,
80 jstring jpath) { 80 jstring jpath) {
81 const auto file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile( 81 const auto file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
82 GetJString(env, jpath), FileSys::Mode::Read); 82 GetJString(env, jpath), FileSys::OpenMode::Read);
83 if (!file) { 83 if (!file) {
84 return false; 84 return false;
85 } 85 }
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 247f2c2b3..3fd9a500c 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -35,9 +35,10 @@
35#include "core/crypto/key_manager.h" 35#include "core/crypto/key_manager.h"
36#include "core/file_sys/card_image.h" 36#include "core/file_sys/card_image.h"
37#include "core/file_sys/content_archive.h" 37#include "core/file_sys/content_archive.h"
38#include "core/file_sys/fs_filesystem.h"
38#include "core/file_sys/submission_package.h" 39#include "core/file_sys/submission_package.h"
39#include "core/file_sys/vfs.h" 40#include "core/file_sys/vfs/vfs.h"
40#include "core/file_sys/vfs_real.h" 41#include "core/file_sys/vfs/vfs_real.h"
41#include "core/frontend/applets/cabinet.h" 42#include "core/frontend/applets/cabinet.h"
42#include "core/frontend/applets/controller.h" 43#include "core/frontend/applets/controller.h"
43#include "core/frontend/applets/error.h" 44#include "core/frontend/applets/error.h"
@@ -154,7 +155,7 @@ void EmulationSession::SurfaceChanged() {
154} 155}
155 156
156void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath) { 157void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath) {
157 const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::Mode::Read); 158 const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::OpenMode::Read);
158 if (!file) { 159 if (!file) {
159 return; 160 return;
160 } 161 }
@@ -475,8 +476,8 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* en
475 u64 program_id = EmulationSession::GetProgramId(env, jprogramId); 476 u64 program_id = EmulationSession::GetProgramId(env, jprogramId);
476 std::string updatePath = GetJString(env, jupdatePath); 477 std::string updatePath = GetJString(env, jupdatePath);
477 std::shared_ptr<FileSys::NSP> nsp = std::make_shared<FileSys::NSP>( 478 std::shared_ptr<FileSys::NSP> nsp = std::make_shared<FileSys::NSP>(
478 EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(updatePath, 479 EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
479 FileSys::Mode::Read)); 480 updatePath, FileSys::OpenMode::Read));
480 for (const auto& item : nsp->GetNCAs()) { 481 for (const auto& item : nsp->GetNCAs()) {
481 for (const auto& nca_details : item.second) { 482 for (const auto& nca_details : item.second) {
482 if (nca_details.second->GetName().ends_with(".cnmt.nca")) { 483 if (nca_details.second->GetName().ends_with(".cnmt.nca")) {
@@ -719,7 +720,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
719 jobject instance) { 720 jobject instance) {
720 const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir); 721 const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
721 auto vfs_nand_dir = EmulationSession::GetInstance().System().GetFilesystem()->OpenDirectory( 722 auto vfs_nand_dir = EmulationSession::GetInstance().System().GetFilesystem()->OpenDirectory(
722 Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read); 723 Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read);
723 724
724 const auto user_id = EmulationSession::GetInstance().System().GetProfileManager().GetUser( 725 const auto user_id = EmulationSession::GetInstance().System().GetProfileManager().GetUser(
725 static_cast<std::size_t>(0)); 726 static_cast<std::size_t>(0));
@@ -889,7 +890,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j
889 890
890 const auto nandDir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir); 891 const auto nandDir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
891 auto vfsNandDir = system.GetFilesystem()->OpenDirectory(Common::FS::PathToUTF8String(nandDir), 892 auto vfsNandDir = system.GetFilesystem()->OpenDirectory(Common::FS::PathToUTF8String(nandDir),
892 FileSys::Mode::Read); 893 FileSys::OpenMode::Read);
893 894
894 const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( 895 const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
895 {}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, 896 {}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
diff --git a/src/common/overflow.h b/src/common/overflow.h
index e765c0d89..e184ead95 100644
--- a/src/common/overflow.h
+++ b/src/common/overflow.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <algorithm>
6#include <type_traits> 7#include <type_traits>
7#include "bit_cast.h" 8#include "bit_cast.h"
8 9
diff --git a/src/core/file_sys/fs_directory.h b/src/core/file_sys/fs_directory.h
index cba6155f8..25c9cb18a 100644
--- a/src/core/file_sys/fs_directory.h
+++ b/src/core/file_sys/fs_directory.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
diff --git a/src/core/file_sys/fs_file.h b/src/core/file_sys/fs_file.h
index 35f66b959..4fb77e8db 100644
--- a/src/core/file_sys/fs_file.h
+++ b/src/core/file_sys/fs_file.h
@@ -1,12 +1,14 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include "common/common_types.h"
7
6namespace FileSys { 8namespace FileSys {
7 9
8struct ReadOption { 10struct ReadOption {
9 u32 _value; 11 u32 value;
10 12
11 static const ReadOption None; 13 static const ReadOption None;
12}; 14};
@@ -18,7 +20,7 @@ enum ReadOptionFlag : u32 {
18inline constexpr const ReadOption ReadOption::None = {ReadOptionFlag_None}; 20inline constexpr const ReadOption ReadOption::None = {ReadOptionFlag_None};
19 21
20inline constexpr bool operator==(const ReadOption& lhs, const ReadOption& rhs) { 22inline constexpr bool operator==(const ReadOption& lhs, const ReadOption& rhs) {
21 return lhs._value == rhs._value; 23 return lhs.value == rhs.value;
22} 24}
23 25
24inline constexpr bool operator!=(const ReadOption& lhs, const ReadOption& rhs) { 26inline constexpr bool operator!=(const ReadOption& lhs, const ReadOption& rhs) {
@@ -33,10 +35,10 @@ enum WriteOptionFlag : u32 {
33}; 35};
34 36
35struct WriteOption { 37struct WriteOption {
36 u32 _value; 38 u32 value;
37 39
38 constexpr inline bool HasFlushFlag() const { 40 constexpr inline bool HasFlushFlag() const {
39 return _value & WriteOptionFlag_Flush; 41 return value & WriteOptionFlag_Flush;
40 } 42 }
41 43
42 static const WriteOption None; 44 static const WriteOption None;
@@ -47,7 +49,7 @@ inline constexpr const WriteOption WriteOption::None = {WriteOptionFlag_None};
47inline constexpr const WriteOption WriteOption::Flush = {WriteOptionFlag_Flush}; 49inline constexpr const WriteOption WriteOption::Flush = {WriteOptionFlag_Flush};
48 50
49inline constexpr bool operator==(const WriteOption& lhs, const WriteOption& rhs) { 51inline constexpr bool operator==(const WriteOption& lhs, const WriteOption& rhs) {
50 return lhs._value == rhs._value; 52 return lhs.value == rhs.value;
51} 53}
52 54
53inline constexpr bool operator!=(const WriteOption& lhs, const WriteOption& rhs) { 55inline constexpr bool operator!=(const WriteOption& lhs, const WriteOption& rhs) {
diff --git a/src/core/file_sys/fs_filesystem.h b/src/core/file_sys/fs_filesystem.h
index 436d6c731..7f237b7fa 100644
--- a/src/core/file_sys/fs_filesystem.h
+++ b/src/core/file_sys/fs_filesystem.h
@@ -3,6 +3,9 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/common_funcs.h"
7#include "common/common_types.h"
8
6namespace FileSys { 9namespace FileSys {
7 10
8enum class OpenMode : u32 { 11enum class OpenMode : u32 {
@@ -20,9 +23,6 @@ enum class OpenDirectoryMode : u64 {
20 File = (1 << 1), 23 File = (1 << 1),
21 24
22 All = (Directory | File), 25 All = (Directory | File),
23
24 /* TODO: Separate enum, like N? */
25 _NotRequireFileSize = (1 << 31),
26}; 26};
27DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode) 27DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode)
28 28
diff --git a/src/core/file_sys/fs_memory_management.h b/src/core/file_sys/fs_memory_management.h
index 596143ba9..f03c6354b 100644
--- a/src/core/file_sys/fs_memory_management.h
+++ b/src/core/file_sys/fs_memory_management.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
@@ -8,39 +8,31 @@
8 8
9namespace FileSys { 9namespace FileSys {
10 10
11std::mutex g_mutex;
12
13constexpr size_t RequiredAlignment = alignof(u64); 11constexpr size_t RequiredAlignment = alignof(u64);
14 12
15void* AllocateUnsafe(size_t size) { 13void* AllocateUnsafe(size_t size) {
16 /* Allocate. */ 14 // Allocate
17 void* const ptr = ::operator new(size, std::align_val_t{RequiredAlignment}); 15 void* const ptr = ::operator new(size, std::align_val_t{RequiredAlignment});
18 16
19 /* Check alignment. */ 17 // Check alignment
20 ASSERT(Common::IsAligned(reinterpret_cast<uintptr_t>(ptr), RequiredAlignment)); 18 ASSERT(Common::IsAligned(reinterpret_cast<uintptr_t>(ptr), RequiredAlignment));
21 19
22 /* Return allocated pointer. */ 20 // Return allocated pointer
23 return ptr; 21 return ptr;
24} 22}
25 23
26void DeallocateUnsafe(void* ptr, size_t size) { 24void DeallocateUnsafe(void* ptr, size_t size) {
27 /* Deallocate the pointer. */ 25 // Deallocate the pointer
28 ::operator delete(ptr, std::align_val_t{RequiredAlignment}); 26 ::operator delete(ptr, std::align_val_t{RequiredAlignment});
29} 27}
30 28
31void* Allocate(size_t size) { 29void* Allocate(size_t size) {
32 /* Lock the allocator. */
33 std::scoped_lock lk(g_mutex);
34
35 return AllocateUnsafe(size); 30 return AllocateUnsafe(size);
36} 31}
37 32
38void Deallocate(void* ptr, size_t size) { 33void Deallocate(void* ptr, size_t size) {
39 /* If the pointer is non-null, deallocate it. */ 34 // If the pointer is non-null, deallocate it
40 if (ptr != nullptr) { 35 if (ptr != nullptr) {
41 /* Lock the allocator. */
42 std::scoped_lock lk(g_mutex);
43
44 DeallocateUnsafe(ptr, size); 36 DeallocateUnsafe(ptr, size);
45 } 37 }
46} 38}
diff --git a/src/core/file_sys/fs_operate_range.h b/src/core/file_sys/fs_operate_range.h
index 750999907..04ea64cc0 100644
--- a/src/core/file_sys/fs_operate_range.h
+++ b/src/core/file_sys/fs_operate_range.h
@@ -1,8 +1,10 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include "common/common_types.h"
7
6namespace FileSys { 8namespace FileSys {
7 9
8enum class OperationId : s64 { 10enum class OperationId : s64 {
diff --git a/src/core/file_sys/fs_path.h b/src/core/file_sys/fs_path.h
index 9ea452644..56ba08a6a 100644
--- a/src/core/file_sys/fs_path.h
+++ b/src/core/file_sys/fs_path.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
@@ -34,8 +34,7 @@ public:
34 size_t m_length_and_is_normalized; 34 size_t m_length_and_is_normalized;
35 35
36 public: 36 public:
37 constexpr WriteBuffer() : m_buffer(nullptr), m_length_and_is_normalized(0) { /* ... */ 37 constexpr WriteBuffer() : m_buffer(nullptr), m_length_and_is_normalized(0) {}
38 }
39 38
40 constexpr ~WriteBuffer() { 39 constexpr ~WriteBuffer() {
41 if (m_buffer != nullptr) { 40 if (m_buffer != nullptr) {
@@ -113,35 +112,32 @@ private:
113 WriteBuffer m_write_buffer; 112 WriteBuffer m_write_buffer;
114 113
115public: 114public:
116 constexpr Path() : m_str(EmptyPath), m_write_buffer() { 115 constexpr Path() : m_str(EmptyPath), m_write_buffer() {}
117 /* ... */
118 }
119 116
120 constexpr Path(const char* s) : m_str(s), m_write_buffer() { 117 constexpr Path(const char* s) : m_str(s), m_write_buffer() {
121 m_write_buffer.SetNormalized(); 118 m_write_buffer.SetNormalized();
122 } 119 }
123 120
124 constexpr ~Path() { /* ... */ 121 constexpr ~Path() = default;
125 }
126 122
127 constexpr Result SetShallowBuffer(const char* buffer) { 123 constexpr Result SetShallowBuffer(const char* buffer) {
128 /* Check pre-conditions. */ 124 // Check pre-conditions
129 ASSERT(m_write_buffer.GetLength() == 0); 125 ASSERT(m_write_buffer.GetLength() == 0);
130 126
131 /* Check the buffer is valid. */ 127 // Check the buffer is valid
132 R_UNLESS(buffer != nullptr, ResultNullptrArgument); 128 R_UNLESS(buffer != nullptr, ResultNullptrArgument);
133 129
134 /* Set buffer. */ 130 // Set buffer
135 this->SetReadOnlyBuffer(buffer); 131 this->SetReadOnlyBuffer(buffer);
136 132
137 /* Note that we're normalized. */ 133 // Note that we're normalized
138 this->SetNormalized(); 134 this->SetNormalized();
139 135
140 R_SUCCEED(); 136 R_SUCCEED();
141 } 137 }
142 138
143 constexpr const char* GetString() const { 139 constexpr const char* GetString() const {
144 /* Check pre-conditions. */ 140 // Check pre-conditions
145 ASSERT(this->IsNormalized()); 141 ASSERT(this->IsNormalized());
146 142
147 return m_str; 143 return m_str;
@@ -164,69 +160,69 @@ public:
164 } 160 }
165 161
166 Result Initialize(const Path& rhs) { 162 Result Initialize(const Path& rhs) {
167 /* Check the other path is normalized. */ 163 // Check the other path is normalized
168 const bool normalized = rhs.IsNormalized(); 164 const bool normalized = rhs.IsNormalized();
169 R_UNLESS(normalized, ResultNotNormalized); 165 R_UNLESS(normalized, ResultNotNormalized);
170 166
171 /* Allocate buffer for our path. */ 167 // Allocate buffer for our path
172 const auto len = rhs.GetLength(); 168 const auto len = rhs.GetLength();
173 R_TRY(this->Preallocate(len + 1)); 169 R_TRY(this->Preallocate(len + 1));
174 170
175 /* Copy the path. */ 171 // Copy the path
176 const size_t copied = Strlcpy<char>(m_write_buffer.Get(), rhs.GetString(), len + 1); 172 const size_t copied = Strlcpy<char>(m_write_buffer.Get(), rhs.GetString(), len + 1);
177 R_UNLESS(copied == len, ResultUnexpectedInPathA); 173 R_UNLESS(copied == len, ResultUnexpectedInPathA);
178 174
179 /* Set normalized. */ 175 // Set normalized
180 this->SetNormalized(); 176 this->SetNormalized();
181 R_SUCCEED(); 177 R_SUCCEED();
182 } 178 }
183 179
184 Result Initialize(const char* path, size_t len) { 180 Result Initialize(const char* path, size_t len) {
185 /* Check the path is valid. */ 181 // Check the path is valid
186 R_UNLESS(path != nullptr, ResultNullptrArgument); 182 R_UNLESS(path != nullptr, ResultNullptrArgument);
187 183
188 /* Initialize. */ 184 // Initialize
189 R_TRY(this->InitializeImpl(path, len)); 185 R_TRY(this->InitializeImpl(path, len));
190 186
191 /* Set not normalized. */ 187 // Set not normalized
192 this->SetNotNormalized(); 188 this->SetNotNormalized();
193 189
194 R_SUCCEED(); 190 R_SUCCEED();
195 } 191 }
196 192
197 Result Initialize(const char* path) { 193 Result Initialize(const char* path) {
198 /* Check the path is valid. */ 194 // Check the path is valid
199 R_UNLESS(path != nullptr, ResultNullptrArgument); 195 R_UNLESS(path != nullptr, ResultNullptrArgument);
200 196
201 R_RETURN(this->Initialize(path, std::strlen(path))); 197 R_RETURN(this->Initialize(path, std::strlen(path)));
202 } 198 }
203 199
204 Result InitializeWithReplaceBackslash(const char* path) { 200 Result InitializeWithReplaceBackslash(const char* path) {
205 /* Check the path is valid. */ 201 // Check the path is valid
206 R_UNLESS(path != nullptr, ResultNullptrArgument); 202 R_UNLESS(path != nullptr, ResultNullptrArgument);
207 203
208 /* Initialize. */ 204 // Initialize
209 R_TRY(this->InitializeImpl(path, std::strlen(path))); 205 R_TRY(this->InitializeImpl(path, std::strlen(path)));
210 206
211 /* Replace slashes as desired. */ 207 // Replace slashes as desired
212 if (const auto write_buffer_length = m_write_buffer.GetLength(); write_buffer_length > 1) { 208 if (const auto write_buffer_length = m_write_buffer.GetLength(); write_buffer_length > 1) {
213 Replace(m_write_buffer.Get(), write_buffer_length - 1, '\\', '/'); 209 Replace(m_write_buffer.Get(), write_buffer_length - 1, '\\', '/');
214 } 210 }
215 211
216 /* Set not normalized. */ 212 // Set not normalized
217 this->SetNotNormalized(); 213 this->SetNotNormalized();
218 214
219 R_SUCCEED(); 215 R_SUCCEED();
220 } 216 }
221 217
222 Result InitializeWithReplaceForwardSlashes(const char* path) { 218 Result InitializeWithReplaceForwardSlashes(const char* path) {
223 /* Check the path is valid. */ 219 // Check the path is valid
224 R_UNLESS(path != nullptr, ResultNullptrArgument); 220 R_UNLESS(path != nullptr, ResultNullptrArgument);
225 221
226 /* Initialize. */ 222 // Initialize
227 R_TRY(this->InitializeImpl(path, std::strlen(path))); 223 R_TRY(this->InitializeImpl(path, std::strlen(path)));
228 224
229 /* Replace slashes as desired. */ 225 // Replace slashes as desired
230 if (m_write_buffer.GetLength() > 1) { 226 if (m_write_buffer.GetLength() > 1) {
231 if (auto* p = m_write_buffer.Get(); p[0] == '/' && p[1] == '/') { 227 if (auto* p = m_write_buffer.Get(); p[0] == '/' && p[1] == '/') {
232 p[0] = '\\'; 228 p[0] = '\\';
@@ -234,23 +230,23 @@ public:
234 } 230 }
235 } 231 }
236 232
237 /* Set not normalized. */ 233 // Set not normalized
238 this->SetNotNormalized(); 234 this->SetNotNormalized();
239 235
240 R_SUCCEED(); 236 R_SUCCEED();
241 } 237 }
242 238
243 Result InitializeWithNormalization(const char* path, size_t size) { 239 Result InitializeWithNormalization(const char* path, size_t size) {
244 /* Check the path is valid. */ 240 // Check the path is valid
245 R_UNLESS(path != nullptr, ResultNullptrArgument); 241 R_UNLESS(path != nullptr, ResultNullptrArgument);
246 242
247 /* Initialize. */ 243 // Initialize
248 R_TRY(this->InitializeImpl(path, size)); 244 R_TRY(this->InitializeImpl(path, size));
249 245
250 /* Set not normalized. */ 246 // Set not normalized
251 this->SetNotNormalized(); 247 this->SetNotNormalized();
252 248
253 /* Perform normalization. */ 249 // Perform normalization
254 PathFlags path_flags; 250 PathFlags path_flags;
255 if (IsPathRelative(m_str)) { 251 if (IsPathRelative(m_str)) {
256 path_flags.AllowRelativePath(); 252 path_flags.AllowRelativePath();
@@ -269,7 +265,7 @@ public:
269 R_SUCCEED(); 265 R_SUCCEED();
270 } 266 }
271 267
272 /* Normalize. */ 268 // Normalize
273 R_TRY(this->Normalize(path_flags)); 269 R_TRY(this->Normalize(path_flags));
274 270
275 this->SetNormalized(); 271 this->SetNormalized();
@@ -277,30 +273,30 @@ public:
277 } 273 }
278 274
279 Result InitializeWithNormalization(const char* path) { 275 Result InitializeWithNormalization(const char* path) {
280 /* Check the path is valid. */ 276 // Check the path is valid
281 R_UNLESS(path != nullptr, ResultNullptrArgument); 277 R_UNLESS(path != nullptr, ResultNullptrArgument);
282 278
283 R_RETURN(this->InitializeWithNormalization(path, std::strlen(path))); 279 R_RETURN(this->InitializeWithNormalization(path, std::strlen(path)));
284 } 280 }
285 281
286 Result InitializeAsEmpty() { 282 Result InitializeAsEmpty() {
287 /* Clear our buffer. */ 283 // Clear our buffer
288 this->ClearBuffer(); 284 this->ClearBuffer();
289 285
290 /* Set normalized. */ 286 // Set normalized
291 this->SetNormalized(); 287 this->SetNormalized();
292 288
293 R_SUCCEED(); 289 R_SUCCEED();
294 } 290 }
295 291
296 Result AppendChild(const char* child) { 292 Result AppendChild(const char* child) {
297 /* Check the path is valid. */ 293 // Check the path is valid
298 R_UNLESS(child != nullptr, ResultNullptrArgument); 294 R_UNLESS(child != nullptr, ResultNullptrArgument);
299 295
300 /* Basic checks. If we hvea a path and the child is empty, we have nothing to do. */ 296 // Basic checks. If we have a path and the child is empty, we have nothing to do
301 const char* c = child; 297 const char* c = child;
302 if (m_str[0]) { 298 if (m_str[0]) {
303 /* Skip an early separator. */ 299 // Skip an early separator
304 if (*c == '/') { 300 if (*c == '/') {
305 ++c; 301 ++c;
306 } 302 }
@@ -308,40 +304,40 @@ public:
308 R_SUCCEED_IF(*c == '\x00'); 304 R_SUCCEED_IF(*c == '\x00');
309 } 305 }
310 306
311 /* If we don't have a string, we can just initialize. */ 307 // If we don't have a string, we can just initialize
312 auto cur_len = std::strlen(m_str); 308 auto cur_len = std::strlen(m_str);
313 if (cur_len == 0) { 309 if (cur_len == 0) {
314 R_RETURN(this->Initialize(child)); 310 R_RETURN(this->Initialize(child));
315 } 311 }
316 312
317 /* Remove a trailing separator. */ 313 // Remove a trailing separator
318 if (m_str[cur_len - 1] == '/' || m_str[cur_len - 1] == '\\') { 314 if (m_str[cur_len - 1] == '/' || m_str[cur_len - 1] == '\\') {
319 --cur_len; 315 --cur_len;
320 } 316 }
321 317
322 /* Get the child path's length. */ 318 // Get the child path's length
323 auto child_len = std::strlen(c); 319 auto child_len = std::strlen(c);
324 320
325 /* Reset our write buffer. */ 321 // Reset our write buffer
326 WriteBuffer old_write_buffer; 322 WriteBuffer old_write_buffer;
327 if (m_write_buffer.Get() != nullptr) { 323 if (m_write_buffer.Get() != nullptr) {
328 old_write_buffer = std::move(m_write_buffer); 324 old_write_buffer = std::move(m_write_buffer);
329 this->ClearBuffer(); 325 this->ClearBuffer();
330 } 326 }
331 327
332 /* Pre-allocate the new buffer. */ 328 // Pre-allocate the new buffer
333 R_TRY(this->Preallocate(cur_len + 1 + child_len + 1)); 329 R_TRY(this->Preallocate(cur_len + 1 + child_len + 1));
334 330
335 /* Get our write buffer. */ 331 // Get our write buffer
336 auto* dst = m_write_buffer.Get(); 332 auto* dst = m_write_buffer.Get();
337 if (old_write_buffer.Get() != nullptr && cur_len > 0) { 333 if (old_write_buffer.Get() != nullptr && cur_len > 0) {
338 Strlcpy<char>(dst, old_write_buffer.Get(), cur_len + 1); 334 Strlcpy<char>(dst, old_write_buffer.Get(), cur_len + 1);
339 } 335 }
340 336
341 /* Add separator. */ 337 // Add separator
342 dst[cur_len] = '/'; 338 dst[cur_len] = '/';
343 339
344 /* Copy the child path. */ 340 // Copy the child path
345 const size_t copied = Strlcpy<char>(dst + cur_len + 1, c, child_len + 1); 341 const size_t copied = Strlcpy<char>(dst + cur_len + 1, c, child_len + 1);
346 R_UNLESS(copied == child_len, ResultUnexpectedInPathA); 342 R_UNLESS(copied == child_len, ResultUnexpectedInPathA);
347 343
@@ -353,21 +349,21 @@ public:
353 } 349 }
354 350
355 Result Combine(const Path& parent, const Path& child) { 351 Result Combine(const Path& parent, const Path& child) {
356 /* Get the lengths. */ 352 // Get the lengths
357 const auto p_len = parent.GetLength(); 353 const auto p_len = parent.GetLength();
358 const auto c_len = child.GetLength(); 354 const auto c_len = child.GetLength();
359 355
360 /* Allocate our buffer. */ 356 // Allocate our buffer
361 R_TRY(this->Preallocate(p_len + c_len + 1)); 357 R_TRY(this->Preallocate(p_len + c_len + 1));
362 358
363 /* Initialize as parent. */ 359 // Initialize as parent
364 R_TRY(this->Initialize(parent)); 360 R_TRY(this->Initialize(parent));
365 361
366 /* If we're empty, we can just initialize as child. */ 362 // If we're empty, we can just initialize as child
367 if (this->IsEmpty()) { 363 if (this->IsEmpty()) {
368 R_TRY(this->Initialize(child)); 364 R_TRY(this->Initialize(child));
369 } else { 365 } else {
370 /* Otherwise, we should append the child. */ 366 // Otherwise, we should append the child
371 R_TRY(this->AppendChild(child)); 367 R_TRY(this->AppendChild(child));
372 } 368 }
373 369
@@ -375,7 +371,7 @@ public:
375 } 371 }
376 372
377 Result RemoveChild() { 373 Result RemoveChild() {
378 /* If we don't have a write-buffer, ensure that we have one. */ 374 // If we don't have a write-buffer, ensure that we have one
379 if (m_write_buffer.Get() == nullptr) { 375 if (m_write_buffer.Get() == nullptr) {
380 if (const auto len = std::strlen(m_str); len > 0) { 376 if (const auto len = std::strlen(m_str); len > 0) {
381 R_TRY(this->Preallocate(len)); 377 R_TRY(this->Preallocate(len));
@@ -383,17 +379,17 @@ public:
383 } 379 }
384 } 380 }
385 381
386 /* Check that it's possible for us to remove a child. */ 382 // Check that it's possible for us to remove a child
387 auto* p = m_write_buffer.Get(); 383 auto* p = m_write_buffer.Get();
388 s32 len = std::strlen(p); 384 s32 len = std::strlen(p);
389 R_UNLESS(len != 1 || (p[0] != '/' && p[0] != '.'), ResultNotImplemented); 385 R_UNLESS(len != 1 || (p[0] != '/' && p[0] != '.'), ResultNotImplemented);
390 386
391 /* Handle a trailing separator. */ 387 // Handle a trailing separator
392 if (len > 0 && (p[len - 1] == '\\' || p[len - 1] == '/')) { 388 if (len > 0 && (p[len - 1] == '\\' || p[len - 1] == '/')) {
393 --len; 389 --len;
394 } 390 }
395 391
396 /* Remove the child path segment. */ 392 // Remove the child path segment
397 while ((--len) >= 0 && p[len]) { 393 while ((--len) >= 0 && p[len]) {
398 if (p[len] == '/' || p[len] == '\\') { 394 if (p[len] == '/' || p[len] == '\\') {
399 if (len > 0) { 395 if (len > 0) {
@@ -406,25 +402,25 @@ public:
406 } 402 }
407 } 403 }
408 404
409 /* Check that length remains > 0. */ 405 // Check that length remains > 0
410 R_UNLESS(len > 0, ResultNotImplemented); 406 R_UNLESS(len > 0, ResultNotImplemented);
411 407
412 R_SUCCEED(); 408 R_SUCCEED();
413 } 409 }
414 410
415 Result Normalize(const PathFlags& flags) { 411 Result Normalize(const PathFlags& flags) {
416 /* If we're already normalized, nothing to do. */ 412 // If we're already normalized, nothing to do
417 R_SUCCEED_IF(this->IsNormalized()); 413 R_SUCCEED_IF(this->IsNormalized());
418 414
419 /* Check if we're normalized. */ 415 // Check if we're normalized
420 bool normalized; 416 bool normalized;
421 size_t dummy; 417 size_t dummy;
422 R_TRY(PathFormatter::IsNormalized(std::addressof(normalized), std::addressof(dummy), m_str, 418 R_TRY(PathFormatter::IsNormalized(std::addressof(normalized), std::addressof(dummy), m_str,
423 flags)); 419 flags));
424 420
425 /* If we're not normalized, normalize. */ 421 // If we're not normalized, normalize
426 if (!normalized) { 422 if (!normalized) {
427 /* Determine necessary buffer length. */ 423 // Determine necessary buffer length
428 auto len = m_write_buffer.GetLength(); 424 auto len = m_write_buffer.GetLength();
429 if (flags.IsRelativePathAllowed() && IsPathRelative(m_str)) { 425 if (flags.IsRelativePathAllowed() && IsPathRelative(m_str)) {
430 len += 2; 426 len += 2;
@@ -433,20 +429,20 @@ public:
433 len += 1; 429 len += 1;
434 } 430 }
435 431
436 /* Allocate a new buffer. */ 432 // Allocate a new buffer
437 const size_t size = Common::AlignUp(len, WriteBufferAlignmentLength); 433 const size_t size = Common::AlignUp(len, WriteBufferAlignmentLength);
438 auto buf = WriteBuffer::Make(size); 434 auto buf = WriteBuffer::Make(size);
439 R_UNLESS(buf.Get() != nullptr, ResultAllocationMemoryFailedMakeUnique); 435 R_UNLESS(buf.Get() != nullptr, ResultAllocationMemoryFailedMakeUnique);
440 436
441 /* Normalize into it. */ 437 // Normalize into it
442 R_TRY(PathFormatter::Normalize(buf.Get(), size, m_write_buffer.Get(), 438 R_TRY(PathFormatter::Normalize(buf.Get(), size, m_write_buffer.Get(),
443 m_write_buffer.GetLength(), flags)); 439 m_write_buffer.GetLength(), flags));
444 440
445 /* Set the normalized buffer as our buffer. */ 441 // Set the normalized buffer as our buffer
446 this->SetModifiableBuffer(std::move(buf)); 442 this->SetModifiableBuffer(std::move(buf));
447 } 443 }
448 444
449 /* Set normalized. */ 445 // Set normalized
450 this->SetNormalized(); 446 this->SetNormalized();
451 R_SUCCEED(); 447 R_SUCCEED();
452 } 448 }
@@ -458,19 +454,19 @@ private:
458 } 454 }
459 455
460 void SetModifiableBuffer(WriteBuffer&& buffer) { 456 void SetModifiableBuffer(WriteBuffer&& buffer) {
461 /* Check pre-conditions. */ 457 // Check pre-conditions
462 ASSERT(buffer.Get() != nullptr); 458 ASSERT(buffer.Get() != nullptr);
463 ASSERT(buffer.GetLength() > 0); 459 ASSERT(buffer.GetLength() > 0);
464 ASSERT(Common::IsAligned(buffer.GetLength(), WriteBufferAlignmentLength)); 460 ASSERT(Common::IsAligned(buffer.GetLength(), WriteBufferAlignmentLength));
465 461
466 /* Get whether we're normalized. */ 462 // Get whether we're normalized
467 if (m_write_buffer.IsNormalized()) { 463 if (m_write_buffer.IsNormalized()) {
468 buffer.SetNormalized(); 464 buffer.SetNormalized();
469 } else { 465 } else {
470 buffer.SetNotNormalized(); 466 buffer.SetNotNormalized();
471 } 467 }
472 468
473 /* Set write buffer. */ 469 // Set write buffer
474 m_write_buffer = std::move(buffer); 470 m_write_buffer = std::move(buffer);
475 m_str = m_write_buffer.Get(); 471 m_str = m_write_buffer.Get();
476 } 472 }
@@ -481,14 +477,14 @@ private:
481 } 477 }
482 478
483 Result Preallocate(size_t length) { 479 Result Preallocate(size_t length) {
484 /* Allocate additional space, if needed. */ 480 // Allocate additional space, if needed
485 if (length > m_write_buffer.GetLength()) { 481 if (length > m_write_buffer.GetLength()) {
486 /* Allocate buffer. */ 482 // Allocate buffer
487 const size_t size = Common::AlignUp(length, WriteBufferAlignmentLength); 483 const size_t size = Common::AlignUp(length, WriteBufferAlignmentLength);
488 auto buf = WriteBuffer::Make(size); 484 auto buf = WriteBuffer::Make(size);
489 R_UNLESS(buf.Get() != nullptr, ResultAllocationMemoryFailedMakeUnique); 485 R_UNLESS(buf.Get() != nullptr, ResultAllocationMemoryFailedMakeUnique);
490 486
491 /* Set write buffer. */ 487 // Set write buffer
492 this->SetModifiableBuffer(std::move(buf)); 488 this->SetModifiableBuffer(std::move(buf));
493 } 489 }
494 490
@@ -497,14 +493,14 @@ private:
497 493
498 Result InitializeImpl(const char* path, size_t size) { 494 Result InitializeImpl(const char* path, size_t size) {
499 if (size > 0 && path[0]) { 495 if (size > 0 && path[0]) {
500 /* Pre allocate a buffer for the path. */ 496 // Pre allocate a buffer for the path
501 R_TRY(this->Preallocate(size + 1)); 497 R_TRY(this->Preallocate(size + 1));
502 498
503 /* Copy the path. */ 499 // Copy the path
504 const size_t copied = Strlcpy<char>(m_write_buffer.Get(), path, size + 1); 500 const size_t copied = Strlcpy<char>(m_write_buffer.Get(), path, size + 1);
505 R_UNLESS(copied >= size, ResultUnexpectedInPathA); 501 R_UNLESS(copied >= size, ResultUnexpectedInPathA);
506 } else { 502 } else {
507 /* We can just clear the buffer. */ 503 // We can just clear the buffer
508 this->ClearBuffer(); 504 this->ClearBuffer();
509 } 505 }
510 506
@@ -548,14 +544,14 @@ public:
548}; 544};
549 545
550inline Result SetUpFixedPath(FileSys::Path* out, const char* s) { 546inline Result SetUpFixedPath(FileSys::Path* out, const char* s) {
551 /* Verify the path is normalized. */ 547 // Verify the path is normalized
552 bool normalized; 548 bool normalized;
553 size_t dummy; 549 size_t dummy;
554 R_TRY(PathNormalizer::IsNormalized(std::addressof(normalized), std::addressof(dummy), s)); 550 R_TRY(PathNormalizer::IsNormalized(std::addressof(normalized), std::addressof(dummy), s));
555 551
556 R_UNLESS(normalized, ResultInvalidPathFormat); 552 R_UNLESS(normalized, ResultInvalidPathFormat);
557 553
558 /* Set the fixed path. */ 554 // Set the fixed path
559 R_RETURN(out->SetShallowBuffer(s)); 555 R_RETURN(out->SetShallowBuffer(s));
560} 556}
561 557
diff --git a/src/core/file_sys/fs_path_utility.h b/src/core/file_sys/fs_path_utility.h
index 276445707..e9011d065 100644
--- a/src/core/file_sys/fs_path_utility.h
+++ b/src/core/file_sys/fs_path_utility.h
@@ -1,9 +1,10 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/common_funcs.h"
7#include "common/common_types.h" 8#include "common/common_types.h"
8#include "common/scope_exit.h" 9#include "common/scope_exit.h"
9#include "core/file_sys/fs_directory.h" 10#include "core/file_sys/fs_directory.h"
@@ -14,7 +15,6 @@
14namespace FileSys { 15namespace FileSys {
15 16
16constexpr inline size_t MountNameLengthMax = 15; 17constexpr inline size_t MountNameLengthMax = 15;
17using Result = ::Result;
18 18
19namespace StringTraits { 19namespace StringTraits {
20 20
@@ -57,15 +57,15 @@ constexpr bool IsInvalidCharacterImpl(char c) {
57} // namespace impl 57} // namespace impl
58 58
59constexpr bool IsInvalidCharacter(char c) { 59constexpr bool IsInvalidCharacter(char c) {
60 return impl::IsInvalidCharacterImpl<InvalidCharacters, size(InvalidCharacters)>(c); 60 return impl::IsInvalidCharacterImpl<InvalidCharacters, Common::Size(InvalidCharacters)>(c);
61} 61}
62constexpr bool IsInvalidCharacterForHostName(char c) { 62constexpr bool IsInvalidCharacterForHostName(char c) {
63 return impl::IsInvalidCharacterImpl<InvalidCharactersForHostName, 63 return impl::IsInvalidCharacterImpl<InvalidCharactersForHostName,
64 size(InvalidCharactersForHostName)>(c); 64 Common::Size(InvalidCharactersForHostName)>(c);
65} 65}
66constexpr bool IsInvalidCharacterForMountName(char c) { 66constexpr bool IsInvalidCharacterForMountName(char c) {
67 return impl::IsInvalidCharacterImpl<InvalidCharactersForMountName, 67 return impl::IsInvalidCharacterImpl<InvalidCharactersForMountName,
68 size(InvalidCharactersForMountName)>(c); 68 Common::Size(InvalidCharactersForMountName)>(c);
69} 69}
70 70
71} // namespace StringTraits 71} // namespace StringTraits
@@ -177,14 +177,14 @@ constexpr inline bool IsPathStartWithCurrentDirectory(const char* path) {
177} 177}
178 178
179constexpr inline bool IsSubPath(const char* lhs, const char* rhs) { 179constexpr inline bool IsSubPath(const char* lhs, const char* rhs) {
180 /* Check pre-conditions. */ 180 // Check pre-conditions
181 ASSERT(lhs != nullptr); 181 ASSERT(lhs != nullptr);
182 ASSERT(rhs != nullptr); 182 ASSERT(rhs != nullptr);
183 183
184 /* Import StringTraits names for current scope. */ 184 // Import StringTraits names for current scope
185 using namespace StringTraits; 185 using namespace StringTraits;
186 186
187 /* Special case certain paths. */ 187 // Special case certain paths
188 if (IsUncPath(lhs) && !IsUncPath(rhs)) { 188 if (IsUncPath(lhs) && !IsUncPath(rhs)) {
189 return false; 189 return false;
190 } 190 }
@@ -201,7 +201,7 @@ constexpr inline bool IsSubPath(const char* lhs, const char* rhs) {
201 return true; 201 return true;
202 } 202 }
203 203
204 /* Check subpath. */ 204 // Check subpath
205 for (size_t i = 0; /* ... */; ++i) { 205 for (size_t i = 0; /* ... */; ++i) {
206 if (lhs[i] == NullTerminator) { 206 if (lhs[i] == NullTerminator) {
207 return rhs[i] == DirectorySeparator; 207 return rhs[i] == DirectorySeparator;
@@ -213,7 +213,7 @@ constexpr inline bool IsSubPath(const char* lhs, const char* rhs) {
213 } 213 }
214} 214}
215 215
216/* Path utilities. */ 216// Path utilities
217constexpr inline void Replace(char* dst, size_t dst_size, char old_char, char new_char) { 217constexpr inline void Replace(char* dst, size_t dst_size, char old_char, char new_char) {
218 ASSERT(dst != nullptr); 218 ASSERT(dst != nullptr);
219 for (char* cur = dst; cur < dst + dst_size && *cur; ++cur) { 219 for (char* cur = dst; cur < dst + dst_size && *cur; ++cur) {
@@ -224,10 +224,10 @@ constexpr inline void Replace(char* dst, size_t dst_size, char old_char, char ne
224} 224}
225 225
226constexpr inline Result CheckUtf8(const char* s) { 226constexpr inline Result CheckUtf8(const char* s) {
227 /* Check pre-conditions. */ 227 // Check pre-conditions
228 ASSERT(s != nullptr); 228 ASSERT(s != nullptr);
229 229
230 /* Iterate, checking for utf8-validity. */ 230 // Iterate, checking for utf8-validity
231 while (*s) { 231 while (*s) {
232 char utf8_buf[4] = {}; 232 char utf8_buf[4] = {};
233 233
@@ -242,7 +242,7 @@ constexpr inline Result CheckUtf8(const char* s) {
242 R_SUCCEED(); 242 R_SUCCEED();
243} 243}
244 244
245/* Path formatting. */ 245// Path formatting
246class PathNormalizer { 246class PathNormalizer {
247private: 247private:
248 enum class PathState { 248 enum class PathState {
@@ -256,10 +256,10 @@ private:
256 256
257private: 257private:
258 static constexpr void ReplaceParentDirectoryPath(char* dst, const char* src) { 258 static constexpr void ReplaceParentDirectoryPath(char* dst, const char* src) {
259 /* Use StringTraits names for remainder of scope. */ 259 // Use StringTraits names for remainder of scope
260 using namespace StringTraits; 260 using namespace StringTraits;
261 261
262 /* Start with a dir-separator. */ 262 // Start with a dir-separator
263 dst[0] = DirectorySeparator; 263 dst[0] = DirectorySeparator;
264 264
265 auto i = 1; 265 auto i = 1;
@@ -292,14 +292,14 @@ private:
292 292
293public: 293public:
294 static constexpr bool IsParentDirectoryPathReplacementNeeded(const char* path) { 294 static constexpr bool IsParentDirectoryPathReplacementNeeded(const char* path) {
295 /* Use StringTraits names for remainder of scope. */ 295 // Use StringTraits names for remainder of scope
296 using namespace StringTraits; 296 using namespace StringTraits;
297 297
298 if (path[0] != DirectorySeparator && path[0] != AlternateDirectorySeparator) { 298 if (path[0] != DirectorySeparator && path[0] != AlternateDirectorySeparator) {
299 return false; 299 return false;
300 } 300 }
301 301
302 /* Check to find a parent reference using alternate separators. */ 302 // Check to find a parent reference using alternate separators
303 if (path[0] != NullTerminator && path[1] != NullTerminator && path[2] != NullTerminator) { 303 if (path[0] != NullTerminator && path[1] != NullTerminator && path[2] != NullTerminator) {
304 size_t i; 304 size_t i;
305 for (i = 0; path[i + 3] != NullTerminator; ++path) { 305 for (i = 0; path[i + 3] != NullTerminator; ++path) {
@@ -333,24 +333,24 @@ public:
333 333
334 static constexpr Result IsNormalized(bool* out, size_t* out_len, const char* path, 334 static constexpr Result IsNormalized(bool* out, size_t* out_len, const char* path,
335 bool allow_all_characters = false) { 335 bool allow_all_characters = false) {
336 /* Use StringTraits names for remainder of scope. */ 336 // Use StringTraits names for remainder of scope
337 using namespace StringTraits; 337 using namespace StringTraits;
338 338
339 /* Parse the path. */ 339 // Parse the path
340 auto state = PathState::Start; 340 auto state = PathState::Start;
341 size_t len = 0; 341 size_t len = 0;
342 while (path[len] != NullTerminator) { 342 while (path[len] != NullTerminator) {
343 /* Get the current character. */ 343 // Get the current character
344 const char c = path[len++]; 344 const char c = path[len++];
345 345
346 /* Check the current character is valid. */ 346 // Check the current character is valid
347 if (!allow_all_characters && state != PathState::Start) { 347 if (!allow_all_characters && state != PathState::Start) {
348 R_UNLESS(!IsInvalidCharacter(c), ResultInvalidCharacter); 348 R_UNLESS(!IsInvalidCharacter(c), ResultInvalidCharacter);
349 } 349 }
350 350
351 /* Process depending on current state. */ 351 // Process depending on current state
352 switch (state) { 352 switch (state) {
353 /* Import the PathState enums for convenience. */ 353 // Import the PathState enums for convenience
354 using enum PathState; 354 using enum PathState;
355 355
356 case Start: 356 case Start:
@@ -401,9 +401,9 @@ public:
401 } 401 }
402 } 402 }
403 403
404 /* Check the final state. */ 404 // Check the final state
405 switch (state) { 405 switch (state) {
406 /* Import the PathState enums for convenience. */ 406 // Import the PathState enums for convenience
407 using enum PathState; 407 using enum PathState;
408 case Start: 408 case Start:
409 R_THROW(ResultInvalidPathFormat); 409 R_THROW(ResultInvalidPathFormat);
@@ -421,7 +421,7 @@ public:
421 break; 421 break;
422 } 422 }
423 423
424 /* Set the output length. */ 424 // Set the output length
425 *out_len = len; 425 *out_len = len;
426 R_SUCCEED(); 426 R_SUCCEED();
427 } 427 }
@@ -429,21 +429,21 @@ public:
429 static Result Normalize(char* dst, size_t* out_len, const char* path, size_t max_out_size, 429 static Result Normalize(char* dst, size_t* out_len, const char* path, size_t max_out_size,
430 bool is_windows_path, bool is_drive_relative_path, 430 bool is_windows_path, bool is_drive_relative_path,
431 bool allow_all_characters = false) { 431 bool allow_all_characters = false) {
432 /* Use StringTraits names for remainder of scope. */ 432 // Use StringTraits names for remainder of scope
433 using namespace StringTraits; 433 using namespace StringTraits;
434 434
435 /* Prepare to iterate. */ 435 // Prepare to iterate
436 const char* cur_path = path; 436 const char* cur_path = path;
437 size_t total_len = 0; 437 size_t total_len = 0;
438 438
439 /* If path begins with a separator, check that we're not drive relative. */ 439 // If path begins with a separator, check that we're not drive relative
440 if (cur_path[0] != DirectorySeparator) { 440 if (cur_path[0] != DirectorySeparator) {
441 R_UNLESS(is_drive_relative_path, ResultInvalidPathFormat); 441 R_UNLESS(is_drive_relative_path, ResultInvalidPathFormat);
442 442
443 dst[total_len++] = DirectorySeparator; 443 dst[total_len++] = DirectorySeparator;
444 } 444 }
445 445
446 /* We're going to need to do path replacement, potentially. */ 446 // We're going to need to do path replacement, potentially
447 char* replacement_path = nullptr; 447 char* replacement_path = nullptr;
448 size_t replacement_path_size = 0; 448 size_t replacement_path_size = 0;
449 449
@@ -457,7 +457,7 @@ public:
457 } 457 }
458 }); 458 });
459 459
460 /* Perform path replacement, if necessary. */ 460 // Perform path replacement, if necessary
461 if (IsParentDirectoryPathReplacementNeeded(cur_path)) { 461 if (IsParentDirectoryPathReplacementNeeded(cur_path)) {
462 if (std::is_constant_evaluated()) { 462 if (std::is_constant_evaluated()) {
463 replacement_path_size = EntryNameLengthMax + 1; 463 replacement_path_size = EntryNameLengthMax + 1;
@@ -472,25 +472,24 @@ public:
472 cur_path = replacement_path; 472 cur_path = replacement_path;
473 } 473 }
474 474
475 /* Iterate, normalizing path components. */ 475 // Iterate, normalizing path components
476 bool skip_next_sep = false; 476 bool skip_next_sep = false;
477 size_t i = 0; 477 size_t i = 0;
478 478
479 while (cur_path[i] != NullTerminator) { 479 while (cur_path[i] != NullTerminator) {
480 /* Process a directory separator, if we run into one. */ 480 // Process a directory separator, if we run into one
481 if (cur_path[i] == DirectorySeparator) { 481 if (cur_path[i] == DirectorySeparator) {
482 /* Swallow separators. */ 482 // Swallow separators
483 do { 483 do {
484 ++i; 484 ++i;
485 } while (cur_path[i] == DirectorySeparator); 485 } while (cur_path[i] == DirectorySeparator);
486 486
487 /* Check if we hit end of string. */ 487 // Check if we hit end of string
488 if (cur_path[i] == NullTerminator) { 488 if (cur_path[i] == NullTerminator) {
489 break; 489 break;
490 } 490 }
491 491
492 /* If we aren't skipping the separator, write it, checking that we remain in bounds. 492 // If we aren't skipping the separator, write it, checking that we remain in bounds.
493 */
494 if (!skip_next_sep) { 493 if (!skip_next_sep) {
495 if (total_len + 1 == max_out_size) { 494 if (total_len + 1 == max_out_size) {
496 dst[total_len] = NullTerminator; 495 dst[total_len] = NullTerminator;
@@ -501,15 +500,15 @@ public:
501 dst[total_len++] = DirectorySeparator; 500 dst[total_len++] = DirectorySeparator;
502 } 501 }
503 502
504 /* Don't skip the next separator. */ 503 // Don't skip the next separator
505 skip_next_sep = false; 504 skip_next_sep = false;
506 } 505 }
507 506
508 /* Get the length of the current directory component. */ 507 // Get the length of the current directory component
509 size_t dir_len = 0; 508 size_t dir_len = 0;
510 while (cur_path[i + dir_len] != DirectorySeparator && 509 while (cur_path[i + dir_len] != DirectorySeparator &&
511 cur_path[i + dir_len] != NullTerminator) { 510 cur_path[i + dir_len] != NullTerminator) {
512 /* Check for validity. */ 511 // Check for validity
513 if (!allow_all_characters) { 512 if (!allow_all_characters) {
514 R_UNLESS(!IsInvalidCharacter(cur_path[i + dir_len]), ResultInvalidCharacter); 513 R_UNLESS(!IsInvalidCharacter(cur_path[i + dir_len]), ResultInvalidCharacter);
515 } 514 }
@@ -517,19 +516,19 @@ public:
517 ++dir_len; 516 ++dir_len;
518 } 517 }
519 518
520 /* Handle the current dir component. */ 519 // Handle the current dir component
521 if (IsCurrentDirectory(cur_path + i)) { 520 if (IsCurrentDirectory(cur_path + i)) {
522 skip_next_sep = true; 521 skip_next_sep = true;
523 } else if (IsParentDirectory(cur_path + i)) { 522 } else if (IsParentDirectory(cur_path + i)) {
524 /* We should have just written a separator. */ 523 // We should have just written a separator
525 ASSERT(dst[total_len - 1] == DirectorySeparator); 524 ASSERT(dst[total_len - 1] == DirectorySeparator);
526 525
527 /* We should have started with a separator, for non-windows paths. */ 526 // We should have started with a separator, for non-windows paths
528 if (!is_windows_path) { 527 if (!is_windows_path) {
529 ASSERT(dst[0] == DirectorySeparator); 528 ASSERT(dst[0] == DirectorySeparator);
530 } 529 }
531 530
532 /* Remove the previous component. */ 531 // Remove the previous component
533 if (total_len == 1) { 532 if (total_len == 1) {
534 R_UNLESS(is_windows_path, ResultDirectoryUnobtainable); 533 R_UNLESS(is_windows_path, ResultDirectoryUnobtainable);
535 534
@@ -544,15 +543,15 @@ public:
544 } while ((--total_len) != 0); 543 } while ((--total_len) != 0);
545 } 544 }
546 545
547 /* We should be pointing to a directory separator, for non-windows paths. */ 546 // We should be pointing to a directory separator, for non-windows paths
548 if (!is_windows_path) { 547 if (!is_windows_path) {
549 ASSERT(dst[total_len] == DirectorySeparator); 548 ASSERT(dst[total_len] == DirectorySeparator);
550 } 549 }
551 550
552 /* We should remain in bounds. */ 551 // We should remain in bounds
553 ASSERT(total_len < max_out_size); 552 ASSERT(total_len < max_out_size);
554 } else { 553 } else {
555 /* Copy, possibly truncating. */ 554 // Copy, possibly truncating
556 if (total_len + dir_len + 1 > max_out_size) { 555 if (total_len + dir_len + 1 > max_out_size) {
557 const size_t copy_len = max_out_size - (total_len + 1); 556 const size_t copy_len = max_out_size - (total_len + 1);
558 557
@@ -570,7 +569,7 @@ public:
570 } 569 }
571 } 570 }
572 571
573 /* Advance past the current directory component. */ 572 // Advance past the current directory component
574 i += dir_len; 573 i += dir_len;
575 } 574 }
576 575
@@ -583,22 +582,22 @@ public:
583 dst[0] = DirectorySeparator; 582 dst[0] = DirectorySeparator;
584 } 583 }
585 584
586 /* NOTE: Probable nintendo bug, as max_out_size must be at least total_len + 1 for the null 585 // NOTE: Probable nintendo bug, as max_out_size must be at least total_len + 1 for the null
587 * terminator. */ 586 // terminator.
588 R_UNLESS(max_out_size >= total_len - 1, ResultTooLongPath); 587 R_UNLESS(max_out_size >= total_len - 1, ResultTooLongPath);
589 588
590 dst[total_len] = NullTerminator; 589 dst[total_len] = NullTerminator;
591 590
592 /* Check that the result path is normalized. */ 591 // Check that the result path is normalized
593 bool is_normalized; 592 bool is_normalized;
594 size_t dummy; 593 size_t dummy;
595 R_TRY(IsNormalized(std::addressof(is_normalized), std::addressof(dummy), dst, 594 R_TRY(IsNormalized(std::addressof(is_normalized), std::addressof(dummy), dst,
596 allow_all_characters)); 595 allow_all_characters));
597 596
598 /* Assert that the result path is normalized. */ 597 // Assert that the result path is normalized
599 ASSERT(is_normalized); 598 ASSERT(is_normalized);
600 599
601 /* Set the output length. */ 600 // Set the output length
602 *out_len = total_len; 601 *out_len = total_len;
603 R_SUCCEED(); 602 R_SUCCEED();
604 } 603 }
@@ -607,7 +606,7 @@ public:
607class PathFormatter { 606class PathFormatter {
608private: 607private:
609 static constexpr Result CheckSharedName(const char* name, size_t len) { 608 static constexpr Result CheckSharedName(const char* name, size_t len) {
610 /* Use StringTraits names for remainder of scope. */ 609 // Use StringTraits names for remainder of scope
611 using namespace StringTraits; 610 using namespace StringTraits;
612 611
613 if (len == 1) { 612 if (len == 1) {
@@ -624,7 +623,7 @@ private:
624 } 623 }
625 624
626 static constexpr Result CheckHostName(const char* name, size_t len) { 625 static constexpr Result CheckHostName(const char* name, size_t len) {
627 /* Use StringTraits names for remainder of scope. */ 626 // Use StringTraits names for remainder of scope
628 using namespace StringTraits; 627 using namespace StringTraits;
629 628
630 if (len == 2) { 629 if (len == 2) {
@@ -640,10 +639,10 @@ private:
640 639
641 static constexpr Result CheckInvalidBackslash(bool* out_contains_backslash, const char* path, 640 static constexpr Result CheckInvalidBackslash(bool* out_contains_backslash, const char* path,
642 bool allow_backslash) { 641 bool allow_backslash) {
643 /* Use StringTraits names for remainder of scope. */ 642 // Use StringTraits names for remainder of scope
644 using namespace StringTraits; 643 using namespace StringTraits;
645 644
646 /* Default to no backslashes, so we can just write if we see one. */ 645 // Default to no backslashes, so we can just write if we see one
647 *out_contains_backslash = false; 646 *out_contains_backslash = false;
648 647
649 while (*path != NullTerminator) { 648 while (*path != NullTerminator) {
@@ -670,34 +669,34 @@ public:
670 669
671 static constexpr Result ParseMountName(const char** out, size_t* out_len, char* out_mount_name, 670 static constexpr Result ParseMountName(const char** out, size_t* out_len, char* out_mount_name,
672 size_t out_mount_name_buffer_size, const char* path) { 671 size_t out_mount_name_buffer_size, const char* path) {
673 /* Check pre-conditions. */ 672 // Check pre-conditions
674 ASSERT(path != nullptr); 673 ASSERT(path != nullptr);
675 ASSERT(out_len != nullptr); 674 ASSERT(out_len != nullptr);
676 ASSERT(out != nullptr); 675 ASSERT(out != nullptr);
677 ASSERT((out_mount_name == nullptr) == (out_mount_name_buffer_size == 0)); 676 ASSERT((out_mount_name == nullptr) == (out_mount_name_buffer_size == 0));
678 677
679 /* Use StringTraits names for remainder of scope. */ 678 // Use StringTraits names for remainder of scope
680 using namespace StringTraits; 679 using namespace StringTraits;
681 680
682 /* Determine max mount length. */ 681 // Determine max mount length
683 const auto max_mount_len = 682 const auto max_mount_len =
684 out_mount_name_buffer_size == 0 683 out_mount_name_buffer_size == 0
685 ? MountNameLengthMax + 1 684 ? MountNameLengthMax + 1
686 : std::min(MountNameLengthMax + 1, out_mount_name_buffer_size); 685 : std::min(MountNameLengthMax + 1, out_mount_name_buffer_size);
687 686
688 /* Parse the path until we see a drive separator. */ 687 // Parse the path until we see a drive separator
689 size_t mount_len = 0; 688 size_t mount_len = 0;
690 for (/* ... */; mount_len < max_mount_len && path[mount_len]; ++mount_len) { 689 for (/* ... */; mount_len < max_mount_len && path[mount_len]; ++mount_len) {
691 const char c = path[mount_len]; 690 const char c = path[mount_len];
692 691
693 /* If we see a drive separator, advance, then we're done with the pre-drive separator 692 // If we see a drive separator, advance, then we're done with the pre-drive separator
694 * part of the mount. */ 693 // part of the mount.
695 if (c == DriveSeparator) { 694 if (c == DriveSeparator) {
696 ++mount_len; 695 ++mount_len;
697 break; 696 break;
698 } 697 }
699 698
700 /* If we see a directory separator, we're not in a mount name. */ 699 // If we see a directory separator, we're not in a mount name
701 if (c == DirectorySeparator || c == AlternateDirectorySeparator) { 700 if (c == DirectorySeparator || c == AlternateDirectorySeparator) {
702 *out = path; 701 *out = path;
703 *out_len = 0; 702 *out_len = 0;
@@ -705,19 +704,19 @@ public:
705 } 704 }
706 } 705 }
707 706
708 /* Check to be sure we're actually looking at a mount name. */ 707 // Check to be sure we're actually looking at a mount name
709 if (mount_len <= 2 || path[mount_len - 1] != DriveSeparator) { 708 if (mount_len <= 2 || path[mount_len - 1] != DriveSeparator) {
710 *out = path; 709 *out = path;
711 *out_len = 0; 710 *out_len = 0;
712 R_SUCCEED(); 711 R_SUCCEED();
713 } 712 }
714 713
715 /* Check that all characters in the mount name are allowable. */ 714 // Check that all characters in the mount name are allowable
716 for (size_t i = 0; i < mount_len; ++i) { 715 for (size_t i = 0; i < mount_len; ++i) {
717 R_UNLESS(!IsInvalidCharacterForMountName(path[i]), ResultInvalidCharacter); 716 R_UNLESS(!IsInvalidCharacterForMountName(path[i]), ResultInvalidCharacter);
718 } 717 }
719 718
720 /* Copy out the mount name. */ 719 // Copy out the mount name
721 if (out_mount_name_buffer_size > 0) { 720 if (out_mount_name_buffer_size > 0) {
722 R_UNLESS(mount_len < out_mount_name_buffer_size, ResultTooLongPath); 721 R_UNLESS(mount_len < out_mount_name_buffer_size, ResultTooLongPath);
723 722
@@ -727,7 +726,7 @@ public:
727 out_mount_name[mount_len] = NullTerminator; 726 out_mount_name[mount_len] = NullTerminator;
728 } 727 }
729 728
730 /* Set the output. */ 729 // Set the output
731 *out = path + mount_len; 730 *out = path + mount_len;
732 *out_len = mount_len; 731 *out_len = mount_len;
733 R_SUCCEED(); 732 R_SUCCEED();
@@ -742,21 +741,21 @@ public:
742 char* out_relative, 741 char* out_relative,
743 size_t out_relative_buffer_size, 742 size_t out_relative_buffer_size,
744 const char* path) { 743 const char* path) {
745 /* Check pre-conditions. */ 744 // Check pre-conditions
746 ASSERT(path != nullptr); 745 ASSERT(path != nullptr);
747 ASSERT(out_len != nullptr); 746 ASSERT(out_len != nullptr);
748 ASSERT(out != nullptr); 747 ASSERT(out != nullptr);
749 ASSERT((out_relative == nullptr) == (out_relative_buffer_size == 0)); 748 ASSERT((out_relative == nullptr) == (out_relative_buffer_size == 0));
750 749
751 /* Use StringTraits names for remainder of scope. */ 750 // Use StringTraits names for remainder of scope
752 using namespace StringTraits; 751 using namespace StringTraits;
753 752
754 /* Initialize the output buffer, if we have one. */ 753 // Initialize the output buffer, if we have one
755 if (out_relative_buffer_size > 0) { 754 if (out_relative_buffer_size > 0) {
756 out_relative[0] = NullTerminator; 755 out_relative[0] = NullTerminator;
757 } 756 }
758 757
759 /* Check if the path is relative. */ 758 // Check if the path is relative
760 if (path[0] == Dot && (path[1] == NullTerminator || path[1] == DirectorySeparator || 759 if (path[0] == Dot && (path[1] == NullTerminator || path[1] == DirectorySeparator ||
761 path[1] == AlternateDirectorySeparator)) { 760 path[1] == AlternateDirectorySeparator)) {
762 if (out_relative_buffer_size > 0) { 761 if (out_relative_buffer_size > 0) {
@@ -771,10 +770,10 @@ public:
771 R_SUCCEED(); 770 R_SUCCEED();
772 } 771 }
773 772
774 /* Ensure the path isn't a parent directory. */ 773 // Ensure the path isn't a parent directory
775 R_UNLESS(!(path[0] == Dot && path[1] == Dot), ResultDirectoryUnobtainable); 774 R_UNLESS(!(path[0] == Dot && path[1] == Dot), ResultDirectoryUnobtainable);
776 775
777 /* There was no relative dot path. */ 776 // There was no relative dot path
778 *out = path; 777 *out = path;
779 *out_len = 0; 778 *out_len = 0;
780 R_SUCCEED(); 779 R_SUCCEED();
@@ -782,7 +781,7 @@ public:
782 781
783 static constexpr Result SkipWindowsPath(const char** out, size_t* out_len, bool* out_normalized, 782 static constexpr Result SkipWindowsPath(const char** out, size_t* out_len, bool* out_normalized,
784 const char* path, bool has_mount_name) { 783 const char* path, bool has_mount_name) {
785 /* We're normalized if and only if the parsing doesn't throw ResultNotNormalized(). */ 784 // We're normalized if and only if the parsing doesn't throw ResultNotNormalized()
786 *out_normalized = true; 785 *out_normalized = true;
787 786
788 R_TRY_CATCH(ParseWindowsPath(out, out_len, nullptr, 0, path, has_mount_name)) { 787 R_TRY_CATCH(ParseWindowsPath(out, out_len, nullptr, 0, path, has_mount_name)) {
@@ -801,21 +800,21 @@ public:
801 static constexpr Result ParseWindowsPath(const char** out, size_t* out_len, char* out_win, 800 static constexpr Result ParseWindowsPath(const char** out, size_t* out_len, char* out_win,
802 size_t out_win_buffer_size, const char* path, 801 size_t out_win_buffer_size, const char* path,
803 bool has_mount_name) { 802 bool has_mount_name) {
804 /* Check pre-conditions. */ 803 // Check pre-conditions
805 ASSERT(path != nullptr); 804 ASSERT(path != nullptr);
806 ASSERT(out_len != nullptr); 805 ASSERT(out_len != nullptr);
807 ASSERT(out != nullptr); 806 ASSERT(out != nullptr);
808 ASSERT((out_win == nullptr) == (out_win_buffer_size == 0)); 807 ASSERT((out_win == nullptr) == (out_win_buffer_size == 0));
809 808
810 /* Use StringTraits names for remainder of scope. */ 809 // Use StringTraits names for remainder of scope
811 using namespace StringTraits; 810 using namespace StringTraits;
812 811
813 /* Initialize the output buffer, if we have one. */ 812 // Initialize the output buffer, if we have one
814 if (out_win_buffer_size > 0) { 813 if (out_win_buffer_size > 0) {
815 out_win[0] = NullTerminator; 814 out_win[0] = NullTerminator;
816 } 815 }
817 816
818 /* Handle path start. */ 817 // Handle path start
819 const char* cur_path = path; 818 const char* cur_path = path;
820 if (has_mount_name && path[0] == DirectorySeparator) { 819 if (has_mount_name && path[0] == DirectorySeparator) {
821 if (path[1] == AlternateDirectorySeparator && path[2] == AlternateDirectorySeparator) { 820 if (path[1] == AlternateDirectorySeparator && path[2] == AlternateDirectorySeparator) {
@@ -829,9 +828,9 @@ public:
829 } 828 }
830 } 829 }
831 830
832 /* Handle windows drive. */ 831 // Handle windows drive
833 if (IsWindowsDrive(cur_path)) { 832 if (IsWindowsDrive(cur_path)) {
834 /* Parse up to separator. */ 833 // Parse up to separator
835 size_t win_path_len = WindowsDriveLength; 834 size_t win_path_len = WindowsDriveLength;
836 for (/* ... */; cur_path[win_path_len] != NullTerminator; ++win_path_len) { 835 for (/* ... */; cur_path[win_path_len] != NullTerminator; ++win_path_len) {
837 R_UNLESS(!IsInvalidCharacter(cur_path[win_path_len]), ResultInvalidCharacter); 836 R_UNLESS(!IsInvalidCharacter(cur_path[win_path_len]), ResultInvalidCharacter);
@@ -842,13 +841,13 @@ public:
842 } 841 }
843 } 842 }
844 843
845 /* Ensure that we're normalized, if we're required to be. */ 844 // Ensure that we're normalized, if we're required to be
846 if (out_win_buffer_size == 0) { 845 if (out_win_buffer_size == 0) {
847 for (size_t i = 0; i < win_path_len; ++i) { 846 for (size_t i = 0; i < win_path_len; ++i) {
848 R_UNLESS(cur_path[i] != AlternateDirectorySeparator, ResultNotNormalized); 847 R_UNLESS(cur_path[i] != AlternateDirectorySeparator, ResultNotNormalized);
849 } 848 }
850 } else { 849 } else {
851 /* Ensure we can copy into the normalized buffer. */ 850 // Ensure we can copy into the normalized buffer
852 R_UNLESS(win_path_len < out_win_buffer_size, ResultTooLongPath); 851 R_UNLESS(win_path_len < out_win_buffer_size, ResultTooLongPath);
853 852
854 for (size_t i = 0; i < win_path_len; ++i) { 853 for (size_t i = 0; i < win_path_len; ++i) {
@@ -864,7 +863,7 @@ public:
864 R_SUCCEED(); 863 R_SUCCEED();
865 } 864 }
866 865
867 /* Handle DOS device. */ 866 // Handle DOS device
868 if (IsDosDevicePath(cur_path)) { 867 if (IsDosDevicePath(cur_path)) {
869 size_t dos_prefix_len = DosDevicePathPrefixLength; 868 size_t dos_prefix_len = DosDevicePathPrefixLength;
870 869
@@ -875,7 +874,7 @@ public:
875 } 874 }
876 875
877 if (out_win_buffer_size > 0) { 876 if (out_win_buffer_size > 0) {
878 /* Ensure we can copy into the normalized buffer. */ 877 // Ensure we can copy into the normalized buffer
879 R_UNLESS(dos_prefix_len < out_win_buffer_size, ResultTooLongPath); 878 R_UNLESS(dos_prefix_len < out_win_buffer_size, ResultTooLongPath);
880 879
881 for (size_t i = 0; i < dos_prefix_len; ++i) { 880 for (size_t i = 0; i < dos_prefix_len; ++i) {
@@ -891,7 +890,7 @@ public:
891 R_SUCCEED(); 890 R_SUCCEED();
892 } 891 }
893 892
894 /* Handle UNC path. */ 893 // Handle UNC path
895 if (IsUncPath(cur_path, false, true)) { 894 if (IsUncPath(cur_path, false, true)) {
896 const char* final_path = cur_path; 895 const char* final_path = cur_path;
897 896
@@ -932,13 +931,13 @@ public:
932 931
933 size_t unc_prefix_len = final_path - cur_path; 932 size_t unc_prefix_len = final_path - cur_path;
934 933
935 /* Ensure that we're normalized, if we're required to be. */ 934 // Ensure that we're normalized, if we're required to be
936 if (out_win_buffer_size == 0) { 935 if (out_win_buffer_size == 0) {
937 for (size_t i = 0; i < unc_prefix_len; ++i) { 936 for (size_t i = 0; i < unc_prefix_len; ++i) {
938 R_UNLESS(cur_path[i] != DirectorySeparator, ResultNotNormalized); 937 R_UNLESS(cur_path[i] != DirectorySeparator, ResultNotNormalized);
939 } 938 }
940 } else { 939 } else {
941 /* Ensure we can copy into the normalized buffer. */ 940 // Ensure we can copy into the normalized buffer
942 R_UNLESS(unc_prefix_len < out_win_buffer_size, ResultTooLongPath); 941 R_UNLESS(unc_prefix_len < out_win_buffer_size, ResultTooLongPath);
943 942
944 for (size_t i = 0; i < unc_prefix_len; ++i) { 943 for (size_t i = 0; i < unc_prefix_len; ++i) {
@@ -954,7 +953,7 @@ public:
954 R_SUCCEED(); 953 R_SUCCEED();
955 } 954 }
956 955
957 /* There's no windows path to parse. */ 956 // There's no windows path to parse
958 *out = path; 957 *out = path;
959 *out_len = 0; 958 *out_len = 0;
960 R_SUCCEED(); 959 R_SUCCEED();
@@ -962,18 +961,18 @@ public:
962 961
963 static constexpr Result IsNormalized(bool* out, size_t* out_len, const char* path, 962 static constexpr Result IsNormalized(bool* out, size_t* out_len, const char* path,
964 const PathFlags& flags = {}) { 963 const PathFlags& flags = {}) {
965 /* Ensure nothing is null. */ 964 // Ensure nothing is null
966 R_UNLESS(out != nullptr, ResultNullptrArgument); 965 R_UNLESS(out != nullptr, ResultNullptrArgument);
967 R_UNLESS(out_len != nullptr, ResultNullptrArgument); 966 R_UNLESS(out_len != nullptr, ResultNullptrArgument);
968 R_UNLESS(path != nullptr, ResultNullptrArgument); 967 R_UNLESS(path != nullptr, ResultNullptrArgument);
969 968
970 /* Verify that the path is valid utf-8. */ 969 // Verify that the path is valid utf-8
971 R_TRY(CheckUtf8(path)); 970 R_TRY(CheckUtf8(path));
972 971
973 /* Use StringTraits names for remainder of scope. */ 972 // Use StringTraits names for remainder of scope
974 using namespace StringTraits; 973 using namespace StringTraits;
975 974
976 /* Handle the case where the path is empty. */ 975 // Handle the case where the path is empty
977 if (path[0] == NullTerminator) { 976 if (path[0] == NullTerminator) {
978 R_UNLESS(flags.IsEmptyPathAllowed(), ResultInvalidPathFormat); 977 R_UNLESS(flags.IsEmptyPathAllowed(), ResultInvalidPathFormat);
979 978
@@ -982,32 +981,32 @@ public:
982 R_SUCCEED(); 981 R_SUCCEED();
983 } 982 }
984 983
985 /* All normalized paths start with a directory separator...unless they're windows paths, 984 // All normalized paths start with a directory separator...unless they're windows paths,
986 * relative paths, or have mount names. */ 985 // relative paths, or have mount names.
987 if (path[0] != DirectorySeparator) { 986 if (path[0] != DirectorySeparator) {
988 R_UNLESS(flags.IsWindowsPathAllowed() || flags.IsRelativePathAllowed() || 987 R_UNLESS(flags.IsWindowsPathAllowed() || flags.IsRelativePathAllowed() ||
989 flags.IsMountNameAllowed(), 988 flags.IsMountNameAllowed(),
990 ResultInvalidPathFormat); 989 ResultInvalidPathFormat);
991 } 990 }
992 991
993 /* Check that the path is allowed to be a windows path, if it is. */ 992 // Check that the path is allowed to be a windows path, if it is
994 if (IsWindowsPath(path, false)) { 993 if (IsWindowsPath(path, false)) {
995 R_UNLESS(flags.IsWindowsPathAllowed(), ResultInvalidPathFormat); 994 R_UNLESS(flags.IsWindowsPathAllowed(), ResultInvalidPathFormat);
996 } 995 }
997 996
998 /* Skip past the mount name, if one is present. */ 997 // Skip past the mount name, if one is present
999 size_t total_len = 0; 998 size_t total_len = 0;
1000 size_t mount_name_len = 0; 999 size_t mount_name_len = 0;
1001 R_TRY(SkipMountName(std::addressof(path), std::addressof(mount_name_len), path)); 1000 R_TRY(SkipMountName(std::addressof(path), std::addressof(mount_name_len), path));
1002 1001
1003 /* If we had a mount name, check that that was allowed. */ 1002 // If we had a mount name, check that that was allowed
1004 if (mount_name_len > 0) { 1003 if (mount_name_len > 0) {
1005 R_UNLESS(flags.IsMountNameAllowed(), ResultInvalidPathFormat); 1004 R_UNLESS(flags.IsMountNameAllowed(), ResultInvalidPathFormat);
1006 1005
1007 total_len += mount_name_len; 1006 total_len += mount_name_len;
1008 } 1007 }
1009 1008
1010 /* Check that the path starts as a normalized path should. */ 1009 // Check that the path starts as a normalized path should
1011 if (path[0] != DirectorySeparator && !IsPathStartWithCurrentDirectory(path) && 1010 if (path[0] != DirectorySeparator && !IsPathStartWithCurrentDirectory(path) &&
1012 !IsWindowsPath(path, false)) { 1011 !IsWindowsPath(path, false)) {
1013 R_UNLESS(flags.IsRelativePathAllowed(), ResultInvalidPathFormat); 1012 R_UNLESS(flags.IsRelativePathAllowed(), ResultInvalidPathFormat);
@@ -1017,11 +1016,11 @@ public:
1017 R_SUCCEED(); 1016 R_SUCCEED();
1018 } 1017 }
1019 1018
1020 /* Process relative path. */ 1019 // Process relative path
1021 size_t relative_len = 0; 1020 size_t relative_len = 0;
1022 R_TRY(SkipRelativeDotPath(std::addressof(path), std::addressof(relative_len), path)); 1021 R_TRY(SkipRelativeDotPath(std::addressof(path), std::addressof(relative_len), path));
1023 1022
1024 /* If we have a relative path, check that was allowed. */ 1023 // If we have a relative path, check that was allowed
1025 if (relative_len > 0) { 1024 if (relative_len > 0) {
1026 R_UNLESS(flags.IsRelativePathAllowed(), ResultInvalidPathFormat); 1025 R_UNLESS(flags.IsRelativePathAllowed(), ResultInvalidPathFormat);
1027 1026
@@ -1034,13 +1033,13 @@ public:
1034 } 1033 }
1035 } 1034 }
1036 1035
1037 /* Process windows path. */ 1036 // Process windows path
1038 size_t windows_len = 0; 1037 size_t windows_len = 0;
1039 bool normalized_win = false; 1038 bool normalized_win = false;
1040 R_TRY(SkipWindowsPath(std::addressof(path), std::addressof(windows_len), 1039 R_TRY(SkipWindowsPath(std::addressof(path), std::addressof(windows_len),
1041 std::addressof(normalized_win), path, mount_name_len > 0)); 1040 std::addressof(normalized_win), path, mount_name_len > 0));
1042 1041
1043 /* If the windows path wasn't normalized, we're not normalized. */ 1042 // If the windows path wasn't normalized, we're not normalized
1044 if (!normalized_win) { 1043 if (!normalized_win) {
1045 R_UNLESS(flags.IsWindowsPathAllowed(), ResultInvalidPathFormat); 1044 R_UNLESS(flags.IsWindowsPathAllowed(), ResultInvalidPathFormat);
1046 1045
@@ -1048,22 +1047,22 @@ public:
1048 R_SUCCEED(); 1047 R_SUCCEED();
1049 } 1048 }
1050 1049
1051 /* If we had a windows path, check that was allowed. */ 1050 // If we had a windows path, check that was allowed
1052 if (windows_len > 0) { 1051 if (windows_len > 0) {
1053 R_UNLESS(flags.IsWindowsPathAllowed(), ResultInvalidPathFormat); 1052 R_UNLESS(flags.IsWindowsPathAllowed(), ResultInvalidPathFormat);
1054 1053
1055 total_len += windows_len; 1054 total_len += windows_len;
1056 1055
1057 /* We can't have both a relative path and a windows path. */ 1056 // We can't have both a relative path and a windows path
1058 R_UNLESS(relative_len == 0, ResultInvalidPathFormat); 1057 R_UNLESS(relative_len == 0, ResultInvalidPathFormat);
1059 1058
1060 /* A path ending in a windows path isn't normalized. */ 1059 // A path ending in a windows path isn't normalized
1061 if (path[0] == NullTerminator) { 1060 if (path[0] == NullTerminator) {
1062 *out = false; 1061 *out = false;
1063 R_SUCCEED(); 1062 R_SUCCEED();
1064 } 1063 }
1065 1064
1066 /* Check that there are no windows directory separators in the path. */ 1065 // Check that there are no windows directory separators in the path
1067 for (size_t i = 0; path[i] != NullTerminator; ++i) { 1066 for (size_t i = 0; path[i] != NullTerminator; ++i) {
1068 if (path[i] == AlternateDirectorySeparator) { 1067 if (path[i] == AlternateDirectorySeparator) {
1069 *out = false; 1068 *out = false;
@@ -1072,48 +1071,48 @@ public:
1072 } 1071 }
1073 } 1072 }
1074 1073
1075 /* Check that parent directory replacement is not needed if backslashes are allowed. */ 1074 // Check that parent directory replacement is not needed if backslashes are allowed
1076 if (flags.IsBackslashAllowed() && 1075 if (flags.IsBackslashAllowed() &&
1077 PathNormalizer::IsParentDirectoryPathReplacementNeeded(path)) { 1076 PathNormalizer::IsParentDirectoryPathReplacementNeeded(path)) {
1078 *out = false; 1077 *out = false;
1079 R_SUCCEED(); 1078 R_SUCCEED();
1080 } 1079 }
1081 1080
1082 /* Check that the backslash state is valid. */ 1081 // Check that the backslash state is valid
1083 bool is_backslash_contained = false; 1082 bool is_backslash_contained = false;
1084 R_TRY(CheckInvalidBackslash(std::addressof(is_backslash_contained), path, 1083 R_TRY(CheckInvalidBackslash(std::addressof(is_backslash_contained), path,
1085 flags.IsWindowsPathAllowed() || flags.IsBackslashAllowed())); 1084 flags.IsWindowsPathAllowed() || flags.IsBackslashAllowed()));
1086 1085
1087 /* Check that backslashes are contained only if allowed. */ 1086 // Check that backslashes are contained only if allowed
1088 if (is_backslash_contained && !flags.IsBackslashAllowed()) { 1087 if (is_backslash_contained && !flags.IsBackslashAllowed()) {
1089 *out = false; 1088 *out = false;
1090 R_SUCCEED(); 1089 R_SUCCEED();
1091 } 1090 }
1092 1091
1093 /* Check that the final result path is normalized. */ 1092 // Check that the final result path is normalized
1094 size_t normal_len = 0; 1093 size_t normal_len = 0;
1095 R_TRY(PathNormalizer::IsNormalized(out, std::addressof(normal_len), path, 1094 R_TRY(PathNormalizer::IsNormalized(out, std::addressof(normal_len), path,
1096 flags.IsAllCharactersAllowed())); 1095 flags.IsAllCharactersAllowed()));
1097 1096
1098 /* Add the normal length. */ 1097 // Add the normal length
1099 total_len += normal_len; 1098 total_len += normal_len;
1100 1099
1101 /* Set the output length. */ 1100 // Set the output length
1102 *out_len = total_len; 1101 *out_len = total_len;
1103 R_SUCCEED(); 1102 R_SUCCEED();
1104 } 1103 }
1105 1104
1106 static Result Normalize(char* dst, size_t dst_size, const char* path, size_t path_len, 1105 static Result Normalize(char* dst, size_t dst_size, const char* path, size_t path_len,
1107 const PathFlags& flags) { 1106 const PathFlags& flags) {
1108 /* Use StringTraits names for remainder of scope. */ 1107 // Use StringTraits names for remainder of scope
1109 using namespace StringTraits; 1108 using namespace StringTraits;
1110 1109
1111 /* Prepare to iterate. */ 1110 // Prepare to iterate
1112 const char* src = path; 1111 const char* src = path;
1113 size_t cur_pos = 0; 1112 size_t cur_pos = 0;
1114 bool is_windows_path = false; 1113 bool is_windows_path = false;
1115 1114
1116 /* Check if the path is empty. */ 1115 // Check if the path is empty
1117 if (src[0] == NullTerminator) { 1116 if (src[0] == NullTerminator) {
1118 if (dst_size != 0) { 1117 if (dst_size != 0) {
1119 dst[0] = NullTerminator; 1118 dst[0] = NullTerminator;
@@ -1124,7 +1123,7 @@ public:
1124 R_SUCCEED(); 1123 R_SUCCEED();
1125 } 1124 }
1126 1125
1127 /* Handle a mount name. */ 1126 // Handle a mount name
1128 size_t mount_name_len = 0; 1127 size_t mount_name_len = 0;
1129 if (flags.IsMountNameAllowed()) { 1128 if (flags.IsMountNameAllowed()) {
1130 R_TRY(ParseMountName(std::addressof(src), std::addressof(mount_name_len), dst + cur_pos, 1129 R_TRY(ParseMountName(std::addressof(src), std::addressof(mount_name_len), dst + cur_pos,
@@ -1133,7 +1132,7 @@ public:
1133 cur_pos += mount_name_len; 1132 cur_pos += mount_name_len;
1134 } 1133 }
1135 1134
1136 /* Handle a drive-relative prefix. */ 1135 // Handle a drive-relative prefix
1137 bool is_drive_relative = false; 1136 bool is_drive_relative = false;
1138 if (src[0] != DirectorySeparator && !IsPathStartWithCurrentDirectory(src) && 1137 if (src[0] != DirectorySeparator && !IsPathStartWithCurrentDirectory(src) &&
1139 !IsWindowsPath(src, false)) { 1138 !IsWindowsPath(src, false)) {
@@ -1161,7 +1160,7 @@ public:
1161 } 1160 }
1162 } 1161 }
1163 1162
1164 /* Handle a windows path. */ 1163 // Handle a windows path
1165 if (flags.IsWindowsPathAllowed()) { 1164 if (flags.IsWindowsPathAllowed()) {
1166 const char* const orig = src; 1165 const char* const orig = src;
1167 1166
@@ -1187,16 +1186,16 @@ public:
1187 } 1186 }
1188 } 1187 }
1189 1188
1190 /* Check for invalid backslash. */ 1189 // Check for invalid backslash
1191 bool backslash_contained = false; 1190 bool backslash_contained = false;
1192 R_TRY(CheckInvalidBackslash(std::addressof(backslash_contained), src, 1191 R_TRY(CheckInvalidBackslash(std::addressof(backslash_contained), src,
1193 flags.IsWindowsPathAllowed() || flags.IsBackslashAllowed())); 1192 flags.IsWindowsPathAllowed() || flags.IsBackslashAllowed()));
1194 1193
1195 /* Handle backslash replacement as necessary. */ 1194 // Handle backslash replacement as necessary
1196 if (backslash_contained && flags.IsWindowsPathAllowed()) { 1195 if (backslash_contained && flags.IsWindowsPathAllowed()) {
1197 /* Create a temporary buffer holding a slash-replaced version of the path. */ 1196 // Create a temporary buffer holding a slash-replaced version of the path.
1198 /* NOTE: Nintendo unnecessarily allocates and replaces here a fully copy of the path, 1197 // NOTE: Nintendo unnecessarily allocates and replaces here a fully copy of the path,
1199 * despite having skipped some of it already. */ 1198 // despite having skipped some of it already.
1200 const size_t replaced_src_len = path_len - (src - path); 1199 const size_t replaced_src_len = path_len - (src - path);
1201 1200
1202 char* replaced_src = nullptr; 1201 char* replaced_src = nullptr;
@@ -1226,7 +1225,7 @@ public:
1226 dst_size - cur_pos, is_windows_path, is_drive_relative, 1225 dst_size - cur_pos, is_windows_path, is_drive_relative,
1227 flags.IsAllCharactersAllowed())); 1226 flags.IsAllCharactersAllowed()));
1228 } else { 1227 } else {
1229 /* We can just do normalization. */ 1228 // We can just do normalization
1230 size_t dummy; 1229 size_t dummy;
1231 R_TRY(PathNormalizer::Normalize(dst + cur_pos, std::addressof(dummy), src, 1230 R_TRY(PathNormalizer::Normalize(dst + cur_pos, std::addressof(dummy), src,
1232 dst_size - cur_pos, is_windows_path, is_drive_relative, 1231 dst_size - cur_pos, is_windows_path, is_drive_relative,
diff --git a/src/core/file_sys/fs_string_util.h b/src/core/file_sys/fs_string_util.h
index 68114e72c..874e09054 100644
--- a/src/core/file_sys/fs_string_util.h
+++ b/src/core/file_sys/fs_string_util.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
@@ -71,21 +71,6 @@ static constexpr int Strlcpy(T* dst, const T* src, int count) {
71 return static_cast<int>(cur - src); 71 return static_cast<int>(cur - src);
72} 72}
73 73
74/* std::size() does not support zero-size C arrays. We're fixing that. */
75template <class C>
76constexpr auto size(const C& c) -> decltype(c.size()) {
77 return std::size(c);
78}
79
80template <class C>
81constexpr std::size_t size(const C& c) {
82 if constexpr (sizeof(C) == 0) {
83 return 0;
84 } else {
85 return std::size(c);
86 }
87}
88
89enum CharacterEncodingResult { 74enum CharacterEncodingResult {
90 CharacterEncodingResult_Success = 0, 75 CharacterEncodingResult_Success = 0,
91 CharacterEncodingResult_InsufficientLength = 1, 76 CharacterEncodingResult_InsufficientLength = 1,
@@ -116,11 +101,11 @@ public:
116} // namespace impl 101} // namespace impl
117 102
118constexpr inline CharacterEncodingResult ConvertCharacterUtf8ToUtf32(u32* dst, const char* src) { 103constexpr inline CharacterEncodingResult ConvertCharacterUtf8ToUtf32(u32* dst, const char* src) {
119 /* Check pre-conditions. */ 104 // Check pre-conditions
120 ASSERT(dst != nullptr); 105 ASSERT(dst != nullptr);
121 ASSERT(src != nullptr); 106 ASSERT(src != nullptr);
122 107
123 /* Perform the conversion. */ 108 // Perform the conversion
124 const auto* p = src; 109 const auto* p = src;
125 switch (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[0]))) { 110 switch (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[0]))) {
126 case 1: 111 case 1:
@@ -164,24 +149,24 @@ constexpr inline CharacterEncodingResult ConvertCharacterUtf8ToUtf32(u32* dst, c
164 break; 149 break;
165 } 150 }
166 151
167 /* We failed to convert. */ 152 // We failed to convert
168 return CharacterEncodingResult_InvalidFormat; 153 return CharacterEncodingResult_InvalidFormat;
169} 154}
170 155
171constexpr inline CharacterEncodingResult PickOutCharacterFromUtf8String(char* dst, 156constexpr inline CharacterEncodingResult PickOutCharacterFromUtf8String(char* dst,
172 const char** str) { 157 const char** str) {
173 /* Check pre-conditions. */ 158 // Check pre-conditions
174 ASSERT(dst != nullptr); 159 ASSERT(dst != nullptr);
175 ASSERT(str != nullptr); 160 ASSERT(str != nullptr);
176 ASSERT(*str != nullptr); 161 ASSERT(*str != nullptr);
177 162
178 /* Clear the output. */ 163 // Clear the output
179 dst[0] = 0; 164 dst[0] = 0;
180 dst[1] = 0; 165 dst[1] = 0;
181 dst[2] = 0; 166 dst[2] = 0;
182 dst[3] = 0; 167 dst[3] = 0;
183 168
184 /* Perform the conversion. */ 169 // Perform the conversion
185 const auto* p = *str; 170 const auto* p = *str;
186 u32 c = static_cast<u32>(*p); 171 u32 c = static_cast<u32>(*p);
187 switch (impl::CharacterEncodingHelper::GetUtf8NBytes(c)) { 172 switch (impl::CharacterEncodingHelper::GetUtf8NBytes(c)) {
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 2413cdb5c..718500385 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <memory> 6#include <memory>
7#include <mutex>
7#include "common/common_types.h" 8#include "common/common_types.h"
8#include "core/file_sys/fs_directory.h" 9#include "core/file_sys/fs_directory.h"
9#include "core/file_sys/fs_filesystem.h" 10#include "core/file_sys/fs_filesystem.h"
diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp
index 6423e5089..b56762941 100644
--- a/src/core/hle/service/glue/time/manager.cpp
+++ b/src/core/hle/service/glue/time/manager.cpp
@@ -8,7 +8,7 @@
8 8
9#include "common/settings.h" 9#include "common/settings.h"
10#include "common/time_zone.h" 10#include "common/time_zone.h"
11#include "core/file_sys/vfs.h" 11#include "core/file_sys/vfs/vfs.h"
12#include "core/hle/kernel/svc.h" 12#include "core/hle/kernel/svc.h"
13#include "core/hle/service/glue/time/manager.h" 13#include "core/hle/service/glue/time/manager.h"
14#include "core/hle/service/glue/time/time_zone_binary.h" 14#include "core/hle/service/glue/time/time_zone_binary.h"
diff --git a/src/core/hle/service/glue/time/manager.h b/src/core/hle/service/glue/time/manager.h
index a46ec6364..1de93f8f9 100644
--- a/src/core/hle/service/glue/time/manager.h
+++ b/src/core/hle/service/glue/time/manager.h
@@ -7,7 +7,7 @@
7#include <string> 7#include <string>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/file_sys/vfs_types.h" 10#include "core/file_sys/vfs/vfs_types.h"
11#include "core/hle/service/glue/time/file_timestamp_worker.h" 11#include "core/hle/service/glue/time/file_timestamp_worker.h"
12#include "core/hle/service/glue/time/standard_steady_clock_resource.h" 12#include "core/hle/service/glue/time/standard_steady_clock_resource.h"
13#include "core/hle/service/glue/time/worker.h" 13#include "core/hle/service/glue/time/worker.h"
diff --git a/src/core/hle/service/glue/time/time_zone_binary.cpp b/src/core/hle/service/glue/time/time_zone_binary.cpp
index 67969aa3f..d33f784c0 100644
--- a/src/core/hle/service/glue/time/time_zone_binary.cpp
+++ b/src/core/hle/service/glue/time/time_zone_binary.cpp
@@ -7,7 +7,7 @@
7#include "core/file_sys/registered_cache.h" 7#include "core/file_sys/registered_cache.h"
8#include "core/file_sys/romfs.h" 8#include "core/file_sys/romfs.h"
9#include "core/file_sys/system_archive/system_archive.h" 9#include "core/file_sys/system_archive/system_archive.h"
10#include "core/file_sys/vfs.h" 10#include "core/file_sys/vfs/vfs.h"
11#include "core/hle/service/filesystem/filesystem.h" 11#include "core/hle/service/filesystem/filesystem.h"
12#include "core/hle/service/glue/time/time_zone_binary.h" 12#include "core/hle/service/glue/time/time_zone_binary.h"
13 13
diff --git a/src/frontend_common/content_manager.h b/src/frontend_common/content_manager.h
index fc359b494..f3efe3465 100644
--- a/src/frontend_common/content_manager.h
+++ b/src/frontend_common/content_manager.h
@@ -159,7 +159,7 @@ inline InstallResult InstallNSP(Core::System& system, FileSys::VfsFilesystem& vf
159 }; 159 };
160 160
161 std::shared_ptr<FileSys::NSP> nsp; 161 std::shared_ptr<FileSys::NSP> nsp;
162 FileSys::VirtualFile file = vfs.OpenFile(filename, FileSys::Mode::Read); 162 FileSys::VirtualFile file = vfs.OpenFile(filename, FileSys::OpenMode::Read);
163 if (boost::to_lower_copy(file->GetName()).ends_with(std::string("nsp"))) { 163 if (boost::to_lower_copy(file->GetName()).ends_with(std::string("nsp"))) {
164 nsp = std::make_shared<FileSys::NSP>(file); 164 nsp = std::make_shared<FileSys::NSP>(file);
165 if (nsp->IsExtractedType()) { 165 if (nsp->IsExtractedType()) {
@@ -224,7 +224,8 @@ inline InstallResult InstallNCA(FileSys::VfsFilesystem& vfs, const std::string&
224 return true; 224 return true;
225 }; 225 };
226 226
227 const auto nca = std::make_shared<FileSys::NCA>(vfs.OpenFile(filename, FileSys::Mode::Read)); 227 const auto nca =
228 std::make_shared<FileSys::NCA>(vfs.OpenFile(filename, FileSys::OpenMode::Read));
228 const auto id = nca->GetStatus(); 229 const auto id = nca->GetStatus();
229 230
230 // Game updates necessary are missing base RomFS 231 // Game updates necessary are missing base RomFS
@@ -345,8 +346,8 @@ inline std::vector<std::string> VerifyInstalledContents(
345inline GameVerificationResult VerifyGameContents( 346inline GameVerificationResult VerifyGameContents(
346 Core::System& system, const std::string& game_path, 347 Core::System& system, const std::string& game_path,
347 const std::function<bool(size_t, size_t)>& callback) { 348 const std::function<bool(size_t, size_t)>& callback) {
348 const auto loader = 349 const auto loader = Loader::GetLoader(
349 Loader::GetLoader(system, system.GetFilesystem()->OpenFile(game_path, FileSys::Mode::Read)); 350 system, system.GetFilesystem()->OpenFile(game_path, FileSys::OpenMode::Read));
350 if (loader == nullptr) { 351 if (loader == nullptr) {
351 return GameVerificationResult::NotImplemented; 352 return GameVerificationResult::NotImplemented;
352 } 353 }