From a2de96a4d1eab0df3d38c45aed37c1368eabf65f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 8 Mar 2026 10:09:48 +0100 Subject: [PATCH] iOS: Try to avoid leaking file bookmarks. Don't try to install zips into iCloud folder. --- Common/File/FileUtil.cpp | 6 ++++++ Core/FileLoaders/LocalFileLoader.cpp | 24 +++++++++++++++++++++--- Core/Loaders.cpp | 10 +--------- Core/Util/DarwinFileSystemServices.mm | 7 ++++--- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index fe081ea2bd..53a86f54f1 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -1495,6 +1495,12 @@ bool IsProbablyInDownloadsFolder(const Path &filename) { default: break; } +#if PPSSPP_PLATFORM(IOS) + if (filename.FilePathContainsNoCase("com~apple~CloudDocs")) { + return true; + } +#endif + return filename.FilePathContainsNoCase("download"); } diff --git a/Core/FileLoaders/LocalFileLoader.cpp b/Core/FileLoaders/LocalFileLoader.cpp index 290dacec89..097456ab12 100644 --- a/Core/FileLoaders/LocalFileLoader.cpp +++ b/Core/FileLoaders/LocalFileLoader.cpp @@ -21,6 +21,7 @@ #include "Common/Log.h" #include "Common/File/FileUtil.h" #include "Common/File/DirListing.h" +#include "Core/Util/DarwinFileSystemServices.h" #include "Core/FileLoaders/LocalFileLoader.h" #if PPSSPP_PLATFORM(ANDROID) @@ -77,23 +78,37 @@ LocalFileLoader::LocalFileLoader(const Path &filename) } #endif + #if defined(HAVE_LIBRETRO_VFS) file_ = File::OpenCFile(filename, "rb"); if (!file_) { + ERROR_LOG(Log::FileSystem, "LocalFileLoader: failed to open file: '%s'", filename.c_str()); return; } filesize_ = File::GetFileSize(file_); +#elif PPSSPP_PLATFORM(IOS) + if (!File::Exists(filename)) { + // Try to "unlock" the path before the file loader hits it + Path newFilename = DarwinFileSystemServices::reauthorizeBookmarkByPath(filename); + if (!newFilename.empty()) { + filename_ = newFilename; + } + } + fd_ = open(filename_.c_str(), O_RDONLY | O_CLOEXEC); + if (fd_ == -1) { + ERROR_LOG(Log::FileSystem, "LocalFileLoader: failed to open file: '%s'", filename_.c_str()); + return; + } + DetectSizeFd(); #elif !defined(_WIN32) - fd_ = open(filename.c_str(), O_RDONLY | O_CLOEXEC); if (fd_ == -1) { + ERROR_LOG(Log::FileSystem, "LocalFileLoader: failed to open file: '%s'", filename.c_str()); return; } DetectSizeFd(); - #else // _WIN32 - const DWORD access = GENERIC_READ, share = FILE_SHARE_READ, mode = OPEN_EXISTING, flags = FILE_ATTRIBUTE_NORMAL; #if PPSSPP_PLATFORM(UWP) handle_ = CreateFile2FromAppW(filename.ToWString().c_str(), access, share, mode, nullptr); @@ -121,6 +136,9 @@ LocalFileLoader::~LocalFileLoader() { if (file_ != nullptr) { fclose(file_); } +#elif PPSSPP_PLATFORM(IOS) + close(fd_); + DarwinFileSystemServices::stopAccessingPath(filename_); #elif !defined(_WIN32) if (fd_ != -1) { close(fd_); diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index a67bee12d7..5b16599f75 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -58,15 +58,7 @@ FileLoader *ConstructFileLoader(const Path &filename) { } return new CachingFileLoader(baseLoader); } - #if PPSSPP_PLATFORM(IOS) - if (!File::Exists(filename)) { - // Try to "unlock" the path before the file loader hits it - Path newFilename = DarwinFileSystemServices::reauthorizeBookmarkByPath(filename); - if (!newFilename.empty()) { - return new LocalFileLoader(newFilename); - } - } - #endif + return new LocalFileLoader(filename); } diff --git a/Core/Util/DarwinFileSystemServices.mm b/Core/Util/DarwinFileSystemServices.mm index ddc8952750..16e43e79a8 100644 --- a/Core/Util/DarwinFileSystemServices.mm +++ b/Core/Util/DarwinFileSystemServices.mm @@ -70,8 +70,8 @@ static void addBookmark(NSURL *url); BOOL success = [url startAccessingSecurityScopedResource]; if (success) { // 2. Pass the path to PPSSPP - // Note: In a real app, you'd want to call stopAccessingSecurityScopedResource - // when the game is closed, otherwise you "leak" kernel permissions. + // You should call stopAccessingSecurityScopedResource + // when the file is closed, otherwise you "leak" kernel permissions. self.panelCallback(true, Path(url.path.UTF8String)); } else { ERROR_LOG(Log::System, "Failed to start accessing security scoped resource for: %s", url.path.UTF8String); @@ -139,6 +139,7 @@ static void addBookmark(NSURL *url) { if (accessStarted) [url stopAccessingSecurityScopedResource]; } } + Path DarwinFileSystemServices::reauthorizeBookmarkByPath(const Path &pathStr) { INFO_LOG(Log::System, "Darwin: Reauthorizing [%s]", pathStr.c_str()); @@ -207,7 +208,7 @@ void DarwinFileSystemServices::stopAccessingPath(const Path &pathStr) { [url stopAccessingSecurityScopedResource]; activeAccessTokens.erase(it); - } + } } void DarwinFileSystemServices::terminate() {