diff --git a/games/totk/runtime/romfs.c b/games/totk/runtime/romfs.c index 220242fdf..ff4594107 100644 --- a/games/totk/runtime/romfs.c +++ b/games/totk/runtime/romfs.c @@ -283,8 +283,11 @@ void runtime_fs_init(void) { fprintf(stderr,"[totk] native read-only RomFS ready: %llu files\n",(unsigned long long)file_count); } static int path_ok(const char *p) {return romfs_path_valid_relative(p);} -static const char *rom_path(const char *path) { - for(unsigned i=0;i4094)return NOT_FOUND; + char normalized[4096];const char *p=rom_path(path,normalized,sizeof normalized);if(!p)return NOT_FOUND;size_t n=strlen(p);if(n>4094)return NOT_FOUND; char prefix[4096];memcpy(prefix,p,n);prefix[n]='/';prefix[n+1]=0; uint64_t i=lower(prefix),seen=0;char last[4096]=""; for(;ipath,O_RDONLY|O_CLOEXEC);struct stat st; if(fd<0||fstat(fd,&st)!=0||(uint64_t)st.st_size!=o->size||st.st_dev!=o->dev||st.st_ino!=o->ino||st.st_mtimespec.tv_sec!=o->mtime.tv_sec||st.st_mtimespec.tv_nsec!=o->mtime.tv_nsec){ @@ -356,7 +359,7 @@ unsigned runtime_romfs_read(uint64_t *out,uint64_t h,int64_t offset,void *buffer unsigned runtime_romfs_size(int64_t *out,uint64_t h) {Entry e;if(!out||!handle_entry(h,&e))return INVALID;int fd;uint64_t base,size;handle_source(h,&e,&fd,&base,&size);*out=(int64_t)size;return 0;} void runtime_romfs_close(uint64_t h) {Entry e;if(!handle_entry(h,&e))runtime_fail("close invalid file handle");uint64_t j=h-0x100000000ULL;pthread_mutex_lock(&lock);int fd=handle_ovl[j]?handle_fd[j]:-1;handles[j]=0;handle_ovl[j]=0;handle_fd[j]=-1;pthread_mutex_unlock(&lock);if(fd>=0)close(fd);} unsigned runtime_romfs_entry_type(int *out,const char *path) { - if(!out)return INVALID;const char *p=rom_path(path);if(!p)return NOT_FOUND;if(file_index(p)!=UINT64_MAX){*out=1;return 0;} + if(!out)return INVALID;char normalized[4096];const char *p=rom_path(path,normalized,sizeof normalized);if(!p)return NOT_FOUND;if(file_index(p)!=UINT64_MAX){*out=1;return 0;} char dir[4096];if(snprintf(dir,sizeof(dir),"%s/",p)>=(int)sizeof(dir))return INVALID;if(folder_exists(dir)){*out=0;return 0;}return NOT_FOUND; } int runtime_romfs_owns(const char *path) {for(unsigned i=0;i= capacity) return NULL; + scratch[used++] = *p; + if (*p == '/') while (p[1] == '/') ++p; + } + scratch[used] = '\0'; + return romfs_path_valid_relative(scratch) ? scratch : NULL; } diff --git a/tests/test_romfs_paths.c b/tests/test_romfs_paths.c index 0bee84ff9..ad3a79b2b 100644 --- a/tests/test_romfs_paths.c +++ b/tests/test_romfs_paths.c @@ -34,7 +34,7 @@ int main(void) { {"rom", "rom://dir\\file", NULL}, }; for (size_t i = 0; i < sizeof cases / sizeof cases[0]; ++i) { - const char *result = romfs_path_relative(cases[i].mount, cases[i].path); + const char *result = romfs_path_relative(cases[i].mount, cases[i].path, NULL, 0); if ((!result != !cases[i].expected) || (result && strcmp(result, cases[i].expected))) { fprintf(stderr, "case %zu failed: %s -> %s (expected %s)\n", i, @@ -44,6 +44,17 @@ int main(void) { return 1; } } + char normalized[128]; + const char *voice = romfs_path_relative("content", "content://Voice/Resource//Stream/opening.bwav", + normalized, sizeof normalized); + if (!voice || strcmp(voice, "Voice/Resource/Stream/opening.bwav") || + romfs_path_relative("content", "content://Voice//../file", normalized, sizeof normalized) || + romfs_path_relative("content", "content://Voice//./file", normalized, sizeof normalized) || + romfs_path_relative("content", "content://Voice//dir\\file", normalized, sizeof normalized) || + romfs_path_relative("content", "content://Voice//file", normalized, 10)) { + fputs("OoT audio path normalization failed\n", stderr); + return 1; + } printf("PASS: %zu RomFS path cases\n", sizeof cases / sizeof cases[0]); return 0; }