diff --git a/nx/include/switch/runtime/devices/fs_dev.h b/nx/include/switch/runtime/devices/fs_dev.h index da17640b..05ab9329 100644 --- a/nx/include/switch/runtime/devices/fs_dev.h +++ b/nx/include/switch/runtime/devices/fs_dev.h @@ -42,6 +42,9 @@ FsFileSystem* fsdevGetDeviceFileSystem(const char *name); /// Returns the FsFileSystem for the default device (SD card), if mounted. Used internally by romfs_dev. FsFileSystem* fsdevGetDefaultFileSystem(void); +/// Writes the FS-path to outpath (which has buffer size FS_MAX_PATH), for the input device path. The FsFileSystem is also written to device when not NULL. +int fsdevTranslatePath(const char *path, FsFileSystem** device, char *outpath); + /// This calls fsFsSetArchiveBit on the filesystem specified by the input absolute path. Result fsdevSetArchiveBit(const char *path); diff --git a/nx/include/switch/runtime/devices/romfs_dev.h b/nx/include/switch/runtime/devices/romfs_dev.h index d5f34166..c5e7b8c8 100644 --- a/nx/include/switch/runtime/devices/romfs_dev.h +++ b/nx/include/switch/runtime/devices/romfs_dev.h @@ -84,6 +84,14 @@ static inline Result romfsInitFromStorage(FsStorage storage, u64 offset) return romfsMountFromStorage(storage, offset, "romfs"); } +/** + * @brief Mounts RomFS from a file path in a mounted fsdev device. + * @param path File path. + * @param offset Offset of the RomFS within the file. + * @param name Device mount name. + */ +Result romfsMountFromFsdev(const char *path, u64 offset, const char *name); + /** * @brief Mounts RomFS from a system data archive. * @param dataId Title ID of system data archive to mount. diff --git a/nx/source/runtime/devices/fs_dev.c b/nx/source/runtime/devices/fs_dev.c index ca08ae4e..bce39331 100644 --- a/nx/source/runtime/devices/fs_dev.c +++ b/nx/source/runtime/devices/fs_dev.c @@ -487,6 +487,17 @@ FsFileSystem* fsdevGetDefaultFileSystem(void) return &fsdev_fsdevices[fsdev_fsdevice_default].fs; } +int fsdevTranslatePath(const char *path, FsFileSystem** device, char *outpath) +{ + fsdev_fsdevice *tmpdev = NULL; + + int ret = fsdev_getfspath(_REENT, path, &tmpdev, outpath); + if(ret==-1)return ret; + + if(device)*device = &tmpdev->fs; + return ret; +} + /*! Open a file * * @param[in,out] r newlib reentrancy struct diff --git a/nx/source/runtime/devices/romfs_dev.c b/nx/source/runtime/devices/romfs_dev.c index 51e65c96..3468ec7c 100644 --- a/nx/source/runtime/devices/romfs_dev.c +++ b/nx/source/runtime/devices/romfs_dev.c @@ -15,11 +15,16 @@ #include "runtime/env.h" #include "nro.h" +typedef enum { + RomfsSource_FsFile, + RomfsSource_FsStorage, +} RomfsSource; + typedef struct romfs_mount { devoptab_t device; bool setup; - bool fd_type; + RomfsSource fd_type; s32 id; FsFile fd; FsStorage fd_storage; @@ -49,11 +54,11 @@ static ssize_t _romfs_read(romfs_mount *mount, u64 offset, void* buffer, u64 siz u64 pos = mount->offset + offset; size_t read = 0; Result rc = 0; - if(!mount->fd_type) + if(mount->fd_type == RomfsSource_FsFile) { rc = fsFileRead(&mount->fd, pos, buffer, size, &read); } - else + else if(mount->fd_type == RomfsSource_FsStorage) { rc = fsStorageRead(&mount->fd_storage, pos, buffer, size); read = size; @@ -189,6 +194,13 @@ static void romfs_free(romfs_mount *mount) _romfsResetMount(mount, mount->id); } +static void romfs_mountclose(romfs_mount *mount) +{ + if(mount->fd_type == RomfsSource_FsFile)fsFileClose(&mount->fd); + if(mount->fd_type == RomfsSource_FsStorage)fsStorageClose(&mount->fd_storage); + romfs_free(mount); +} + Result romfsMount(const char *name) { romfs_mount *mount = romfs_alloc(); @@ -199,7 +211,7 @@ Result romfsMount(const char *name) { // RomFS embedded in a NRO - mount->fd_type = 0; + mount->fd_type = RomfsSource_FsFile; FsFileSystem *sdfs = fsdevGetDefaultFileSystem(); if(sdfs==NULL) @@ -260,7 +272,7 @@ Result romfsMount(const char *name) { // Regular RomFS - mount->fd_type = 1; + mount->fd_type = RomfsSource_FsStorage; Result rc = fsOpenDataStorageByCurrentProcess(&mount->fd_storage); if (R_FAILED(rc)) @@ -275,9 +287,7 @@ Result romfsMount(const char *name) return romfsMountCommon(name, mount); _fail0: - if(!mount->fd_type)fsFileClose(&mount->fd); - if(mount->fd_type)fsStorageClose(&mount->fd_storage); - romfs_free(mount); + romfs_mountclose(mount); return 10; } @@ -287,7 +297,7 @@ Result romfsMountFromFile(FsFile file, u64 offset, const char *name) if(mount == NULL) return 99; - mount->fd_type = 0; + mount->fd_type = RomfsSource_FsFile; mount->fd = file; mount->offset = offset; @@ -300,13 +310,40 @@ Result romfsMountFromStorage(FsStorage storage, u64 offset, const char *name) if(mount == NULL) return 99; - mount->fd_type = 1; + mount->fd_type = RomfsSource_FsStorage; mount->fd_storage = storage; mount->offset = offset; return romfsMountCommon(name, mount); } +Result romfsMountFromFsdev(const char *path, u64 offset, const char *name) +{ + FsFileSystem *tmpfs = NULL; + char filepath[FS_MAX_PATH]; + + memset(filepath, 0, sizeof(filepath)); + + if(fsdevTranslatePath(path, &tmpfs, filepath)==-1) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + + romfs_mount *mount = romfs_alloc(); + if(mount == NULL) + return 99; + + mount->fd_type = RomfsSource_FsFile; + mount->offset = offset; + + Result rc = fsFsOpenFile(tmpfs, filepath, FS_OPEN_READ, &mount->fd); + if (R_FAILED(rc)) + { + romfs_free(mount); + return rc; + } + + return romfsMountCommon(name, mount); +} + Result romfsMountFromDataArchive(u64 dataId, FsStorageId storageId, const char *name) { FsStorage storage; @@ -358,9 +395,7 @@ Result romfsMountCommon(const char *name, romfs_mount *mount) return 0; fail: - if(!mount->fd_type)fsFileClose(&mount->fd); - if(mount->fd_type)fsStorageClose(&mount->fd_storage); - romfs_free(mount); + romfs_mountclose(mount); return 10; } @@ -377,9 +412,7 @@ Result romfsUnmount(const char *name) if (mount == NULL) return -1; - if(!mount->fd_type)fsFileClose(&mount->fd); - if(mount->fd_type)fsStorageClose(&mount->fd_storage); - romfs_free(mount); + romfs_mountclose(mount); return 0; }