romfs_dev: Backport proper multimount system from libnx with some tweaks
This commit is contained in:
parent
1c7914e2f4
commit
da529aed21
@ -45,36 +45,40 @@ typedef struct
|
|||||||
u16 name[]; ///< Name. (UTF-16)
|
u16 name[]; ///< Name. (UTF-16)
|
||||||
} romfs_file;
|
} romfs_file;
|
||||||
|
|
||||||
struct romfs_mount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Mounts the Application's RomFS.
|
* @brief Mounts the Application's RomFS.
|
||||||
* @param mount Output mount handle
|
* @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 3DSX, it mounts the embedded RomFS section inside the 3DSX.
|
||||||
|
* If on the other hand it's an NCCH, it behaves identically to \ref romfsMountFromCurrentProcess.
|
||||||
*/
|
*/
|
||||||
Result romfsMount(struct romfs_mount **mount);
|
Result romfsMountSelf(const char *name);
|
||||||
static inline Result romfsInit(void)
|
|
||||||
{
|
|
||||||
return romfsMount(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Mounts RomFS from an open file.
|
* @brief Mounts RomFS from an open file.
|
||||||
* @param file Handle of the RomFS file.
|
* @param fd FSFILE handle of the RomFS image.
|
||||||
* @param offset Offset of the RomFS within the file.
|
* @param offset Offset of the RomFS within the file.
|
||||||
* @param mount Output mount handle
|
* @param name Device mount name.
|
||||||
*/
|
*/
|
||||||
Result romfsMountFromFile(Handle file, u32 offset, struct romfs_mount **mount);
|
Result romfsMountFromFile(Handle fd, u32 offset, const char *name);
|
||||||
static inline Result romfsInitFromFile(Handle file, u32 offset)
|
|
||||||
{
|
|
||||||
return romfsMountFromFile(file, offset, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Bind the RomFS mount
|
/**
|
||||||
Result romfsBind(struct romfs_mount *mount);
|
* @brief Mounts RomFS using the current process host program RomFS.
|
||||||
|
* @param name Device mount name.
|
||||||
|
*/
|
||||||
|
Result romfsMountFromCurrentProcess(const char *name);
|
||||||
|
|
||||||
/// Unmounts the RomFS device.
|
/// Unmounts the RomFS device.
|
||||||
Result romfsUnmount(struct romfs_mount *mount);
|
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)
|
static inline Result romfsExit(void)
|
||||||
{
|
{
|
||||||
return romfsUnmount(NULL);
|
return romfsUnmount("romfs");
|
||||||
}
|
}
|
||||||
|
@ -41,15 +41,14 @@ static Result __read_versionbin(FS_ArchiveID archiveId, FS_Path archivePath, FS_
|
|||||||
Result ret = 0;
|
Result ret = 0;
|
||||||
Handle filehandle = 0;
|
Handle filehandle = 0;
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
struct romfs_mount *mount;
|
|
||||||
|
|
||||||
ret = FSUSER_OpenFileDirectly(&filehandle, archiveId, archivePath, fileLowPath, FS_OPEN_READ, 0x0);
|
ret = FSUSER_OpenFileDirectly(&filehandle, archiveId, archivePath, fileLowPath, FS_OPEN_READ, 0x0);
|
||||||
if(R_FAILED(ret))return ret;
|
if(R_FAILED(ret))return ret;
|
||||||
|
|
||||||
ret = romfsMountFromFile(filehandle, 0x0, &mount);
|
ret = romfsMountFromFile(filehandle, 0x0, "ver");
|
||||||
if(R_FAILED(ret))return ret;
|
if(R_FAILED(ret))return ret;
|
||||||
|
|
||||||
f = fopen("romfs:/version.bin", "r");
|
f = fopen("ver:/version.bin", "r");
|
||||||
if(f==NULL)
|
if(f==NULL)
|
||||||
{
|
{
|
||||||
ret = errno;
|
ret = errno;
|
||||||
@ -60,7 +59,7 @@ static Result __read_versionbin(FS_ArchiveID archiveId, FS_Path archivePath, FS_
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
romfsUnmount(mount);
|
romfsUnmount("ver");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -121,7 +120,7 @@ Result osGetSystemVersionDataString(OS_VersionBin *nver_versionbin, OS_VersionBi
|
|||||||
ret = osGetSystemVersionData(nver_versionbin, cver_versionbin);
|
ret = osGetSystemVersionData(nver_versionbin, cver_versionbin);
|
||||||
if(R_FAILED(ret))return ret;
|
if(R_FAILED(ret))return ret;
|
||||||
|
|
||||||
snprintf(sysverstr, sysverstr_maxsize, "%u.%u.%u-%u%c\n", cver_versionbin->mainver, cver_versionbin->minor, cver_versionbin->build, nver_versionbin->mainver, nver_versionbin->region);
|
snprintf(sysverstr, sysverstr_maxsize, "%u.%u.%u-%u%c", cver_versionbin->mainver, cver_versionbin->minor, cver_versionbin->build, nver_versionbin->mainver, nver_versionbin->region);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
typedef struct romfs_mount
|
typedef struct romfs_mount
|
||||||
{
|
{
|
||||||
|
devoptab_t device;
|
||||||
|
char name[32];
|
||||||
Handle fd;
|
Handle fd;
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
@ -84,9 +86,8 @@ typedef struct
|
|||||||
u32 childFile;
|
u32 childFile;
|
||||||
} romfs_diriter;
|
} romfs_diriter;
|
||||||
|
|
||||||
static devoptab_t romFS_devoptab =
|
static const devoptab_t romFS_devoptab =
|
||||||
{
|
{
|
||||||
.name = "romfs",
|
|
||||||
.structSize = sizeof(romfs_fileobj),
|
.structSize = sizeof(romfs_fileobj),
|
||||||
.open_r = romfs_open,
|
.open_r = romfs_open,
|
||||||
.close_r = romfs_close,
|
.close_r = romfs_close,
|
||||||
@ -101,7 +102,6 @@ static devoptab_t romFS_devoptab =
|
|||||||
.dirreset_r = romfs_dirreset,
|
.dirreset_r = romfs_dirreset,
|
||||||
.dirnext_r = romfs_dirnext,
|
.dirnext_r = romfs_dirnext,
|
||||||
.dirclose_r = romfs_dirclose,
|
.dirclose_r = romfs_dirclose,
|
||||||
.deviceData = 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -124,9 +124,6 @@ typedef struct
|
|||||||
u32 fsOffset;
|
u32 fsOffset;
|
||||||
} _3DSX_Header;
|
} _3DSX_Header;
|
||||||
|
|
||||||
static Result romfsMountCommon(romfs_mount *mount);
|
|
||||||
static void romfsInitMtime(romfs_mount *mount, FS_ArchiveID archId, FS_Path archPath, FS_Path filePath);
|
|
||||||
|
|
||||||
__attribute__((weak)) const char* __romfs_path = NULL;
|
__attribute__((weak)) const char* __romfs_path = NULL;
|
||||||
|
|
||||||
static romfs_mount *romfs_mount_list = NULL;
|
static romfs_mount *romfs_mount_list = NULL;
|
||||||
@ -151,16 +148,23 @@ static void romfs_remove(romfs_mount *mount)
|
|||||||
|
|
||||||
static romfs_mount* romfs_alloc(void)
|
static romfs_mount* romfs_alloc(void)
|
||||||
{
|
{
|
||||||
romfs_mount *mount = (romfs_mount*)calloc(1, sizeof(romfs_mount));
|
romfs_mount *mount = (romfs_mount*)malloc(sizeof(romfs_mount));
|
||||||
|
|
||||||
if (mount)
|
if (mount)
|
||||||
|
{
|
||||||
|
memset(mount, 0, sizeof(*mount));
|
||||||
|
memcpy(&mount->device, &romFS_devoptab, sizeof(romFS_devoptab));
|
||||||
|
mount->device.name = mount->name;
|
||||||
|
mount->device.deviceData = mount;
|
||||||
romfs_insert(mount);
|
romfs_insert(mount);
|
||||||
|
}
|
||||||
|
|
||||||
return mount;
|
return mount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void romfs_free(romfs_mount *mount)
|
static void romfs_free(romfs_mount *mount)
|
||||||
{
|
{
|
||||||
|
FSFILE_Close(mount->fd);
|
||||||
romfs_remove(mount);
|
romfs_remove(mount);
|
||||||
free(mount->fileTable);
|
free(mount->fileTable);
|
||||||
free(mount->fileHashTable);
|
free(mount->fileHashTable);
|
||||||
@ -169,24 +173,78 @@ static void romfs_free(romfs_mount *mount)
|
|||||||
free(mount);
|
free(mount);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result romfsMount(struct romfs_mount **p)
|
Result romfsMountFromFile(Handle fd, u32 offset, const char *name)
|
||||||
{
|
{
|
||||||
romfs_mount *mount = romfs_alloc();
|
romfs_mount *mount = romfs_alloc();
|
||||||
if (mount == NULL)
|
if (mount == NULL)
|
||||||
return 99;
|
|
||||||
|
|
||||||
if (envIsHomebrew())
|
|
||||||
{
|
{
|
||||||
// RomFS appended to a 3DSX file
|
FSFILE_Close(fd);
|
||||||
|
return MAKERESULT(RL_FATAL, RS_OUTOFRESOURCE, RM_ROMFS, RD_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
mount->fd = fd;
|
||||||
|
mount->offset = offset;
|
||||||
|
mount->mtime = time(NULL);
|
||||||
|
strncpy(mount->name, name, sizeof(mount->name)-1);
|
||||||
|
|
||||||
|
if (_romfs_read(mount, 0, &mount->header, sizeof(mount->header)) != sizeof(mount->header))
|
||||||
|
goto fail_io;
|
||||||
|
|
||||||
|
mount->dirHashTable = (u32*)malloc(mount->header.dirHashTableSize);
|
||||||
|
if (!mount->dirHashTable)
|
||||||
|
goto fail_oom;
|
||||||
|
if (!_romfs_read_chk(mount, mount->header.dirHashTableOff, mount->dirHashTable, mount->header.dirHashTableSize))
|
||||||
|
goto fail_io;
|
||||||
|
|
||||||
|
mount->dirTable = malloc(mount->header.dirTableSize);
|
||||||
|
if (!mount->dirTable)
|
||||||
|
goto fail_oom;
|
||||||
|
if (!_romfs_read_chk(mount, mount->header.dirTableOff, mount->dirTable, mount->header.dirTableSize))
|
||||||
|
goto fail_io;
|
||||||
|
|
||||||
|
mount->fileHashTable = (u32*)malloc(mount->header.fileHashTableSize);
|
||||||
|
if (!mount->fileHashTable)
|
||||||
|
goto fail_oom;
|
||||||
|
if (!_romfs_read_chk(mount, mount->header.fileHashTableOff, mount->fileHashTable, mount->header.fileHashTableSize))
|
||||||
|
goto fail_io;
|
||||||
|
|
||||||
|
mount->fileTable = malloc(mount->header.fileTableSize);
|
||||||
|
if (!mount->fileTable)
|
||||||
|
goto fail_oom;
|
||||||
|
if (!_romfs_read_chk(mount, mount->header.fileTableOff, mount->fileTable, mount->header.fileTableSize))
|
||||||
|
goto fail_io;
|
||||||
|
|
||||||
|
mount->cwd = romFS_root(mount);
|
||||||
|
|
||||||
|
if (AddDevice(&mount->device) < 0)
|
||||||
|
goto fail_oom;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_oom:
|
||||||
|
romfs_free(mount);
|
||||||
|
return MAKERESULT(RL_FATAL, RS_OUTOFRESOURCE, RM_ROMFS, RD_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
fail_io:
|
||||||
|
romfs_free(mount);
|
||||||
|
return MAKERESULT(RL_FATAL, RS_INVALIDSTATE, RM_ROMFS, RD_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result romfsMountSelf(const char* name)
|
||||||
|
{
|
||||||
|
// If we are not 3DSX, we need to mount this process' real RomFS
|
||||||
|
if (!envIsHomebrew())
|
||||||
|
return romfsMountFromCurrentProcess(name);
|
||||||
|
|
||||||
|
// Otherwise, we use the embedded RomFS inside the 3DSX file
|
||||||
|
// Retrieve the filename of our 3DSX file
|
||||||
const char* filename = __romfs_path;
|
const char* filename = __romfs_path;
|
||||||
if (__system_argc > 0 && __system_argv[0])
|
if (__system_argc > 0 && __system_argv[0])
|
||||||
filename = __system_argv[0];
|
filename = __system_argv[0];
|
||||||
if (!filename)
|
if (!filename)
|
||||||
{
|
return MAKERESULT(RL_USAGE, RS_INVALIDARG, RM_ROMFS, RD_NO_DATA);
|
||||||
romfs_free(mount);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Adjust the path name
|
||||||
if (strncmp(filename, "sdmc:/", 6) == 0)
|
if (strncmp(filename, "sdmc:/", 6) == 0)
|
||||||
filename += 5;
|
filename += 5;
|
||||||
else if (strncmp(filename, "3dslink:/", 9) == 0)
|
else if (strncmp(filename, "3dslink:/", 9) == 0)
|
||||||
@ -197,193 +255,83 @@ Result romfsMount(struct romfs_mount **p)
|
|||||||
filename = __ctru_dev_path_buf;
|
filename = __ctru_dev_path_buf;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
return MAKERESULT(RL_USAGE, RS_NOTSUPPORTED, RM_ROMFS, RD_NOT_IMPLEMENTED);
|
||||||
romfs_free(mount);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Convert the path to UTF-16
|
||||||
ssize_t units = utf8_to_utf16(__ctru_dev_utf16_buf, (const uint8_t*)filename, PATH_MAX);
|
ssize_t units = utf8_to_utf16(__ctru_dev_utf16_buf, (const uint8_t*)filename, PATH_MAX);
|
||||||
if (units < 0)
|
if (units < 0 || units > PATH_MAX)
|
||||||
{
|
return MAKERESULT(RL_USAGE, RS_INVALIDARG, RM_ROMFS, RD_OUT_OF_RANGE);
|
||||||
romfs_free(mount);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
if (units > PATH_MAX)
|
|
||||||
{
|
|
||||||
romfs_free(mount);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
__ctru_dev_utf16_buf[units] = 0;
|
__ctru_dev_utf16_buf[units] = 0;
|
||||||
|
|
||||||
|
// Open the file directly
|
||||||
|
Handle fd = 0;
|
||||||
FS_Path archPath = { PATH_EMPTY, 1, "" };
|
FS_Path archPath = { PATH_EMPTY, 1, "" };
|
||||||
FS_Path filePath = { PATH_UTF16, (units+1)*2, __ctru_dev_utf16_buf };
|
FS_Path filePath = { PATH_UTF16, (units+1)*2, __ctru_dev_utf16_buf };
|
||||||
|
Result rc = FSUSER_OpenFileDirectly(&fd, ARCHIVE_SDMC, archPath, filePath, FS_OPEN_READ, 0);
|
||||||
|
if (R_FAILED(rc))
|
||||||
|
return rc;
|
||||||
|
|
||||||
Result rc = FSUSER_OpenFileDirectly(&mount->fd, ARCHIVE_SDMC, archPath, filePath, FS_OPEN_READ, 0);
|
// Read and parse the header
|
||||||
|
_3DSX_Header hdr;
|
||||||
|
u32 bytesRead = 0;
|
||||||
|
rc = FSFILE_Read(fd, &bytesRead, 0, &hdr, sizeof(hdr));
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
romfs_free(mount);
|
FSFILE_Close(fd);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
romfsInitMtime(mount, ARCHIVE_SDMC, archPath, filePath);
|
// Validate the 3DSX header
|
||||||
|
if (bytesRead != sizeof(hdr) || hdr.magic != _3DSX_MAGIC || hdr.headerSize < sizeof(hdr))
|
||||||
_3DSX_Header hdr;
|
|
||||||
if (!_romfs_read_chk(mount, 0, &hdr, sizeof(hdr))) goto _fail0;
|
|
||||||
if (hdr.magic != _3DSX_MAGIC) goto _fail0;
|
|
||||||
if (hdr.headerSize < sizeof(hdr)) goto _fail0;
|
|
||||||
mount->offset = hdr.fsOffset;
|
|
||||||
if (!mount->offset) goto _fail0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Regular RomFS
|
FSFILE_Close(fd);
|
||||||
u8 zeros[0xC] = {0};
|
return MAKERESULT(RL_FATAL, RS_NOTFOUND, RM_ROMFS, RD_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount the file
|
||||||
|
return romfsMountFromFile(fd, hdr.fsOffset, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result romfsMountFromCurrentProcess(const char *name)
|
||||||
|
{
|
||||||
|
// Set up FS_Path structures
|
||||||
|
u8 zeros[0xC] = {0};
|
||||||
FS_Path archPath = { PATH_EMPTY, 1, "" };
|
FS_Path archPath = { PATH_EMPTY, 1, "" };
|
||||||
FS_Path filePath = { PATH_BINARY, sizeof(zeros), zeros };
|
FS_Path filePath = { PATH_BINARY, sizeof(zeros), zeros };
|
||||||
|
|
||||||
Result rc = FSUSER_OpenFileDirectly(&mount->fd, ARCHIVE_ROMFS, archPath, filePath, FS_OPEN_READ, 0);
|
// Open the RomFS file and mount it
|
||||||
if (R_FAILED(rc))
|
Handle fd = 0;
|
||||||
{
|
Result rc = FSUSER_OpenFileDirectly(&fd, ARCHIVE_ROMFS, archPath, filePath, FS_OPEN_READ, 0);
|
||||||
romfs_free(mount);
|
if (R_SUCCEEDED(rc))
|
||||||
|
rc = romfsMountFromFile(fd, 0, name);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
romfsInitMtime(mount, ARCHIVE_ROMFS, archPath, filePath);
|
Result romfsUnmount(const char* name)
|
||||||
}
|
|
||||||
|
|
||||||
Result ret = romfsMountCommon(mount);
|
|
||||||
if(R_SUCCEEDED(ret) && p)
|
|
||||||
*p = mount;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
_fail0:
|
|
||||||
FSFILE_Close(mount->fd);
|
|
||||||
romfs_free(mount);
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result romfsMountFromFile(Handle file, u32 offset, struct romfs_mount **p)
|
|
||||||
{
|
{
|
||||||
romfs_mount *mount = romfs_alloc();
|
// Find the mount
|
||||||
|
romfs_mount* mount = romfs_mount_list;
|
||||||
|
while (mount)
|
||||||
|
{
|
||||||
|
if (strncmp(mount->name, name, sizeof(mount->name)) == 0)
|
||||||
|
break;
|
||||||
|
mount = mount->next;
|
||||||
|
}
|
||||||
|
|
||||||
if (mount == NULL)
|
if (mount == NULL)
|
||||||
return 99;
|
return MAKERESULT(RL_STATUS, RS_NOTFOUND, RM_ROMFS, RD_NOT_FOUND);
|
||||||
|
|
||||||
mount->fd = file;
|
// Remove device
|
||||||
mount->offset = offset;
|
char tmpname[34];
|
||||||
|
unsigned len = strlen(name);
|
||||||
|
memcpy(tmpname, mount->name, len);
|
||||||
|
tmpname[len] = ':';
|
||||||
|
tmpname[len+1] = 0;
|
||||||
|
RemoveDevice(tmpname);
|
||||||
|
|
||||||
Result ret = romfsMountCommon(mount);
|
// Free the mount
|
||||||
if(R_SUCCEEDED(ret) && p)
|
|
||||||
*p = mount;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result romfsMountCommon(romfs_mount *mount)
|
|
||||||
{
|
|
||||||
if (_romfs_read(mount, 0, &mount->header, sizeof(mount->header)) != sizeof(mount->header))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
mount->dirHashTable = (u32*)malloc(mount->header.dirHashTableSize);
|
|
||||||
if (!mount->dirHashTable)
|
|
||||||
goto fail;
|
|
||||||
if (!_romfs_read_chk(mount, mount->header.dirHashTableOff, mount->dirHashTable, mount->header.dirHashTableSize))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
mount->dirTable = malloc(mount->header.dirTableSize);
|
|
||||||
if (!mount->dirTable)
|
|
||||||
goto fail;
|
|
||||||
if (!_romfs_read_chk(mount, mount->header.dirTableOff, mount->dirTable, mount->header.dirTableSize))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
mount->fileHashTable = (u32*)malloc(mount->header.fileHashTableSize);
|
|
||||||
if (!mount->fileHashTable)
|
|
||||||
goto fail;
|
|
||||||
if (!_romfs_read_chk(mount, mount->header.fileHashTableOff, mount->fileHashTable, mount->header.fileHashTableSize))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
mount->fileTable = malloc(mount->header.fileTableSize);
|
|
||||||
if (!mount->fileTable)
|
|
||||||
goto fail;
|
|
||||||
if (!_romfs_read_chk(mount, mount->header.fileTableOff, mount->fileTable, mount->header.fileTableSize))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
mount->cwd = romFS_root(mount);
|
|
||||||
|
|
||||||
// add device if this is the first one
|
|
||||||
if(mount->next == NULL && AddDevice(&romFS_devoptab) < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
FSFILE_Close(mount->fd);
|
|
||||||
romfs_free(mount);
|
romfs_free(mount);
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void romfsInitMtime(romfs_mount *mount, FS_ArchiveID archId, FS_Path archPath, FS_Path filePath)
|
|
||||||
{
|
|
||||||
u64 mtime;
|
|
||||||
FS_Archive arch;
|
|
||||||
Result rc;
|
|
||||||
|
|
||||||
mount->mtime = time(NULL);
|
|
||||||
rc = FSUSER_OpenArchive(&arch, archId, archPath);
|
|
||||||
if (R_FAILED(rc))
|
|
||||||
return;
|
|
||||||
|
|
||||||
rc = FSUSER_ControlArchive(arch, ARCHIVE_ACTION_GET_TIMESTAMP,
|
|
||||||
(void*)filePath.data, filePath.size,
|
|
||||||
&mtime, sizeof(mtime));
|
|
||||||
FSUSER_CloseArchive(arch);
|
|
||||||
if (R_FAILED(rc))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* convert from milliseconds to seconds */
|
|
||||||
mtime /= 1000;
|
|
||||||
/* convert from 2000-based timestamp to UNIX timestamp */
|
|
||||||
mtime += 946684800;
|
|
||||||
mount->mtime = mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result romfsBind(struct romfs_mount *mount)
|
|
||||||
{
|
|
||||||
for(romfs_mount **it = &romfs_mount_list; *it; it = &(*it)->next)
|
|
||||||
{
|
|
||||||
if(*it == mount)
|
|
||||||
{
|
|
||||||
*it = mount->next;
|
|
||||||
romfs_insert(mount);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 99;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result romfsUnmount(struct romfs_mount *mount)
|
|
||||||
{
|
|
||||||
if(mount)
|
|
||||||
{
|
|
||||||
// unmount specific
|
|
||||||
FSFILE_Close(mount->fd);
|
|
||||||
romfs_free(mount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// unmount everything
|
|
||||||
while(romfs_mount_list)
|
|
||||||
{
|
|
||||||
FSFILE_Close(romfs_mount_list->fd);
|
|
||||||
romfs_free(romfs_mount_list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no more mounts, remove device
|
|
||||||
if(romfs_mount_list == NULL)
|
|
||||||
RemoveDevice("romfs:");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -567,7 +515,7 @@ int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags,
|
|||||||
{
|
{
|
||||||
romfs_fileobj* fileobj = (romfs_fileobj*)fileStruct;
|
romfs_fileobj* fileobj = (romfs_fileobj*)fileStruct;
|
||||||
|
|
||||||
fileobj->mount = romfs_mount_list;
|
fileobj->mount = (romfs_mount*)r->deviceData;
|
||||||
|
|
||||||
if ((flags & O_ACCMODE) != O_RDONLY)
|
if ((flags & O_ACCMODE) != O_RDONLY)
|
||||||
{
|
{
|
||||||
@ -696,7 +644,7 @@ int romfs_fstat(struct _reent *r, void *fd, struct stat *st)
|
|||||||
|
|
||||||
int romfs_stat(struct _reent *r, const char *path, struct stat *st)
|
int romfs_stat(struct _reent *r, const char *path, struct stat *st)
|
||||||
{
|
{
|
||||||
romfs_mount* mount = romfs_mount_list;
|
romfs_mount* mount = (romfs_mount*)r->deviceData;
|
||||||
romfs_dir* curDir = NULL;
|
romfs_dir* curDir = NULL;
|
||||||
r->_errno = navigateToDir(mount, &curDir, &path, false);
|
r->_errno = navigateToDir(mount, &curDir, &path, false);
|
||||||
if(r->_errno != 0)
|
if(r->_errno != 0)
|
||||||
@ -740,7 +688,7 @@ int romfs_stat(struct _reent *r, const char *path, struct stat *st)
|
|||||||
|
|
||||||
int romfs_chdir(struct _reent *r, const char *path)
|
int romfs_chdir(struct _reent *r, const char *path)
|
||||||
{
|
{
|
||||||
romfs_mount* mount = romfs_mount_list;
|
romfs_mount* mount = (romfs_mount*)r->deviceData;
|
||||||
romfs_dir* curDir = NULL;
|
romfs_dir* curDir = NULL;
|
||||||
r->_errno = navigateToDir(mount, &curDir, &path, true);
|
r->_errno = navigateToDir(mount, &curDir, &path, true);
|
||||||
if (r->_errno != 0)
|
if (r->_errno != 0)
|
||||||
@ -754,7 +702,7 @@ DIR_ITER* romfs_diropen(struct _reent *r, DIR_ITER *dirState, const char *path)
|
|||||||
{
|
{
|
||||||
romfs_diriter* iter = (romfs_diriter*)(dirState->dirStruct);
|
romfs_diriter* iter = (romfs_diriter*)(dirState->dirStruct);
|
||||||
romfs_dir* curDir = NULL;
|
romfs_dir* curDir = NULL;
|
||||||
iter->mount = romfs_mount_list;
|
iter->mount = (romfs_mount*)r->deviceData;
|
||||||
|
|
||||||
r->_errno = navigateToDir(iter->mount, &curDir, &path, true);
|
r->_errno = navigateToDir(iter->mount, &curDir, &path, true);
|
||||||
if(r->_errno != 0)
|
if(r->_errno != 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user