Major cleanup and refactor of fsdev and romfsdev, see details:

fsdev:
- Removed fsdevGetDefaultFileSystem and default-fs handling
- Refactored CWD support to have (dynamically allocated) per-device CWDs
  (CWD support as a whole can be turned off with __nx_fsdev_support_cwd)
- Optimized calls by passing pointer to device through r->deviceData
- Use the per-thread path buffer directly as the argument to FS functions
- Removed redundant cross-device check in fsdev_rename
- Fixed string comparison logic in fsdevFindDevice
- fsdev_fixpath now accepts an input device in order to skip device
  lookup (extensively used along with r->deviceData)
- Mounting a filesystem now automatically sets the default device
  if there wasn't any previous default device (or if it's stdnull)
- fsdevMountSdmc no longer sets cwd to the folder containing the
  executable - this logic was moved to a new internal function
  called on startup by default (and it is now disabled for NSOs)
- Other miscellaneous optimizations

romfsdev:
- Cleaned up romfsMount* functions, removed unused/unnecessary logic
- Changed romfsMount* functions to return real result codes
- Renamed romfsMount to romfsMountSelf and improved documentation
- Removed romfsInitFromFile and romfsInitFromStorage (use Mount instead)
- Added documentation for romfsInit and romfsExit
This commit is contained in:
fincs 2019-10-20 22:21:30 +02:00
parent 0403c988ba
commit c77b88d868
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
5 changed files with 212 additions and 288 deletions

View File

@ -27,7 +27,7 @@ NX_CONSTEXPR FsDirectoryEntry* fsdevDirGetEntries(fsdev_dir_t *dir)
return (FsDirectoryEntry*)(void*)(dir+1);
}
/// Initializes and mounts the sdmc device if accessible. Also initializes current working directory to point to the folder containing the path to the executable (argv[0]), if it is provided by the environment.
/// Initializes and mounts the sdmc device if accessible.
Result fsdevMountSdmc(void);
/// Mounts the input fs with the specified device name. fsdev will handle closing the fs when required, including when fsdevMountDevice() fails.
@ -44,9 +44,6 @@ Result fsdevCommitDevice(const char *name);
/// Returns the FsFileSystem for the specified device. Returns NULL when the specified device isn't found.
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 path (as used in stdio). The FsFileSystem is also written to device when not NULL.
int fsdevTranslatePath(const char *path, FsFileSystem** device, char *outpath);

View File

