Remove incompatible fakelib libraries before mounting PPR PKG backports

This commit is contained in:
Roman Tarasov committed 2026-10-03 13:37:27 +03:00
1 parent cb6d2bece1
commit d70b43e5d4
2 files changed
+80

No files matched your search

+1
View File
@@ -188,6 +188,7 @@ Backport overlay behavior:
- If multiple scan paths provide the same title backport, the game's own scan path wins; otherwise scan path order is used, followed by the internal fallback.
- ShadowMount+ checks the selected backport for `fakelib2` and then `fakelib`; if neither exists, it checks the original game source in the same order. The selected directory is mounted into the running game's sandbox `common/lib`. A selected `fakelib2` is always mounted directly and exclusively: neither emulator updates nor the global fakelib can replace or supplement it.
- For folder/image games, `update_emulators=1` makes matching files from `emulators_path` replace files in the selected game fakelib, except when `fakelib2` is selected. Installed PKGs never compose `emulators_path` into their fakelib. The cache is refreshed when its sources change and expires after seven days without a game launch.
- Before preparing and mounting fakelib for an installed PPR PKG, ShadowMount+ deletes `libSceAmpr.sprx`, `libScePlayGo.sprx` and `libkernel.sprx` from the selected `/data/homebrew/backports/<TITLE_ID>/fakelib`. Missing files are harmless skips; a deletion failure stops the fakelib mount.
- With `auto_update_ampr=1`, ShadowMount+ checks for AMPR updates 30 seconds after startup and every four hours. It downloads a missing or newer emulator and displays a notification after a successful update.
- The backport notification adds `Emulators updated` when emulator files are updated for the launched game.
- If both global and per-game fakelib exist, they are combined in the game cache according to `global_fakelib_priority`, unless the selected backport contains `fakelib2`. Without a per-game fakelib, the global folder is mounted directly.
+79
View File
@@ -1323,6 +1323,79 @@ static bool cleanup_fakelib_mount(void) {
return true;
}
static bool cleanup_ppr_backport_fakelib(const char *title_id,
const char *sandbox_app0_path) {
char backport_path[MAX_PATH];
char expected_path[MAX_PATH];
(void)snprintf(expected_path, sizeof(expected_path),
DEFAULT_BACKPORT_SCAN_PATH "/backports/%s", title_id);
if (!resolve_backport_path_for_title(title_id, NULL, backport_path) ||
strcmp(backport_path, expected_path) != 0) {
return true;
}
struct statfs fs;
if (statfs(sandbox_app0_path, &fs) != 0 ||
strcmp(fs.f_fstypename, "nsfs") != 0 ||
strcmp(fs.f_mntonname, sandbox_app0_path) != 0) {
return true;
}
char package_path[MAX_PATH];
(void)snprintf(package_path, sizeof(package_path),
"/mnt/sandbox/pfsmnt/%s-app0", title_id);
if (statfs(package_path, &fs) != 0 ||
strcmp(fs.f_fstypename, "ppr_pfs") != 0 ||
strcmp(fs.f_mntonname, package_path) != 0) {
return true;
}
int backport_fd = open(backport_path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
if (backport_fd < 0) {
int saved_errno = errno;
if (saved_errno == ENOENT)
return true;
log_debug(" [FAKELIB] cannot open PPR backport %s: %s",
backport_path, strerror(saved_errno));
errno = saved_errno;
return false;
}
int fakelib_fd = openat(backport_fd, "fakelib",
O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
int saved_errno = errno;
close(backport_fd);
if (fakelib_fd < 0) {
errno = saved_errno;
if (errno == ENOENT)
return true;
log_debug(" [FAKELIB] cannot open PPR fakelib %s/fakelib: %s",
backport_path, strerror(saved_errno));
errno = saved_errno;
return false;
}
static const char *const filenames[] = {
"libSceAmpr.sprx", "libScePlayGo.sprx", "libkernel.sprx"};
size_t removed = 0;
for (size_t i = 0; i < sizeof(filenames) / sizeof(filenames[0]); ++i) {
if (unlinkat(fakelib_fd, filenames[i], 0) == 0) {
removed++;
} else if (errno != ENOENT) {
saved_errno = errno;
close(fakelib_fd);
log_debug(" [FAKELIB] cannot remove PPR library %s/fakelib/%s: %s",
backport_path, filenames[i], strerror(saved_errno));
errno = saved_errno;
return false;
}
}
close(fakelib_fd);
if (removed > 0) {
log_debug(" [FAKELIB] removed %zu PPR libraries from %s/fakelib",
removed, backport_path);
}
return true;
}
static bool mount_fakelib_for_game_locked(pid_t pid, const char *title_id,
bool notify_user) {
if (!title_id || !is_supported_game_title_id(title_id)) {
@@ -1375,6 +1448,12 @@ static bool mount_fakelib_for_game_locked(pid_t pid, const char *title_id,
// app0. Prefer the external backport source directly and never add files
// from emulators_path for installed packages.
pthread_mutex_lock(&g_fakelib_cache_mutex);
if (!cleanup_ppr_backport_fakelib(title_id, sandbox_app0_path)) {
int saved_errno = errno;
pthread_mutex_unlock(&g_fakelib_cache_mutex);
errno = saved_errno;
return false;
}
prepare_title_cache(title_id, sandbox_app0_path, true, false);
pthread_mutex_unlock(&g_fakelib_cache_mutex);
}