Fix ramfs demangling when a link mount is made

This commit is contained in:
Will Toohey 2026-02-23 14:42:46 +10:00
parent e74b841909
commit 5b02a03240
2 changed files with 74 additions and 0 deletions

View File

@ -48,6 +48,7 @@ typedef struct {
AVS_FILE handle;
void* buffer;
optional<string> ramfs_path;
optional<string> link_path;
optional<string> mounted_path;
} file_cleanup_info_t;
@ -81,6 +82,9 @@ void ramfs_demangler_on_fs_open(const std::string& path, AVS_FILE open_result) {
if (cleanup.ramfs_path) {
ramfs_map.erase(*cleanup.ramfs_path);
}
if (cleanup.link_path) {
ramfs_map.erase(*cleanup.link_path);
}
if (cleanup.mounted_path) {
mangling_map.erase(*cleanup.mounted_path);
}
@ -150,6 +154,19 @@ void ramfs_demangler_on_fs_mount(const char* mountpoint, const char* fsroot, con
}
}
}
else if (!strcmp(fstype, "link")) {
auto find = ramfs_map.find(fsroot);
if (find != ramfs_map.end()) {
auto orig_path = *find;
log_verbose("link mount mapped to %s", orig_path.c_str());
ramfs_map[mountpoint] = orig_path;
auto cleanup = cleanup_map.find(orig_path);
if (cleanup != cleanup_map.end()) {
cleanup->second.link_path = mountpoint;
}
}
}
else if (!strcmp(fstype, "imagefs")) {
auto find = ramfs_map.longest_prefix(fsroot);
if (find != ramfs_map.end()) {

View File

@ -7,8 +7,10 @@
#include "imagefs.hpp"
#include "avs_standalone.hpp"
#include "modpath_handler.h"
#include "ramfs_demangler.h"
#include "3rd_party/rapidxml_print.hpp"
#include "src/utils.hpp"
using ::testing::Contains;
using ::testing::Optional;
@ -197,6 +199,61 @@ TEST(Xml, MergingWorks) {
ASSERT_EQ(node, nullptr);
}
TEST(RamFs, DemanglingWorks) {
AVS_FILE fake_handle = 9999;
uint8_t fake_buffer[1];
ramfs_demangler_on_fs_open("./data/test.ifs", fake_handle);
ramfs_demangler_on_fs_read(fake_handle, fake_buffer);
char* flags = snprintf_auto("base=0x%llx", (unsigned long long)(uintptr_t)fake_buffer);
ramfs_demangler_on_fs_mount("/sd0", "test.ifs", "ramfs", flags);
free(flags);
ramfs_demangler_on_fs_mount("/game/test", "/sd0/test.ifs", "imagefs", nullptr);
std::string path = "/game/test/somefile";
ramfs_demangler_demangle_if_possible(path);
EXPECT_EQ(path, "./data/test.ifs/somefile");
// re-open triggers cleanup, not explicit unmount
ramfs_demangler_on_fs_open("./data/test.ifs", fake_handle);
path = "/game/test/somefile";
ramfs_demangler_demangle_if_possible(path);
EXPECT_EQ(path, "/game/test/somefile");
}
TEST(RamFs, DemanglingWorksNabla) {
// Nabla has an extra indirection:
// M:opening /data/graphics/ver07/logo.ifs mode 1 flags 420
// M:mounting image.bin to /mnt/bm2d/rmp_89_2714881 with type ramfs and args base=0x00000000d2435060,size=0x8984f0,mode=ro
// M:ramfs mount mapped to /data/graphics/ver07/logo.ifs
// M:mounting /mnt/bm2d/rmp_89_2714881/image.bin to /mnt/bm2d/rfs88r89/logo.ifs with type link and args
// M:mounting /mnt/bm2d/rfs88r89/logo.ifs to /mnt/bm2d/ngp88/logo.ifs with type imagefs and args (null)
// M:imagefs mount mapped to /mnt/bm2d/rfs88r89/logo.ifs
// M:opening /mnt/bm2d/rfs88r89/logo.ifs mode 1 flags 420
AVS_FILE fake_handle = 9999;
uint8_t fake_buffer[1];
ramfs_demangler_on_fs_open("/data/graphics/ver07/logo.ifs", fake_handle);
ramfs_demangler_on_fs_read(fake_handle, fake_buffer);
char* flags = snprintf_auto("base=0x%llx", (unsigned long long)(uintptr_t)fake_buffer);
ramfs_demangler_on_fs_mount("/mnt/bm2d/rmp_89_2714881", "image.bin", "ramfs", flags);
free(flags);
ramfs_demangler_on_fs_mount("/mnt/bm2d/rfs88r89/logo.ifs", "/mnt/bm2d/rmp_89_2714881/image.bin", "link", "");
ramfs_demangler_on_fs_mount("/mnt/bm2d/ngp88/logo.ifs", "/mnt/bm2d/rfs88r89/logo.ifs", "imagefs", nullptr);
ramfs_demangler_on_fs_open("/mnt/bm2d/rfs88r89/logo.ifs", 9001);
std::string path = "/mnt/bm2d/ngp88/logo.ifs/tex/texturelist.xml";
ramfs_demangler_demangle_if_possible(path);
EXPECT_EQ(path, "/data/graphics/ver07/logo.ifs/tex/texturelist.xml");
}
TEST(Regression, BeatStreamAfpXml) {
// M:mounting /data2/graphic/psd_result.ifs to /afp22/data2/graphic/psd_result.ifs with type imagefs and args (null)
int mnt = hook_avs_fs_mount("/afp22/data2/graphic/psd_result.ifs", "/data2/graphic/psd_result.ifs", "imagefs", nullptr);