@ -53,12 +53,11 @@ typedef struct
/**
* @brief Mounts the Application's RomFS.
* @param name Device mount name.
* @remark This function is intended to be used to access one's own RomFS.
* If the application is running as NRO, it mounts the embedded RomFS section inside the NRO.
* If on the other hand it's an NSO, it behaves identically to \ref romfsMountFromCurrentProcess.
*/
Result romfsMount(const char *name);
static inline Result romfsInit(void)
{
return romfsMount("romfs");
}
Result romfsMountSelf(const char *name);
/**
* @brief Mounts RomFS from an open file.
@ -67,10 +66,6 @@ static inline Result romfsInit(void)
* @param name Device mount name.
*/
Result romfsMountFromFile(FsFile file, u64 offset, const char *name);
static inline Result romfsInitFromFile(FsFile file, u64 offset)
{
return romfsMountFromFile(file, offset, "romfs");
}
/**
* @brief Mounts RomFS from an open storage.
@ -79,10 +74,6 @@ static inline Result romfsInitFromFile(FsFile file, u64 offset)
* @param name Device mount name.
*/
Result romfsMountFromStorage(FsStorage storage, u64 offset, const char *name);
static inline Result romfsInitFromStorage(FsStorage storage, u64 offset)
{
return romfsMountFromStorage(storage, offset, "romfs");
}
/**
* @brief Mounts RomFS using the current process host title RomFS.
@ -108,8 +99,15 @@ Result romfsMountFromDataArchive(u64 dataId, FsStorageId storageId, const char *
/// Unmounts the RomFS device.
Result romfsUnmount(const char *name);
/// Wrapper for \ref romfsMountSelf with the default "romfs" device name.
static inline Result romfsInit(void)
{
return romfsMountSelf("romfs");
}
/// Wrapper for \ref romfsUnmount with the default "romfs" device name.
static inline Result romfsExit(void)
{
return romfsUnmount("romfs");
}

View File

@ -11,6 +11,7 @@
#include "runtime/devices/fs_dev.h"
#include "runtime/util/utf.h"
#include "runtime/env.h"
#include "services/fs.h"
#include "services/time.h"
@ -62,7 +63,7 @@ typedef struct
} fsdev_file_t;
/*! fsdev devoptab */
static devoptab_t
static const devoptab_t
fsdev_devoptab =
{
.structSize = sizeof(fsdev_file_t),
@ -98,20 +99,21 @@ typedef struct
s32 id;
devoptab_t device;
FsFileSystem fs;
char *cwd;
char name[32];
} fsdev_fsdevice;
static bool fsdev_initialised = false;
static s32 fsdev_fsdevice_default = -1;
static s32 fsdev_fsdevice_cwd = -1;
static s32 fsdev_fsdevice_cwd;
static __thread Result fsdev_last_result = 0;
static fsdev_fsdevice fsdev_fsdevices[32];
/*! @endcond */
static char __cwd[PATH_MAX+1] = "/";
_Static_assert((PATH_MAX+1) >= FS_MAX_PATH, "PATH_MAX is too small");
__attribute__((weak)) u32 __nx_fsdev_direntry_cache_size = 32;
__attribute__((weak)) bool __nx_fsdev_support_cwd = true;
static fsdev_fsdevice *fsdevFindDevice(const char *name)
{
@ -122,18 +124,6 @@ static fsdev_fsdevice *fsdevFindDevice(const char *name)
if(!fsdev_initialised)
return NULL;
if(name && name[0] == '/') //Return the default device.
{
if(fsdev_fsdevice_default==-1)
return NULL;
device = &fsdev_fsdevices[fsdev_fsdevice_default];
if(!device->setup)
device = NULL;
return device;
}
for(i=0; i<total; i++)
{
device = &fsdev_fsdevices[i];
@ -145,7 +135,8 @@ static fsdev_fsdevice *fsdevFindDevice(const char *name)
}
else if(device->setup) //Find the device with the input name.
{
if(strncmp(device->name, name, strlen(device->name))==0)
size_t devnamelen = strlen(device->name);
if(strncmp(device->name, name, devnamelen)==0 && (name[devnamelen]=='\0' || name[devnamelen]==':'))
return device;
}
}
@ -201,13 +192,27 @@ fsdev_fixpath(struct _reent *r,
p += units;
} while(code != 0);
fsdev_fsdevice *dev = NULL;
if(device && *device != NULL)
dev = *device;
else if(path != device_path)
dev = fsdevFindDevice(device_path);
else if(fsdev_fsdevice_cwd != -1)
dev = &fsdev_fsdevices[fsdev_fsdevice_cwd];
if(dev == NULL)
{
r->_errno = ENODEV;
return NULL;
}
if(path[0] == '/')
strncpy(__nx_dev_path_buf, path, PATH_MAX);
else
{
strncpy(__nx_dev_path_buf, __cwd, PATH_MAX);
const char* cwd = dev->cwd ? dev->cwd : "/";
strncpy(__nx_dev_path_buf, cwd, PATH_MAX);
__nx_dev_path_buf[PATH_MAX] = '\0';
strncat(__nx_dev_path_buf, path, PATH_MAX - strlen(__cwd));
strncat(__nx_dev_path_buf, path, PATH_MAX - strlen(cwd));
}
if(__nx_dev_path_buf[PATH_MAX] != 0)
@ -218,23 +223,7 @@ fsdev_fixpath(struct _reent *r,
}
if(device)
{
if(path[0] == '/')
{
*device = fsdevFindDevice(device_path);
}
else
{
*device = NULL;
if(fsdev_fsdevice_cwd != -1)
*device = &fsdev_fsdevices[fsdev_fsdevice_cwd];
}
if(*device == NULL)
{
r->_errno = ENODEV;
return NULL;
}
}
*device = dev;
return __nx_dev_path_buf;
}
@ -248,6 +237,7 @@ fsdev_getfspath(struct _reent *r,
if(fsdev_fixpath(r, path, device) == NULL)
return -1;
if(outpath != __nx_dev_path_buf)
memcpy(outpath, __nx_dev_path_buf, FS_MAX_PATH-1);
outpath[FS_MAX_PATH-1] = '\0';
@ -302,10 +292,11 @@ static void _fsdevInit(void)
memcpy(&fsdev_fsdevices[i].device, &fsdev_devoptab, sizeof(fsdev_devoptab));
fsdev_fsdevices[i].device.name = fsdev_fsdevices[i].name;
fsdev_fsdevices[i].device.dirStateSize += sizeof(FsDirectoryEntry)*__nx_fsdev_direntry_cache_size;
fsdev_fsdevices[i].device.deviceData = &fsdev_fsdevices[i];
fsdev_fsdevices[i].id = i;
}
fsdev_fsdevice_default = -1;
fsdev_fsdevice_cwd = -1;
fsdev_initialised = true;
}
}
@ -314,20 +305,14 @@ static int _fsdevMountDevice(const char *name, FsFileSystem fs, fsdev_fsdevice *
{
fsdev_fsdevice *device = NULL;
_fsdevInit(); //Ensure fsdev is initialized
if(fsdevFindDevice(name)) //Device is already mounted with the same name.
{
fsFsClose(&fs);
return -1;
}
goto _fail;
_fsdevInit(); //Ensure fsdev is initialized
device = fsdevFindDevice(NULL);
if(device==NULL)
{
fsFsClose(&fs);
return -1;
}
goto _fail;
device->fs = fs;
memset(device->name, 0, sizeof(device->name));
@ -335,17 +320,31 @@ static int _fsdevMountDevice(const char *name, FsFileSystem fs, fsdev_fsdevice *
int dev = AddDevice(&device->device);
if(dev==-1)
{
fsFsClose(&device->fs);
return dev;
}
goto _fail;
device->setup = 1;
device->cwd = __nx_fsdev_support_cwd ? malloc(FS_MAX_PATH) : NULL;
if(device->cwd!=NULL)
{
device->cwd[0] = '/';
device->cwd[1] = '\0';
}
if(fsdev_fsdevice_cwd==-1)
fsdev_fsdevice_cwd = device->id;
const devoptab_t *default_dev = GetDeviceOpTab("");
if(default_dev==NULL || strcmp(default_dev->name, "stdnull")==0)
setDefaultDevice(dev);
if(out_device)
*out_device = device;
return dev;
_fail:
fsFsClose(&fs);
return -1;
}
int fsdevMountDevice(const char *name, FsFileSystem fs)
@ -365,13 +364,11 @@ static int _fsdevUnmountDeviceStruct(fsdev_fsdevice *device)
strncat(name, ":", sizeof(name)-strlen(name)-1);
RemoveDevice(name);
free(device->cwd);
fsFsClose(&device->fs);
if(device->id == fsdev_fsdevice_default)
fsdev_fsdevice_default = -1;
if(device->id == fsdev_fsdevice_cwd)
fsdev_fsdevice_cwd = fsdev_fsdevice_default;
fsdev_fsdevice_cwd = -1;
device->setup = 0;
memset(device->name, 0, sizeof(device->name));
@ -402,7 +399,7 @@ Result fsdevCommitDevice(const char *name)
}
Result fsdevSetArchiveBit(const char *path) {
char fs_path[FS_MAX_PATH];
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = NULL;
if(fsdev_getfspath(_REENT, path, &device, fs_path)==-1)
@ -412,7 +409,7 @@ Result fsdevSetArchiveBit(const char *path) {
}
Result fsdevCreateFile(const char* path, size_t size, u32 flags) {
char fs_path[FS_MAX_PATH];
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = NULL;
if(fsdev_getfspath(_REENT, path, &device, fs_path)==-1)
@ -422,7 +419,7 @@ Result fsdevCreateFile(const char* path, size_t size, u32 flags) {
}
Result fsdevDeleteDirectoryRecursively(const char *path) {
char fs_path[FS_MAX_PATH];
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = NULL;
if(fsdev_getfspath(_REENT, path, &device, fs_path)==-1)
@ -434,46 +431,29 @@ Result fsdevDeleteDirectoryRecursively(const char *path) {
/*! Initialize SDMC device */
Result fsdevMountSdmc(void)
{
ssize_t units;
uint32_t code;
char *p;
Result rc = 0;
FsFileSystem fs;
fsdev_fsdevice *device = NULL;
if(fsdevFindDevice("sdmc"))
return 0;
rc = fsMountSdcard(&fs);
Result rc = fsMountSdcard(&fs);
if(R_SUCCEEDED(rc))
{
int dev = _fsdevMountDevice("sdmc", fs, &device);
if(dev != -1)
{
setDefaultDevice(dev);
if(device)
{
fsdev_fsdevice_default = device->id;
fsdev_fsdevice_cwd = fsdev_fsdevice_default;
int ret = fsdevMountDevice("sdmc", fs);
if(ret==-1)
rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
}
if(__system_argc != 0 && __system_argv[0] != NULL)
{
if(FindDevice(__system_argv[0]) == dev)
{
strncpy(__nx_dev_path_buf,__system_argv[0],PATH_MAX);
if(__nx_dev_path_buf[PATH_MAX] != 0)
{
__nx_dev_path_buf[PATH_MAX] = 0;
return rc;
}
else
void __libnx_init_cwd(void)
{
if(envIsNso() || __system_argc==0 || __system_argv[0] == NULL)
return;
char *last_slash = NULL;
p = __nx_dev_path_buf;
char *p = __system_argv[0];
uint32_t code;
do
{
units = decode_utf8(&code, (const uint8_t*)p);
ssize_t units = decode_utf8(&code, (const uint8_t*)p);
if(units < 0)
{
last_slash = NULL;
@ -489,16 +469,10 @@ Result fsdevMountSdmc(void)
if(last_slash != NULL)
{
last_slash[0] = 0;
chdir(__nx_dev_path_buf);
chdir(__system_argv[0]);
last_slash[0] = '/';
}
}
}
}
}
}
return rc;
}
/*! Clean up fsdev devices */
Result fsdevUnmountAll(void)
@ -530,14 +504,6 @@ FsFileSystem* fsdevGetDeviceFileSystem(const char *name)
return &device->fs;
}
FsFileSystem* fsdevGetDefaultFileSystem(void)
{
if(!fsdev_initialised) return NULL;
if(fsdev_fsdevice_default==-1) return NULL;
return &fsdev_fsdevices[fsdev_fsdevice_default].fs;
}
int fsdevTranslatePath(const char *path, FsFileSystem** device, char *outpath)
{
fsdev_fsdevice *tmpdev = NULL;
@ -571,8 +537,8 @@ fsdev_open(struct _reent *r,
Result rc;
u32 fsdev_flags = 0;
u32 attributes = 0;
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = r->deviceData;
if(fsdev_getfspath(r, path, &device, fs_path)==-1)
return -1;
@ -1025,8 +991,8 @@ fsdev_stat(struct _reent *r,
FsDir fdir;
Result rc;
int ret=0;
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = r->deviceData;
FsTimeStampRaw timestamps = {0};
FsDirEntryType type;
@ -1111,8 +1077,8 @@ fsdev_unlink(struct _reent *r,
const char *name)
{
Result rc;
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = r->deviceData;
if(fsdev_getfspath(r, name, &device, fs_path)==-1)
return -1;
@ -1139,8 +1105,14 @@ fsdev_chdir(struct _reent *r,
{
FsDir fd;
Result rc;
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = r->deviceData;
if(device->cwd==NULL)
{
r->_errno = ENOSYS;
return -1;
}
if(fsdev_getfspath(r, name, &device, fs_path)==-1)
return -1;
@ -1149,15 +1121,13 @@ fsdev_chdir(struct _reent *r,
if(R_SUCCEEDED(rc))
{
fsDirClose(&fd);
strncpy(__cwd, fs_path, PATH_MAX);
__cwd[PATH_MAX] = '\0';
memcpy(device->cwd, fs_path, FS_MAX_PATH);
size_t __cwd_len = strlen(__cwd);
if (__cwd[__cwd_len-1] != '/' && __cwd_len < PATH_MAX)
size_t cwdlen = strlen(fs_path);
if (device->cwd[cwdlen-1] != '/' && cwdlen < FS_MAX_PATH-1)
{
__cwd[__cwd_len] = '/';
__cwd[__cwd_len+1] = '\0';
device->cwd[cwdlen] = '/';
device->cwd[cwdlen+1] = '\0';
}
fsdev_fsdevice_cwd = device->id;
@ -1184,34 +1154,28 @@ fsdev_rename(struct _reent *r,
{
Result rc;
FsDirEntryType type;
fsdev_fsdevice *device_old = NULL, *device_new = NULL;
fsdev_fsdevice *device = r->deviceData;
char fs_path_old[FS_MAX_PATH];
char fs_path_new[FS_MAX_PATH];
char*fs_path_new = __nx_dev_path_buf;
if(fsdev_getfspath(r, oldName, &device_old, fs_path_old)==-1)
if(fsdev_getfspath(r, oldName, &device, fs_path_old)==-1)
return -1;
if(fsdev_getfspath(r, newName, &device_new, fs_path_new)==-1)
if(fsdev_getfspath(r, newName, &device, fs_path_new)==-1)
return -1;
if(device_old->id != device_new->id)
{
r->_errno = EXDEV;
return -1;
}
rc = fsFsGetEntryType(&device_old->fs, fs_path_old, &type);
rc = fsFsGetEntryType(&device->fs, fs_path_old, &type);
if(R_SUCCEEDED(rc))
{
if(type == FsDirEntryType_Dir)
{
rc = fsFsRenameDirectory(&device_old->fs, fs_path_old, fs_path_new);
rc = fsFsRenameDirectory(&device->fs, fs_path_old, fs_path_new);
if(R_SUCCEEDED(rc))
return 0;
}
else if(type == FsDirEntryType_File)
{
rc = fsFsRenameFile(&device_old->fs, fs_path_old, fs_path_new);
rc = fsFsRenameFile(&device->fs, fs_path_old, fs_path_new);
if(R_SUCCEEDED(rc))
return 0;
}
@ -1241,8 +1205,8 @@ fsdev_mkdir(struct _reent *r,
int mode)
{
Result rc;
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = r->deviceData;
if(fsdev_getfspath(r, path, &device, fs_path)==-1)
return -1;
@ -1271,8 +1235,8 @@ fsdev_diropen(struct _reent *r,
{
FsDir fd;
Result rc;
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = r->deviceData;
if(fsdev_getfspath(r, path, &device, fs_path)==-1)
return NULL;
@ -1449,8 +1413,8 @@ fsdev_statvfs(struct _reent *r,
struct statvfs *buf)
{
Result rc=0;
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = r->deviceData;
u64 freespace = 0, total_space = 0;
if(fsdev_getfspath(r, path, &device, fs_path)==-1)
@ -1591,8 +1555,8 @@ fsdev_rmdir(struct _reent *r,
const char *name)
{
Result rc;
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
char *fs_path = __nx_dev_path_buf;
fsdev_fsdevice *device = r->deviceData;
if(fsdev_getfspath(r, name, &device, fs_path)==-1)
return -1;

View File

@ -102,7 +102,7 @@ typedef struct
u32 childFile;
} romfs_diriter;
static devoptab_t romFS_devoptab =
static const devoptab_t romFS_devoptab =
{
.structSize = sizeof(romfs_fileobj),
.open_r = romfs_open,
@ -201,101 +201,63 @@ static void romfs_mountclose(romfs_mount *mount)
romfs_free(mount);
}
Result romfsMount(const char *name)
Result romfsMountSelf(const char *name)
{
romfs_mount *mount = romfs_alloc();
if(mount == NULL)
return 99;
if (!envIsNso())
{
// RomFS embedded in a NRO
mount->fd_type = RomfsSource_FsFile;
FsFileSystem *sdfs = fsdevGetDefaultFileSystem();
if(sdfs==NULL)
{
romfs_free(mount);
return 1;
}
// Check whether we are a NSO; if so then just mount the RomFS from the current process
if (envIsNso())
return romfsMountFromCurrentProcess(name);
// Otherwise, we are a homebrew NRO and we need to use our embedded RomFS
// Retrieve the filename of our NRO
const char* filename = __romfs_path;
if (__system_argc > 0 && __system_argv[0])
filename = __system_argv[0];
if (!filename)
{
romfs_free(mount);
return 1;
}
return MAKERESULT(Module_Libnx, LibnxError_NotFound);
if (strncmp(filename, "sdmc:/", 6) == 0)
filename += 5;
else if (strncmp(filename, "nxlink:/", 8) == 0)
{
strncpy(__nx_dev_path_buf, "/switch", PATH_MAX);
strncat(__nx_dev_path_buf, filename+7, PATH_MAX);
__nx_dev_path_buf[PATH_MAX] = 0;
filename = __nx_dev_path_buf;
}
else
{
romfs_free(mount);
return 2;
}
// Retrieve IFileSystem object + fixed path for our NRO
FsFileSystem *tmpfs = NULL;
char* path_buf = __nx_dev_path_buf;
if(fsdevTranslatePath(filename, &tmpfs, path_buf)==-1)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
Result rc = fsFsOpenFile(sdfs, filename, FsOpenMode_Read, &mount->fd);
// Open the NRO file
FsFile nro_file;
Result rc = fsFsOpenFile(tmpfs, path_buf, FsOpenMode_Read, &nro_file);
if (R_FAILED(rc))
{
romfs_free(mount);
return rc;
}
romfsInitMtime(mount);
// Read and parse the header
NroHeader hdr;
u64 readbytes = 0;
rc = fsFileRead(&nro_file, sizeof(NroStart), &hdr, sizeof(hdr), FsReadOption_None, &readbytes);
if (R_FAILED(rc) || readbytes != sizeof(hdr)) goto _fail_io;
if (hdr.magic != NROHEADER_MAGIC) goto _fail_io;
// Read and parse the asset header
NroAssetHeader asset_header;
if (!_romfs_read_chk(mount, sizeof(NroStart), &hdr, sizeof(hdr))) goto _fail0;
if (hdr.magic != NROHEADER_MAGIC) goto _fail0;
if (!_romfs_read_chk(mount, hdr.size, &asset_header, sizeof(asset_header))) goto _fail0;
rc = fsFileRead(&nro_file, hdr.size, &asset_header, sizeof(asset_header), FsReadOption_None, &readbytes);
if (R_FAILED(rc) || readbytes != sizeof(asset_header)) goto _fail_io;
if (asset_header.magic != NROASSETHEADER_MAGIC
|| asset_header.version > NROASSETHEADER_VERSION
|| asset_header.romfs.offset == 0
|| asset_header.romfs.size == 0)
goto _fail0;
goto _fail_io;
mount->offset = hdr.size + asset_header.romfs.offset;
}
else
{
// Regular RomFS
// Calculate the start offset of the embedded RomFS and mount it
u64 romfs_offset = hdr.size + asset_header.romfs.offset;
return romfsMountFromFile(nro_file, romfs_offset, name);
mount->fd_type = RomfsSource_FsStorage;
Result rc = fsOpenDataStorageByCurrentProcess(&mount->fd_storage);
if (R_FAILED(rc))
{
romfs_free(mount);
return rc;
}
romfsInitMtime(mount);
}
return romfsMountCommon(name, mount);
_fail0:
romfs_mountclose(mount);
return 10;
_fail_io:
fsFileClose(&nro_file);
return MAKERESULT(Module_Libnx, LibnxError_IoError);
}
Result romfsMountFromFile(FsFile file, u64 offset, const char *name)
{
romfs_mount *mount = romfs_alloc();
if(mount == NULL)
return 99;
return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
mount->fd_type = RomfsSource_FsFile;
mount->fd = file;
@ -308,7 +270,7 @@ Result romfsMountFromStorage(FsStorage storage, u64 offset, const char *name)
{
romfs_mount *mount = romfs_alloc();
if(mount == NULL)
return 99;
return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
mount->fd_type = RomfsSource_FsStorage;
mount->fd_storage = storage;
@ -330,21 +292,17 @@ Result romfsMountFromCurrentProcess(const char *name) {
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)
if(fsdevTranslatePath(path, &tmpfs, __nx_dev_path_buf)==-1)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
romfs_mount *mount = romfs_alloc();
if(mount == NULL)
return 99;
return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
mount->fd_type = RomfsSource_FsFile;
mount->offset = offset;
Result rc = fsFsOpenFile(tmpfs, filepath, FsOpenMode_Read, &mount->fd);
Result rc = fsFsOpenFile(tmpfs, __nx_dev_path_buf, FsOpenMode_Read, &mount->fd);
if (R_FAILED(rc))
{
romfs_free(mount);
@ -369,45 +327,50 @@ Result romfsMountCommon(const char *name, romfs_mount *mount)
memset(mount->name, 0, sizeof(mount->name));
strncpy(mount->name, name, sizeof(mount->name)-1);
romfsInitMtime(mount);
if (_romfs_read(mount, 0, &mount->header, sizeof(mount->header)) != sizeof(mount->header))
goto fail;
goto fail_io;
mount->dirHashTable = (u32*)malloc(mount->header.dirHashTableSize);
if (!mount->dirHashTable)
goto fail;
goto fail_oom;
if (!_romfs_read_chk(mount, mount->header.dirHashTableOff, mount->dirHashTable, mount->header.dirHashTableSize))
goto fail;
goto fail_io;
mount->dirTable = malloc(mount->header.dirTableSize);
if (!mount->dirTable)
goto fail;
goto fail_oom;
if (!_romfs_read_chk(mount, mount->header.dirTableOff, mount->dirTable, mount->header.dirTableSize))
goto fail;
goto fail_io;
mount->fileHashTable = (u32*)malloc(mount->header.fileHashTableSize);
if (!mount->fileHashTable)
goto fail;
goto fail_oom;
if (!_romfs_read_chk(mount, mount->header.fileHashTableOff, mount->fileHashTable, mount->header.fileHashTableSize))
goto fail;
goto fail_io;
mount->fileTable = malloc(mount->header.fileTableSize);
if (!mount->fileTable)
goto fail;
goto fail_oom;
if (!_romfs_read_chk(mount, mount->header.fileTableOff, mount->fileTable, mount->header.fileTableSize))
goto fail;
goto fail_io;
mount->cwd = romFS_root(mount);
// add device if this is the first one
if(AddDevice(&mount->device) < 0)
goto fail;
goto fail_oom;
mount->setup = true;
return 0;
fail:
fail_oom:
romfs_mountclose(mount);
return 10;
return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
fail_io:
romfs_mountclose(mount);
return MAKERESULT(Module_Libnx, LibnxError_IoError);
}
static void romfsInitMtime(romfs_mount *mount)
@ -422,7 +385,7 @@ Result romfsUnmount(const char *name)
mount = romfsFindMount(name);
if (mount == NULL)
return -1;
return MAKERESULT(Module_Libnx, LibnxError_NotFound);
// Remove device
memset(tmpname, 0, sizeof(tmpname));

View File

@ -17,6 +17,7 @@ void virtmemSetup(void);
void newlibSetup(void);
void argvSetup(void);
void __libnx_init_time(void);
void __libnx_init_cwd(void);
extern u32 __nx_applet_type;
@ -141,6 +142,7 @@ void __attribute__((weak)) __appInit(void)
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS));
fsdevMountSdmc();
__libnx_init_cwd();
if (&__nx_win_init) __nx_win_init();
if (&userAppInit) userAppInit();