summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/fs/path_util.cpp38
-rw-r--r--src/common/fs/path_util.h6
-rw-r--r--src/core/file_sys/vfs.cpp8
-rw-r--r--src/core/file_sys/vfs_real.cpp8
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp6
5 files changed, 38 insertions, 28 deletions
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index c3a81f9a9..d2f50432a 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -354,18 +354,36 @@ std::string_view RemoveTrailingSlash(std::string_view path) {
354 return path; 354 return path;
355} 355}
356 356
357std::vector<std::string> SplitPathComponents(std::string_view filename) { 357template <typename F>
358 std::string copy(filename); 358static void ForEachPathComponent(std::string_view filename, F&& cb) {
359 std::replace(copy.begin(), copy.end(), '\\', '/'); 359 const char* component_begin = filename.data();
360 std::vector<std::string> out; 360 const char* const end = component_begin + filename.size();
361 361 for (const char* it = component_begin; it != end; ++it) {
362 std::stringstream stream(copy); 362 const char c = *it;
363 std::string item; 363 if (c == '\\' || c == '/') {
364 while (std::getline(stream, item, '/')) { 364 if (component_begin != it) {
365 out.push_back(std::move(item)); 365 cb(std::string_view{component_begin, it});
366 }
367 component_begin = it + 1;
368 }
366 } 369 }
370 if (component_begin != end) {
371 cb(std::string_view{component_begin, end});
372 }
373}
374
375std::vector<std::string_view> SplitPathComponents(std::string_view filename) {
376 std::vector<std::string_view> components;
377 ForEachPathComponent(filename, [&](auto component) { components.emplace_back(component); });
378
379 return components;
380}
381
382std::vector<std::string> SplitPathComponentsCopy(std::string_view filename) {
383 std::vector<std::string> components;
384 ForEachPathComponent(filename, [&](auto component) { components.emplace_back(component); });
367 385
368 return out; 386 return components;
369} 387}
370 388
371std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) { 389std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) {
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h
index 2874ea738..23c8b1359 100644
--- a/src/common/fs/path_util.h
+++ b/src/common/fs/path_util.h
@@ -289,7 +289,11 @@ enum class DirectorySeparator {
289 289
290// Splits the path on '/' or '\' and put the components into a vector 290// Splits the path on '/' or '\' and put the components into a vector
291// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } 291// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
292[[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename); 292[[nodiscard]] std::vector<std::string_view> SplitPathComponents(std::string_view filename);
293
294// Splits the path on '/' or '\' and put the components into a vector
295// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
296[[nodiscard]] std::vector<std::string> SplitPathComponentsCopy(std::string_view filename);
293 297
294// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\' 298// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
295// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows 299// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index 639842401..b7105c8ff 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -201,8 +201,6 @@ std::string VfsFile::GetFullPath() const {
201 201
202VirtualFile VfsDirectory::GetFileRelative(std::string_view path) const { 202VirtualFile VfsDirectory::GetFileRelative(std::string_view path) const {
203 auto vec = Common::FS::SplitPathComponents(path); 203 auto vec = Common::FS::SplitPathComponents(path);
204 vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
205 vec.end());
206 if (vec.empty()) { 204 if (vec.empty()) {
207 return nullptr; 205 return nullptr;
208 } 206 }
@@ -237,8 +235,6 @@ VirtualFile VfsDirectory::GetFileAbsolute(std::string_view path) const {
237 235
238VirtualDir VfsDirectory::GetDirectoryRelative(std::string_view path) const { 236VirtualDir VfsDirectory::GetDirectoryRelative(std::string_view path) const {
239 auto vec = Common::FS::SplitPathComponents(path); 237 auto vec = Common::FS::SplitPathComponents(path);
240 vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
241 vec.end());
242 if (vec.empty()) { 238 if (vec.empty()) {
243 // TODO(DarkLordZach): Return this directory if path is '/' or similar. Can't currently 239 // TODO(DarkLordZach): Return this directory if path is '/' or similar. Can't currently
244 // because of const-ness 240 // because of const-ness
@@ -303,8 +299,6 @@ std::size_t VfsDirectory::GetSize() const {
303 299
304VirtualFile VfsDirectory::CreateFileRelative(std::string_view path) { 300VirtualFile VfsDirectory::CreateFileRelative(std::string_view path) {
305 auto vec = Common::FS::SplitPathComponents(path); 301 auto vec = Common::FS::SplitPathComponents(path);
306 vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
307 vec.end());
308 if (vec.empty()) { 302 if (vec.empty()) {
309 return nullptr; 303 return nullptr;
310 } 304 }
@@ -334,8 +328,6 @@ VirtualFile VfsDirectory::CreateFileAbsolute(std::string_view path) {
334 328
335VirtualDir VfsDirectory::CreateDirectoryRelative(std::string_view path) { 329VirtualDir VfsDirectory::CreateDirectoryRelative(std::string_view path) {
336 auto vec = Common::FS::SplitPathComponents(path); 330 auto vec = Common::FS::SplitPathComponents(path);
337 vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
338 vec.end());
339 if (vec.empty()) { 331 if (vec.empty()) {
340 return nullptr; 332 return nullptr;
341 } 333 }
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 1c706e4d8..cd9b79786 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -268,7 +268,7 @@ void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference)
268RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, 268RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_,
269 const std::string& path_, Mode perms_, std::optional<u64> size_) 269 const std::string& path_, Mode perms_, std::optional<u64> size_)
270 : base(base_), reference(std::move(reference_)), path(path_), 270 : base(base_), reference(std::move(reference_)), path(path_),
271 parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), 271 parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponentsCopy(path_)),
272 size(size_), perms(perms_) {} 272 size(size_), perms(perms_) {}
273 273
274RealVfsFile::~RealVfsFile() { 274RealVfsFile::~RealVfsFile() {
@@ -276,7 +276,7 @@ RealVfsFile::~RealVfsFile() {
276} 276}
277 277
278std::string RealVfsFile::GetName() const { 278std::string RealVfsFile::GetName() const {
279 return path_components.back(); 279 return path_components.empty() ? "" : std::string(path_components.back());
280} 280}
281 281
282std::size_t RealVfsFile::GetSize() const { 282std::size_t RealVfsFile::GetSize() const {
@@ -375,7 +375,7 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi
375 375
376RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_) 376RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_)
377 : base(base_), path(FS::RemoveTrailingSlash(path_)), parent_path(FS::GetParentPath(path)), 377 : base(base_), path(FS::RemoveTrailingSlash(path_)), parent_path(FS::GetParentPath(path)),
378 path_components(FS::SplitPathComponents(path)), perms(perms_) { 378 path_components(FS::SplitPathComponentsCopy(path)), perms(perms_) {
379 if (!FS::Exists(path) && True(perms & Mode::Write)) { 379 if (!FS::Exists(path) && True(perms & Mode::Write)) {
380 void(FS::CreateDirs(path)); 380 void(FS::CreateDirs(path));
381 } 381 }
@@ -464,7 +464,7 @@ bool RealVfsDirectory::IsReadable() const {
464} 464}
465 465
466std::string RealVfsDirectory::GetName() const { 466std::string RealVfsDirectory::GetName() const {
467 return path_components.back(); 467 return path_components.empty() ? "" : std::string(path_components.back());
468} 468}
469 469
470VirtualDir RealVfsDirectory::GetParentDirectory() const { 470VirtualDir RealVfsDirectory::GetParentDirectory() const {
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 508db7360..780f8c74d 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -104,11 +104,7 @@ Result VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) con
104 const auto components = Common::FS::SplitPathComponents(path); 104 const auto components = Common::FS::SplitPathComponents(path);
105 std::string relative_path; 105 std::string relative_path;
106 for (const auto& component : components) { 106 for (const auto& component : components) {
107 // Skip empty path components 107 relative_path = Common::FS::SanitizePath(fmt::format("{}/{}", relative_path, component));
108 if (component.empty()) {
109 continue;
110 }
111 relative_path = Common::FS::SanitizePath(relative_path + '/' + component);
112 auto new_dir = backing->CreateSubdirectory(relative_path); 108 auto new_dir = backing->CreateSubdirectory(relative_path);
113 if (new_dir == nullptr) { 109 if (new_dir == nullptr) {
114 // TODO(DarkLordZach): Find a better error code for this 110 // TODO(DarkLordZach): Find a better error code for this