diff options
Diffstat (limited to 'src/common/fs')
| -rw-r--r-- | src/common/fs/file.cpp | 38 | ||||
| -rw-r--r-- | src/common/fs/fs.cpp | 41 | ||||
| -rw-r--r-- | src/common/fs/fs_android.cpp | 98 | ||||
| -rw-r--r-- | src/common/fs/fs_android.h | 65 | ||||
| -rw-r--r-- | src/common/fs/fs_paths.h | 1 | ||||
| -rw-r--r-- | src/common/fs/fs_types.h | 2 | ||||
| -rw-r--r-- | src/common/fs/path_util.cpp | 27 | ||||
| -rw-r--r-- | src/common/fs/path_util.h | 9 |
8 files changed, 273 insertions, 8 deletions
diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp index 656b03cc5..b0b25eb43 100644 --- a/src/common/fs/file.cpp +++ b/src/common/fs/file.cpp | |||
| @@ -5,6 +5,9 @@ | |||
| 5 | 5 | ||
| 6 | #include "common/fs/file.h" | 6 | #include "common/fs/file.h" |
| 7 | #include "common/fs/fs.h" | 7 | #include "common/fs/fs.h" |
| 8 | #ifdef ANDROID | ||
| 9 | #include "common/fs/fs_android.h" | ||
| 10 | #endif | ||
| 8 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 9 | 12 | ||
| 10 | #ifdef _WIN32 | 13 | #ifdef _WIN32 |
| @@ -252,6 +255,23 @@ void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, File | |||
| 252 | } else { | 255 | } else { |
| 253 | _wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type)); | 256 | _wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type)); |
| 254 | } | 257 | } |
| 258 | #elif ANDROID | ||
| 259 | if (Android::IsContentUri(path)) { | ||
| 260 | ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!"); | ||
| 261 | const auto fd = Android::OpenContentUri(path, Android::OpenMode::Read); | ||
| 262 | if (fd != -1) { | ||
| 263 | file = fdopen(fd, "r"); | ||
| 264 | const auto error_num = errno; | ||
| 265 | if (error_num != 0 && file == nullptr) { | ||
| 266 | LOG_ERROR(Common_Filesystem, "Error opening file: {}, error: {}", path.c_str(), | ||
| 267 | strerror(error_num)); | ||
| 268 | } | ||
| 269 | } else { | ||
| 270 | LOG_ERROR(Common_Filesystem, "Error opening file: {}", path.c_str()); | ||
| 271 | } | ||
| 272 | } else { | ||
| 273 | file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); | ||
| 274 | } | ||
| 255 | #else | 275 | #else |
| 256 | file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); | 276 | file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); |
| 257 | #endif | 277 | #endif |
| @@ -372,6 +392,23 @@ u64 IOFile::GetSize() const { | |||
| 372 | // Flush any unwritten buffered data into the file prior to retrieving the file size. | 392 | // Flush any unwritten buffered data into the file prior to retrieving the file size. |
| 373 | std::fflush(file); | 393 | std::fflush(file); |
| 374 | 394 | ||
| 395 | #if ANDROID | ||
| 396 | u64 file_size = 0; | ||
| 397 | if (Android::IsContentUri(file_path)) { | ||
| 398 | file_size = Android::GetSize(file_path); | ||
| 399 | } else { | ||
| 400 | std::error_code ec; | ||
| 401 | |||
| 402 | file_size = fs::file_size(file_path, ec); | ||
| 403 | |||
| 404 | if (ec) { | ||
| 405 | LOG_ERROR(Common_Filesystem, | ||
| 406 | "Failed to retrieve the file size of path={}, ec_message={}", | ||
| 407 | PathToUTF8String(file_path), ec.message()); | ||
| 408 | return 0; | ||
| 409 | } | ||
| 410 | } | ||
| 411 | #else | ||
| 375 | std::error_code ec; | 412 | std::error_code ec; |
| 376 | 413 | ||
| 377 | const auto file_size = fs::file_size(file_path, ec); | 414 | const auto file_size = fs::file_size(file_path, ec); |
| @@ -381,6 +418,7 @@ u64 IOFile::GetSize() const { | |||
| 381 | PathToUTF8String(file_path), ec.message()); | 418 | PathToUTF8String(file_path), ec.message()); |
| 382 | return 0; | 419 | return 0; |
| 383 | } | 420 | } |
| 421 | #endif | ||
| 384 | 422 | ||
| 385 | return file_size; | 423 | return file_size; |
| 386 | } | 424 | } |
diff --git a/src/common/fs/fs.cpp b/src/common/fs/fs.cpp index e1716c62d..36e67c145 100644 --- a/src/common/fs/fs.cpp +++ b/src/common/fs/fs.cpp | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/fs/file.h" | 4 | #include "common/fs/file.h" |
| 5 | #include "common/fs/fs.h" | 5 | #include "common/fs/fs.h" |
| 6 | #ifdef ANDROID | ||
| 7 | #include "common/fs/fs_android.h" | ||
| 8 | #endif | ||
| 6 | #include "common/fs/path_util.h" | 9 | #include "common/fs/path_util.h" |
| 7 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 8 | 11 | ||
| @@ -433,7 +436,7 @@ void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable | |||
| 433 | 436 | ||
| 434 | if (True(filter & DirEntryFilter::File) && | 437 | if (True(filter & DirEntryFilter::File) && |
| 435 | entry.status().type() == fs::file_type::regular) { | 438 | entry.status().type() == fs::file_type::regular) { |
| 436 | if (!callback(entry.path())) { | 439 | if (!callback(entry)) { |
| 437 | callback_error = true; | 440 | callback_error = true; |
| 438 | break; | 441 | break; |
| 439 | } | 442 | } |
| @@ -441,7 +444,7 @@ void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable | |||
| 441 | 444 | ||
| 442 | if (True(filter & DirEntryFilter::Directory) && | 445 | if (True(filter & DirEntryFilter::Directory) && |
| 443 | entry.status().type() == fs::file_type::directory) { | 446 | entry.status().type() == fs::file_type::directory) { |
| 444 | if (!callback(entry.path())) { | 447 | if (!callback(entry)) { |
| 445 | callback_error = true; | 448 | callback_error = true; |
| 446 | break; | 449 | break; |
| 447 | } | 450 | } |
| @@ -490,7 +493,7 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path, | |||
| 490 | 493 | ||
| 491 | if (True(filter & DirEntryFilter::File) && | 494 | if (True(filter & DirEntryFilter::File) && |
| 492 | entry.status().type() == fs::file_type::regular) { | 495 | entry.status().type() == fs::file_type::regular) { |
| 493 | if (!callback(entry.path())) { | 496 | if (!callback(entry)) { |
| 494 | callback_error = true; | 497 | callback_error = true; |
| 495 | break; | 498 | break; |
| 496 | } | 499 | } |
| @@ -498,7 +501,7 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path, | |||
| 498 | 501 | ||
| 499 | if (True(filter & DirEntryFilter::Directory) && | 502 | if (True(filter & DirEntryFilter::Directory) && |
| 500 | entry.status().type() == fs::file_type::directory) { | 503 | entry.status().type() == fs::file_type::directory) { |
| 501 | if (!callback(entry.path())) { | 504 | if (!callback(entry)) { |
| 502 | callback_error = true; | 505 | callback_error = true; |
| 503 | break; | 506 | break; |
| 504 | } | 507 | } |
| @@ -525,15 +528,39 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path, | |||
| 525 | // Generic Filesystem Operations | 528 | // Generic Filesystem Operations |
| 526 | 529 | ||
| 527 | bool Exists(const fs::path& path) { | 530 | bool Exists(const fs::path& path) { |
| 531 | #ifdef ANDROID | ||
| 532 | if (Android::IsContentUri(path)) { | ||
| 533 | return Android::Exists(path); | ||
| 534 | } else { | ||
| 535 | return fs::exists(path); | ||
| 536 | } | ||
| 537 | #else | ||
| 528 | return fs::exists(path); | 538 | return fs::exists(path); |
| 539 | #endif | ||
| 529 | } | 540 | } |
| 530 | 541 | ||
| 531 | bool IsFile(const fs::path& path) { | 542 | bool IsFile(const fs::path& path) { |
| 543 | #ifdef ANDROID | ||
| 544 | if (Android::IsContentUri(path)) { | ||
| 545 | return !Android::IsDirectory(path); | ||
| 546 | } else { | ||
| 547 | return fs::is_regular_file(path); | ||
| 548 | } | ||
| 549 | #else | ||
| 532 | return fs::is_regular_file(path); | 550 | return fs::is_regular_file(path); |
| 551 | #endif | ||
| 533 | } | 552 | } |
| 534 | 553 | ||
| 535 | bool IsDir(const fs::path& path) { | 554 | bool IsDir(const fs::path& path) { |
| 555 | #ifdef ANDROID | ||
| 556 | if (Android::IsContentUri(path)) { | ||
| 557 | return Android::IsDirectory(path); | ||
| 558 | } else { | ||
| 559 | return fs::is_directory(path); | ||
| 560 | } | ||
| 561 | #else | ||
| 536 | return fs::is_directory(path); | 562 | return fs::is_directory(path); |
| 563 | #endif | ||
| 537 | } | 564 | } |
| 538 | 565 | ||
| 539 | fs::path GetCurrentDir() { | 566 | fs::path GetCurrentDir() { |
| @@ -578,6 +605,12 @@ fs::file_type GetEntryType(const fs::path& path) { | |||
| 578 | } | 605 | } |
| 579 | 606 | ||
| 580 | u64 GetSize(const fs::path& path) { | 607 | u64 GetSize(const fs::path& path) { |
| 608 | #ifdef ANDROID | ||
| 609 | if (Android::IsContentUri(path)) { | ||
| 610 | return Android::GetSize(path); | ||
| 611 | } | ||
| 612 | #endif | ||
| 613 | |||
| 581 | std::error_code ec; | 614 | std::error_code ec; |
| 582 | 615 | ||
| 583 | const auto file_size = fs::file_size(path, ec); | 616 | const auto file_size = fs::file_size(path, ec); |
diff --git a/src/common/fs/fs_android.cpp b/src/common/fs/fs_android.cpp new file mode 100644 index 000000000..298a79bac --- /dev/null +++ b/src/common/fs/fs_android.cpp | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/fs/fs_android.h" | ||
| 5 | |||
| 6 | namespace Common::FS::Android { | ||
| 7 | |||
| 8 | JNIEnv* GetEnvForThread() { | ||
| 9 | thread_local static struct OwnedEnv { | ||
| 10 | OwnedEnv() { | ||
| 11 | status = g_jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); | ||
| 12 | if (status == JNI_EDETACHED) | ||
| 13 | g_jvm->AttachCurrentThread(&env, nullptr); | ||
| 14 | } | ||
| 15 | |||
| 16 | ~OwnedEnv() { | ||
| 17 | if (status == JNI_EDETACHED) | ||
| 18 | g_jvm->DetachCurrentThread(); | ||
| 19 | } | ||
| 20 | |||
| 21 | int status; | ||
| 22 | JNIEnv* env = nullptr; | ||
| 23 | } owned; | ||
| 24 | return owned.env; | ||
| 25 | } | ||
| 26 | |||
| 27 | void RegisterCallbacks(JNIEnv* env, jclass clazz) { | ||
| 28 | env->GetJavaVM(&g_jvm); | ||
| 29 | native_library = clazz; | ||
| 30 | |||
| 31 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ | ||
| 32 | F(JMethodID, JMethodName, Signature) | ||
| 33 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \ | ||
| 34 | F(JMethodID, JMethodName, Signature) | ||
| 35 | #define F(JMethodID, JMethodName, Signature) \ | ||
| 36 | JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature); | ||
| 37 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||
| 38 | ANDROID_STORAGE_FUNCTIONS(FS) | ||
| 39 | #undef F | ||
| 40 | #undef FS | ||
| 41 | #undef FR | ||
| 42 | } | ||
| 43 | |||
| 44 | void UnRegisterCallbacks() { | ||
| 45 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | ||
| 46 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) | ||
| 47 | #define F(JMethodID) JMethodID = nullptr; | ||
| 48 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||
| 49 | ANDROID_STORAGE_FUNCTIONS(FS) | ||
| 50 | #undef F | ||
| 51 | #undef FS | ||
| 52 | #undef FR | ||
| 53 | } | ||
| 54 | |||
| 55 | bool IsContentUri(const std::string& path) { | ||
| 56 | constexpr std::string_view prefix = "content://"; | ||
| 57 | if (path.size() < prefix.size()) [[unlikely]] { | ||
| 58 | return false; | ||
| 59 | } | ||
| 60 | |||
| 61 | return path.find(prefix) == 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | int OpenContentUri(const std::string& filepath, OpenMode openmode) { | ||
| 65 | if (open_content_uri == nullptr) | ||
| 66 | return -1; | ||
| 67 | |||
| 68 | const char* mode = ""; | ||
| 69 | switch (openmode) { | ||
| 70 | case OpenMode::Read: | ||
| 71 | mode = "r"; | ||
| 72 | break; | ||
| 73 | default: | ||
| 74 | UNIMPLEMENTED(); | ||
| 75 | return -1; | ||
| 76 | } | ||
| 77 | auto env = GetEnvForThread(); | ||
| 78 | jstring j_filepath = env->NewStringUTF(filepath.c_str()); | ||
| 79 | jstring j_mode = env->NewStringUTF(mode); | ||
| 80 | return env->CallStaticIntMethod(native_library, open_content_uri, j_filepath, j_mode); | ||
| 81 | } | ||
| 82 | |||
| 83 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ | ||
| 84 | F(FunctionName, ReturnValue, JMethodID, Caller) | ||
| 85 | #define F(FunctionName, ReturnValue, JMethodID, Caller) \ | ||
| 86 | ReturnValue FunctionName(const std::string& filepath) { \ | ||
| 87 | if (JMethodID == nullptr) { \ | ||
| 88 | return 0; \ | ||
| 89 | } \ | ||
| 90 | auto env = GetEnvForThread(); \ | ||
| 91 | jstring j_filepath = env->NewStringUTF(filepath.c_str()); \ | ||
| 92 | return env->Caller(native_library, JMethodID, j_filepath); \ | ||
| 93 | } | ||
| 94 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||
| 95 | #undef F | ||
| 96 | #undef FR | ||
| 97 | |||
| 98 | } // namespace Common::FS::Android | ||
diff --git a/src/common/fs/fs_android.h b/src/common/fs/fs_android.h new file mode 100644 index 000000000..b441c2a12 --- /dev/null +++ b/src/common/fs/fs_android.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <string> | ||
| 7 | #include <vector> | ||
| 8 | #include <jni.h> | ||
| 9 | |||
| 10 | #define ANDROID_STORAGE_FUNCTIONS(V) \ | ||
| 11 | V(OpenContentUri, int, (const std::string& filepath, OpenMode openmode), open_content_uri, \ | ||
| 12 | "openContentUri", "(Ljava/lang/String;Ljava/lang/String;)I") | ||
| 13 | |||
| 14 | #define ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(V) \ | ||
| 15 | V(GetSize, std::uint64_t, get_size, CallStaticLongMethod, "getSize", "(Ljava/lang/String;)J") \ | ||
| 16 | V(IsDirectory, bool, is_directory, CallStaticBooleanMethod, "isDirectory", \ | ||
| 17 | "(Ljava/lang/String;)Z") \ | ||
| 18 | V(Exists, bool, file_exists, CallStaticBooleanMethod, "exists", "(Ljava/lang/String;)Z") | ||
| 19 | |||
| 20 | namespace Common::FS::Android { | ||
| 21 | |||
| 22 | static JavaVM* g_jvm = nullptr; | ||
| 23 | static jclass native_library = nullptr; | ||
| 24 | |||
| 25 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | ||
| 26 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) | ||
| 27 | #define F(JMethodID) static jmethodID JMethodID = nullptr; | ||
| 28 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||
| 29 | ANDROID_STORAGE_FUNCTIONS(FS) | ||
| 30 | #undef F | ||
| 31 | #undef FS | ||
| 32 | #undef FR | ||
| 33 | |||
| 34 | enum class OpenMode { | ||
| 35 | Read, | ||
| 36 | Write, | ||
| 37 | ReadWrite, | ||
| 38 | WriteAppend, | ||
| 39 | WriteTruncate, | ||
| 40 | ReadWriteAppend, | ||
| 41 | ReadWriteTruncate, | ||
| 42 | Never | ||
| 43 | }; | ||
| 44 | |||
| 45 | void RegisterCallbacks(JNIEnv* env, jclass clazz); | ||
| 46 | |||
| 47 | void UnRegisterCallbacks(); | ||
| 48 | |||
| 49 | bool IsContentUri(const std::string& path); | ||
| 50 | |||
| 51 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \ | ||
| 52 | F(FunctionName, Parameters, ReturnValue) | ||
| 53 | #define F(FunctionName, Parameters, ReturnValue) ReturnValue FunctionName Parameters; | ||
| 54 | ANDROID_STORAGE_FUNCTIONS(FS) | ||
| 55 | #undef F | ||
| 56 | #undef FS | ||
| 57 | |||
| 58 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ | ||
| 59 | F(FunctionName, ReturnValue) | ||
| 60 | #define F(FunctionName, ReturnValue) ReturnValue FunctionName(const std::string& filepath); | ||
| 61 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||
| 62 | #undef F | ||
| 63 | #undef FR | ||
| 64 | |||
| 65 | } // namespace Common::FS::Android | ||
diff --git a/src/common/fs/fs_paths.h b/src/common/fs/fs_paths.h index c77c112f1..61bac9eba 100644 --- a/src/common/fs/fs_paths.h +++ b/src/common/fs/fs_paths.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | // Sub-directories contained within a yuzu data directory | 11 | // Sub-directories contained within a yuzu data directory |
| 12 | 12 | ||
| 13 | #define AMIIBO_DIR "amiibo" | ||
| 13 | #define CACHE_DIR "cache" | 14 | #define CACHE_DIR "cache" |
| 14 | #define CONFIG_DIR "config" | 15 | #define CONFIG_DIR "config" |
| 15 | #define DUMP_DIR "dump" | 16 | #define DUMP_DIR "dump" |
diff --git a/src/common/fs/fs_types.h b/src/common/fs/fs_types.h index 5a4090c19..900f85d24 100644 --- a/src/common/fs/fs_types.h +++ b/src/common/fs/fs_types.h | |||
| @@ -66,6 +66,6 @@ DECLARE_ENUM_FLAG_OPERATORS(DirEntryFilter); | |||
| 66 | * @returns A boolean value. | 66 | * @returns A boolean value. |
| 67 | * Return true to indicate whether the callback is successful, false otherwise. | 67 | * Return true to indicate whether the callback is successful, false otherwise. |
| 68 | */ | 68 | */ |
| 69 | using DirEntryCallable = std::function<bool(const std::filesystem::path& path)>; | 69 | using DirEntryCallable = std::function<bool(const std::filesystem::directory_entry& entry)>; |
| 70 | 70 | ||
| 71 | } // namespace Common::FS | 71 | } // namespace Common::FS |
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index defa3e918..d71cfacc6 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp | |||
| @@ -6,6 +6,9 @@ | |||
| 6 | #include <unordered_map> | 6 | #include <unordered_map> |
| 7 | 7 | ||
| 8 | #include "common/fs/fs.h" | 8 | #include "common/fs/fs.h" |
| 9 | #ifdef ANDROID | ||
| 10 | #include "common/fs/fs_android.h" | ||
| 11 | #endif | ||
| 9 | #include "common/fs/fs_paths.h" | 12 | #include "common/fs/fs_paths.h" |
| 10 | #include "common/fs/path_util.h" | 13 | #include "common/fs/path_util.h" |
| 11 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| @@ -80,9 +83,7 @@ public: | |||
| 80 | yuzu_paths.insert_or_assign(yuzu_path, new_path); | 83 | yuzu_paths.insert_or_assign(yuzu_path, new_path); |
| 81 | } | 84 | } |
| 82 | 85 | ||
| 83 | private: | 86 | void Reinitialize(fs::path yuzu_path = {}) { |
| 84 | PathManagerImpl() { | ||
| 85 | fs::path yuzu_path; | ||
| 86 | fs::path yuzu_path_cache; | 87 | fs::path yuzu_path_cache; |
| 87 | fs::path yuzu_path_config; | 88 | fs::path yuzu_path_config; |
| 88 | 89 | ||
| @@ -95,6 +96,10 @@ private: | |||
| 95 | 96 | ||
| 96 | yuzu_path_cache = yuzu_path / CACHE_DIR; | 97 | yuzu_path_cache = yuzu_path / CACHE_DIR; |
| 97 | yuzu_path_config = yuzu_path / CONFIG_DIR; | 98 | yuzu_path_config = yuzu_path / CONFIG_DIR; |
| 99 | #elif ANDROID | ||
| 100 | ASSERT(!yuzu_path.empty()); | ||
| 101 | yuzu_path_cache = yuzu_path / CACHE_DIR; | ||
| 102 | yuzu_path_config = yuzu_path / CONFIG_DIR; | ||
| 98 | #else | 103 | #else |
| 99 | yuzu_path = GetCurrentDir() / PORTABLE_DIR; | 104 | yuzu_path = GetCurrentDir() / PORTABLE_DIR; |
| 100 | 105 | ||
| @@ -109,6 +114,7 @@ private: | |||
| 109 | #endif | 114 | #endif |
| 110 | 115 | ||
| 111 | GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path); | 116 | GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path); |
| 117 | GenerateYuzuPath(YuzuPath::AmiiboDir, yuzu_path / AMIIBO_DIR); | ||
| 112 | GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache); | 118 | GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache); |
| 113 | GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config); | 119 | GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config); |
| 114 | GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR); | 120 | GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR); |
| @@ -122,6 +128,11 @@ private: | |||
| 122 | GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR); | 128 | GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR); |
| 123 | } | 129 | } |
| 124 | 130 | ||
| 131 | private: | ||
| 132 | PathManagerImpl() { | ||
| 133 | Reinitialize(); | ||
| 134 | } | ||
| 135 | |||
| 125 | ~PathManagerImpl() = default; | 136 | ~PathManagerImpl() = default; |
| 126 | 137 | ||
| 127 | void GenerateYuzuPath(YuzuPath yuzu_path, const fs::path& new_path) { | 138 | void GenerateYuzuPath(YuzuPath yuzu_path, const fs::path& new_path) { |
| @@ -210,6 +221,10 @@ fs::path RemoveTrailingSeparators(const fs::path& path) { | |||
| 210 | return fs::path{string_path}; | 221 | return fs::path{string_path}; |
| 211 | } | 222 | } |
| 212 | 223 | ||
| 224 | void SetAppDirectory(const std::string& app_directory) { | ||
| 225 | PathManagerImpl::GetInstance().Reinitialize(app_directory); | ||
| 226 | } | ||
| 227 | |||
| 213 | const fs::path& GetYuzuPath(YuzuPath yuzu_path) { | 228 | const fs::path& GetYuzuPath(YuzuPath yuzu_path) { |
| 214 | return PathManagerImpl::GetInstance().GetYuzuPathImpl(yuzu_path); | 229 | return PathManagerImpl::GetInstance().GetYuzuPathImpl(yuzu_path); |
| 215 | } | 230 | } |
| @@ -350,6 +365,12 @@ std::vector<std::string> SplitPathComponents(std::string_view filename) { | |||
| 350 | 365 | ||
| 351 | std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) { | 366 | std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) { |
| 352 | std::string path(path_); | 367 | std::string path(path_); |
| 368 | #ifdef ANDROID | ||
| 369 | if (Android::IsContentUri(path)) { | ||
| 370 | return path; | ||
| 371 | } | ||
| 372 | #endif // ANDROID | ||
| 373 | |||
| 353 | char type1 = directory_separator == DirectorySeparator::BackwardSlash ? '/' : '\\'; | 374 | char type1 = directory_separator == DirectorySeparator::BackwardSlash ? '/' : '\\'; |
| 354 | char type2 = directory_separator == DirectorySeparator::BackwardSlash ? '\\' : '/'; | 375 | char type2 = directory_separator == DirectorySeparator::BackwardSlash ? '\\' : '/'; |
| 355 | 376 | ||
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h index 13d713f1e..ba28964d0 100644 --- a/src/common/fs/path_util.h +++ b/src/common/fs/path_util.h | |||
| @@ -12,6 +12,7 @@ namespace Common::FS { | |||
| 12 | 12 | ||
| 13 | enum class YuzuPath { | 13 | enum class YuzuPath { |
| 14 | YuzuDir, // Where yuzu stores its data. | 14 | YuzuDir, // Where yuzu stores its data. |
| 15 | AmiiboDir, // Where Amiibo backups are stored. | ||
| 15 | CacheDir, // Where cached filesystem data is stored. | 16 | CacheDir, // Where cached filesystem data is stored. |
| 16 | ConfigDir, // Where config files are stored. | 17 | ConfigDir, // Where config files are stored. |
| 17 | DumpDir, // Where dumped data is stored. | 18 | DumpDir, // Where dumped data is stored. |
| @@ -181,6 +182,14 @@ template <typename Path> | |||
| 181 | #endif | 182 | #endif |
| 182 | 183 | ||
| 183 | /** | 184 | /** |
| 185 | * Sets the directory used for application storage. Used on Android where we do not know internal | ||
| 186 | * storage until informed by the frontend. | ||
| 187 | * | ||
| 188 | * @param app_directory Directory to use for application storage. | ||
| 189 | */ | ||
| 190 | void SetAppDirectory(const std::string& app_directory); | ||
| 191 | |||
| 192 | /** | ||
| 184 | * Gets the filesystem path associated with the YuzuPath enum. | 193 | * Gets the filesystem path associated with the YuzuPath enum. |
| 185 | * | 194 | * |
| 186 | * @param yuzu_path YuzuPath enum | 195 | * @param yuzu_path YuzuPath enum |