mirror of
https://github.com/switchbrew/libnx.git
synced 2025-08-05 16:09:24 +02:00
Check for invalid handle in fs*Close(). Added fsOpenDataStorageByCurrentProcess(), fsStorageRead(), and fsStorageClose(). Added fsdevGetDefaultFileSystem(). Imported nro.h from nx-hbmenu. Implemented proper RomFS support.
This commit is contained in:
parent
9e96639681
commit
4c1b09d6b9
@ -12,6 +12,8 @@ extern "C" {
|
|||||||
#include "switch/types.h"
|
#include "switch/types.h"
|
||||||
#include "switch/result.h"
|
#include "switch/result.h"
|
||||||
|
|
||||||
|
#include "switch/nro.h"
|
||||||
|
|
||||||
#include "switch/kernel/svc.h"
|
#include "switch/kernel/svc.h"
|
||||||
#include "switch/kernel/tmem.h"
|
#include "switch/kernel/tmem.h"
|
||||||
#include "switch/kernel/shmem.h"
|
#include "switch/kernel/shmem.h"
|
||||||
@ -59,6 +61,7 @@ extern "C" {
|
|||||||
#include "switch/runtime/devices/console.h"
|
#include "switch/runtime/devices/console.h"
|
||||||
#include "switch/runtime/devices/usb_comms.h"
|
#include "switch/runtime/devices/usb_comms.h"
|
||||||
#include "switch/runtime/devices/fs_dev.h"
|
#include "switch/runtime/devices/fs_dev.h"
|
||||||
|
#include "switch/runtime/devices/romfs_dev.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
54
nx/include/switch/nro.h
Normal file
54
nx/include/switch/nro.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* @file nro.h
|
||||||
|
* @brief NRO headers.
|
||||||
|
* @copyright libnx Authors
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define NROHEADER_MAGICNUM 0x304f524e
|
||||||
|
|
||||||
|
#define ASSETHEADER_MAGICNUM 0x54455341
|
||||||
|
#define ASSETHEADER_VERSION 0
|
||||||
|
|
||||||
|
/// Entry for each segment in the codebin.
|
||||||
|
typedef struct {
|
||||||
|
u32 FileOff;
|
||||||
|
u32 Size;
|
||||||
|
} NsoSegment;
|
||||||
|
|
||||||
|
/// Offset 0x0 in the NRO.
|
||||||
|
typedef struct {
|
||||||
|
u32 unused;
|
||||||
|
u32 modOffset;
|
||||||
|
u8 Padding[8];
|
||||||
|
} NroStart;
|
||||||
|
|
||||||
|
/// This follows NroStart, the actual nro-header.
|
||||||
|
typedef struct {
|
||||||
|
u32 Magic;
|
||||||
|
u32 Unk1;
|
||||||
|
u32 size;
|
||||||
|
u32 Unk2;
|
||||||
|
NsoSegment Segments[3];
|
||||||
|
u32 bssSize;
|
||||||
|
u32 Unk3;
|
||||||
|
u8 BuildId[0x20];
|
||||||
|
u8 Padding[0x20];
|
||||||
|
} NroHeader;
|
||||||
|
|
||||||
|
/// Custom asset section.
|
||||||
|
typedef struct {
|
||||||
|
u64 offset;
|
||||||
|
u64 size;
|
||||||
|
} AssetSection;
|
||||||
|
|
||||||
|
/// Custom asset header.
|
||||||
|
typedef struct {
|
||||||
|
u32 magic;
|
||||||
|
u32 version;
|
||||||
|
AssetSection icon;
|
||||||
|
AssetSection nacp;
|
||||||
|
AssetSection romfs;
|
||||||
|
} AssetHeader;
|
||||||
|
|
@ -38,3 +38,6 @@ int fsdevUnmountDevice(const char *name);
|
|||||||
/// Uses fsFsCommit() with the specified device. This must be used after any savedata-write operations(not just file-write).
|
/// Uses fsFsCommit() with the specified device. This must be used after any savedata-write operations(not just file-write).
|
||||||
/// This is not used automatically at device unmount.
|
/// This is not used automatically at device unmount.
|
||||||
Result fsdevCommitDevice(const char *name);
|
Result fsdevCommitDevice(const char *name);
|
||||||
|
|
||||||
|
/// Returns the FsFileSystem for the default device (SD card), if mounted. Used internally by romfs_dev.
|
||||||
|
FsFileSystem* fsdevGetDefaultFileSystem(void);
|
||||||
|
@ -66,7 +66,7 @@ static inline Result romfsInit(void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Mounts RomFS from an open file.
|
* @brief Mounts RomFS from an open file.
|
||||||
* @param file Handle of the RomFS file.
|
* @param file FsFile 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 mount Output mount handle
|
||||||
*/
|
*/
|
||||||
@ -76,6 +76,18 @@ static inline Result romfsInitFromFile(FsFile file, u64 offset)
|
|||||||
return romfsMountFromFile(file, offset, NULL);
|
return romfsMountFromFile(file, offset, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mounts RomFS from an open storage.
|
||||||
|
* @param storage FsStorage of the RomFS image.
|
||||||
|
* @param offset Offset of the RomFS within the storage.
|
||||||
|
* @param mount Output mount handle
|
||||||
|
*/
|
||||||
|
Result romfsMountFromStorage(FsStorage storage, u64 offset, struct romfs_mount **mount);
|
||||||
|
static inline Result romfsInitFromStorage(FsStorage storage, u64 offset)
|
||||||
|
{
|
||||||
|
return romfsMountFromStorage(storage, offset, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/// Bind the RomFS mount
|
/// Bind the RomFS mount
|
||||||
Result romfsBind(struct romfs_mount *mount);
|
Result romfsBind(struct romfs_mount *mount);
|
||||||
|
|
||||||
|
@ -93,6 +93,7 @@ Service* fsGetServiceSession(void);
|
|||||||
|
|
||||||
Result fsMountSdcard(FsFileSystem* out);
|
Result fsMountSdcard(FsFileSystem* out);
|
||||||
Result fsMountSaveData(FsFileSystem* out, u8 inval, FsSave *save);
|
Result fsMountSaveData(FsFileSystem* out, u8 inval, FsSave *save);
|
||||||
|
Result fsOpenDataStorageByCurrentProcess(FsStorage* out);
|
||||||
// todo: Rest of commands here
|
// todo: Rest of commands here
|
||||||
|
|
||||||
/// FsFileSystem can be mounted with fs_dev for use with stdio, see fs_dev.h.
|
/// FsFileSystem can be mounted with fs_dev for use with stdio, see fs_dev.h.
|
||||||
@ -130,4 +131,6 @@ Result fsDirRead(FsDir* d, u64 inval, size_t* total_entries, size_t max_entries,
|
|||||||
Result fsDirGetEntryCount(FsDir* d, u64* count);
|
Result fsDirGetEntryCount(FsDir* d, u64* count);
|
||||||
void fsDirClose(FsDir* d);
|
void fsDirClose(FsDir* d);
|
||||||
|
|
||||||
// todo: IStorage
|
// IStorage
|
||||||
|
Result fsStorageRead(FsStorage* s, u64 off, void* buf, size_t len);
|
||||||
|
void fsStorageClose(FsStorage* s);
|
||||||
|
@ -469,6 +469,13 @@ Result fsdevExit(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FsFileSystem* fsdevGetDefaultFileSystem(void)
|
||||||
|
{
|
||||||
|
if(fsdev_fsdevice_default==-1) return NULL;
|
||||||
|
|
||||||
|
return &fsdev_fsdevices[fsdev_fsdevice_default].fs;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Open a file
|
/*! Open a file
|
||||||
*
|
*
|
||||||
* @param[in,out] r newlib reentrancy struct
|
* @param[in,out] r newlib reentrancy struct
|
||||||
|
@ -9,14 +9,17 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "runtime/devices/romfs_dev.h"
|
#include "runtime/devices/romfs_dev.h"
|
||||||
|
#include "runtime/devices/fs_dev.h"
|
||||||
#include "runtime/util/utf.h"
|
#include "runtime/util/utf.h"
|
||||||
#include "services/fs.h"
|
#include "services/fs.h"
|
||||||
|
#include "runtime/env.h"
|
||||||
/// WARNING: This is not ready to be used.
|
#include "nro.h"
|
||||||
|
|
||||||
typedef struct romfs_mount
|
typedef struct romfs_mount
|
||||||
{
|
{
|
||||||
|
bool fd_type;
|
||||||
FsFile fd;
|
FsFile fd;
|
||||||
|
FsStorage fd_storage;
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
romfs_header header;
|
romfs_header header;
|
||||||
@ -30,7 +33,6 @@ extern int __system_argc;
|
|||||||
extern char** __system_argv;
|
extern char** __system_argv;
|
||||||
|
|
||||||
static char __component[PATH_MAX+1];
|
static char __component[PATH_MAX+1];
|
||||||
//static uint16_t __utf16path[PATH_MAX+1];
|
|
||||||
|
|
||||||
#define romFS_root(m) ((romfs_dir*)(m)->dirTable)
|
#define romFS_root(m) ((romfs_dir*)(m)->dirTable)
|
||||||
#define romFS_dir(m,x) ((romfs_dir*) ((u8*)(m)->dirTable + (x)))
|
#define romFS_dir(m,x) ((romfs_dir*) ((u8*)(m)->dirTable + (x)))
|
||||||
@ -39,16 +41,25 @@ static char __component[PATH_MAX+1];
|
|||||||
#define romFS_dir_mode (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH)
|
#define romFS_dir_mode (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH)
|
||||||
#define romFS_file_mode (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH)
|
#define romFS_file_mode (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH)
|
||||||
|
|
||||||
static ssize_t _romfs_read(romfs_mount *mount, u64 offset, void* buffer, u32 size)
|
static ssize_t _romfs_read(romfs_mount *mount, u64 offset, void* buffer, u64 size)
|
||||||
{
|
{
|
||||||
u64 pos = mount->offset + offset;
|
u64 pos = mount->offset + offset;
|
||||||
size_t read = 0;
|
size_t read = 0;
|
||||||
Result rc = fsFileRead(&mount->fd, pos, buffer, size, &read);
|
Result rc = 0;
|
||||||
|
if(!mount->fd_type)
|
||||||
|
{
|
||||||
|
rc = fsFileRead(&mount->fd, pos, buffer, size, &read);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = fsStorageRead(&mount->fd_storage, pos, buffer, size);
|
||||||
|
read = size;
|
||||||
|
}
|
||||||
if (R_FAILED(rc)) return -1;
|
if (R_FAILED(rc)) return -1;
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _romfs_read_chk(romfs_mount *mount, u64 offset, void* buffer, u32 size)
|
static bool _romfs_read_chk(romfs_mount *mount, u64 offset, void* buffer, u64 size)
|
||||||
{
|
{
|
||||||
return _romfs_read(mount, offset, buffer, size) == size;
|
return _romfs_read(mount, offset, buffer, size) == size;
|
||||||
}
|
}
|
||||||
@ -104,26 +115,8 @@ static devoptab_t romFS_devoptab =
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// File header
|
|
||||||
/*#define _3DSX_MAGIC 0x58534433 // '3DSX'
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
u32 magic;
|
|
||||||
u16 headerSize, relocHdrSize;
|
|
||||||
u32 formatVer;
|
|
||||||
u32 flags;
|
|
||||||
|
|
||||||
// Sizes of the code, rodata and data segments +
|
|
||||||
// size of the BSS section (uninitialized latter half of the data segment)
|
|
||||||
u32 codeSegSize, rodataSegSize, dataSegSize, bssSize;
|
|
||||||
// offset and size of smdh
|
|
||||||
u32 smdhOffset, smdhSize;
|
|
||||||
// offset to filesystem
|
|
||||||
u32 fsOffset;
|
|
||||||
} _3DSX_Header;*/
|
|
||||||
|
|
||||||
static Result romfsMountCommon(romfs_mount *mount);
|
static Result romfsMountCommon(romfs_mount *mount);
|
||||||
//static void romfsInitMtime(romfs_mount *mount, FS_ArchiveID archId, FS_Path archPath, FS_Path filePath);
|
static void romfsInitMtime(romfs_mount *mount);
|
||||||
|
|
||||||
__attribute__((weak)) const char* __romfs_path = NULL;
|
__attribute__((weak)) const char* __romfs_path = NULL;
|
||||||
|
|
||||||
@ -173,9 +166,19 @@ Result romfsMount(struct romfs_mount **p)
|
|||||||
if(mount == NULL)
|
if(mount == NULL)
|
||||||
return 99;
|
return 99;
|
||||||
|
|
||||||
if (/*envIsHomebrew()*/1)//TODO: How to handle?
|
if (!envIsNso())
|
||||||
{
|
{
|
||||||
// RomFS appended to a 3DSX file
|
// RomFS embedded in a NRO
|
||||||
|
|
||||||
|
mount->fd_type = 0;
|
||||||
|
|
||||||
|
FsFileSystem *sdfs = fsdevGetDefaultFileSystem();
|
||||||
|
if(sdfs==NULL)
|
||||||
|
{
|
||||||
|
romfs_free(mount);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
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];
|
||||||
@ -187,69 +190,57 @@ Result romfsMount(struct romfs_mount **p)
|
|||||||
|
|
||||||
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, "nxlink:/", 8) == 0)
|
||||||
{
|
{
|
||||||
strncpy(__component, "/3ds", PATH_MAX);
|
strncpy(__component, "/switch", PATH_MAX);
|
||||||
strncat(__component, filename+8, PATH_MAX);
|
strncat(__component, filename+7, PATH_MAX);
|
||||||
__component[PATH_MAX] = 0;
|
__component[PATH_MAX] = 0;
|
||||||
filename = __component;
|
filename = __component;
|
||||||
}*/
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
romfs_free(mount);
|
romfs_free(mount);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO
|
Result rc = fsFsOpenFile(sdfs, filename, FS_OPEN_READ, &mount->fd);
|
||||||
/*ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)filename, PATH_MAX);
|
|
||||||
if (units < 0)
|
|
||||||
{
|
|
||||||
romfs_free(mount);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
if (units >= PATH_MAX)
|
|
||||||
{
|
|
||||||
romfs_free(mount);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
__utf16path[units] = 0;
|
|
||||||
|
|
||||||
FS_Path archPath = { PATH_EMPTY, 1, (u8*)"" };
|
|
||||||
FS_Path filePath = { PATH_UTF16, (units+1)*2, (u8*)__utf16path };
|
|
||||||
|
|
||||||
Result rc = FSUSER_OpenFileDirectly(&mount->fd, ARCHIVE_SDMC, archPath, filePath, FS_OPEN_READ, 0);
|
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
romfs_free(mount);
|
romfs_free(mount);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
//romfsInitMtime(mount, ARCHIVE_SDMC, archPath, filePath);
|
romfsInitMtime(mount);
|
||||||
|
|
||||||
_3DSX_Header hdr;
|
NroHeader hdr;
|
||||||
if (!_romfs_read_chk(mount, 0, &hdr, sizeof(hdr))) goto _fail0;
|
AssetHeader asset_header;
|
||||||
if (hdr.magic != _3DSX_MAGIC) goto _fail0;
|
|
||||||
if (hdr.headerSize < sizeof(hdr)) goto _fail0;
|
if (!_romfs_read_chk(mount, sizeof(NroStart), &hdr, sizeof(hdr))) goto _fail0;
|
||||||
mount->offset = hdr.fsOffset;
|
if (hdr.Magic != NROHEADER_MAGICNUM) goto _fail0;
|
||||||
if (!mount->offset) goto _fail0;*/
|
if (!_romfs_read_chk(mount, hdr.size, &asset_header, sizeof(asset_header))) goto _fail0;
|
||||||
|
|
||||||
|
if (asset_header.magic != ASSETHEADER_MAGICNUM
|
||||||
|
|| asset_header.version > ASSETHEADER_VERSION
|
||||||
|
|| asset_header.romfs.offset == 0
|
||||||
|
|| asset_header.romfs.size == 0)
|
||||||
|
goto _fail0;
|
||||||
|
|
||||||
|
mount->offset = hdr.size + asset_header.romfs.offset;
|
||||||
}
|
}
|
||||||
else//TODO
|
else
|
||||||
{
|
{
|
||||||
// Regular RomFS
|
// Regular RomFS
|
||||||
/*u8 zeros[0xC];
|
|
||||||
memset(zeros, 0, sizeof(zeros));
|
|
||||||
|
|
||||||
FS_Path archPath = { PATH_EMPTY, 1, (u8*)"" };
|
mount->fd_type = 1;
|
||||||
FS_Path filePath = { PATH_BINARY, sizeof(zeros), zeros };
|
|
||||||
|
|
||||||
Result rc = FSUSER_OpenFileDirectly(&mount->fd, ARCHIVE_ROMFS, archPath, filePath, FS_OPEN_READ, 0);
|
Result rc = fsOpenDataStorageByCurrentProcess(&mount->fd_storage);
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
romfs_free(mount);
|
romfs_free(mount);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
//romfsInitMtime(mount, ARCHIVE_ROMFS, archPath, filePath);*/
|
romfsInitMtime(mount);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ret = romfsMountCommon(mount);
|
Result ret = romfsMountCommon(mount);
|
||||||
@ -258,8 +249,9 @@ Result romfsMount(struct romfs_mount **p)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
//_fail0:
|
_fail0:
|
||||||
fsFileClose(&mount->fd);
|
if(!mount->fd_type)fsFileClose(&mount->fd);
|
||||||
|
if(mount->fd_type)fsStorageClose(&mount->fd_storage);
|
||||||
romfs_free(mount);
|
romfs_free(mount);
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
@ -270,6 +262,7 @@ Result romfsMountFromFile(FsFile file, u64 offset, struct romfs_mount **p)
|
|||||||
if(mount == NULL)
|
if(mount == NULL)
|
||||||
return 99;
|
return 99;
|
||||||
|
|
||||||
|
mount->fd_type = 0;
|
||||||
mount->fd = file;
|
mount->fd = file;
|
||||||
mount->offset = offset;
|
mount->offset = offset;
|
||||||
|
|
||||||
@ -280,6 +273,23 @@ Result romfsMountFromFile(FsFile file, u64 offset, struct romfs_mount **p)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result romfsMountFromStorage(FsStorage storage, u64 offset, struct romfs_mount **p)
|
||||||
|
{
|
||||||
|
romfs_mount *mount = romfs_alloc();
|
||||||
|
if(mount == NULL)
|
||||||
|
return 99;
|
||||||
|
|
||||||
|
mount->fd_type = 1;
|
||||||
|
mount->fd_storage = storage;
|
||||||
|
mount->offset = offset;
|
||||||
|
|
||||||
|
Result ret = romfsMountCommon(mount);
|
||||||
|
if(R_SUCCEEDED(ret) && p)
|
||||||
|
*p = mount;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
Result romfsMountCommon(romfs_mount *mount)
|
Result romfsMountCommon(romfs_mount *mount)
|
||||||
{
|
{
|
||||||
if (_romfs_read(mount, 0, &mount->header, sizeof(mount->header)) != sizeof(mount->header))
|
if (_romfs_read(mount, 0, &mount->header, sizeof(mount->header)) != sizeof(mount->header))
|
||||||
@ -318,35 +328,16 @@ Result romfsMountCommon(romfs_mount *mount)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
fsFileClose(&mount->fd);
|
if(!mount->fd_type)fsFileClose(&mount->fd);
|
||||||
|
if(mount->fd_type)fsStorageClose(&mount->fd_storage);
|
||||||
romfs_free(mount);
|
romfs_free(mount);
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static void romfsInitMtime(romfs_mount *mount, FS_ArchiveID archId, FS_Path archPath, FS_Path filePath)
|
static void romfsInitMtime(romfs_mount *mount)
|
||||||
{
|
{
|
||||||
u64 mtime;
|
|
||||||
FS_Archive arch;
|
|
||||||
Result rc;
|
|
||||||
|
|
||||||
mount->mtime = time(NULL);
|
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)
|
Result romfsBind(struct romfs_mount *mount)
|
||||||
{
|
{
|
||||||
@ -368,7 +359,8 @@ Result romfsUnmount(struct romfs_mount *mount)
|
|||||||
if(mount)
|
if(mount)
|
||||||
{
|
{
|
||||||
// unmount specific
|
// unmount specific
|
||||||
fsFileClose(&mount->fd);
|
if(!mount->fd_type)fsFileClose(&mount->fd);
|
||||||
|
if(mount->fd_type)fsStorageClose(&mount->fd_storage);
|
||||||
romfs_free(mount);
|
romfs_free(mount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -376,7 +368,8 @@ Result romfsUnmount(struct romfs_mount *mount)
|
|||||||
// unmount everything
|
// unmount everything
|
||||||
while(romfs_mount_list)
|
while(romfs_mount_list)
|
||||||
{
|
{
|
||||||
fsFileClose(&romfs_mount_list->fd);
|
if(!romfs_mount_list->fd_type)fsFileClose(&romfs_mount_list->fd);
|
||||||
|
if(romfs_mount_list->fd_type)fsStorageClose(&romfs_mount_list->fd_storage);
|
||||||
romfs_free(romfs_mount_list);
|
romfs_free(romfs_mount_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,7 +476,7 @@ static int navigateToDir(romfs_mount *mount, romfs_dir** ppDir, const char** pPa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*ppDir = searchForDir(mount, *ppDir, (uint8_t*)component, strlen(component)+1);
|
*ppDir = searchForDir(mount, *ppDir, (uint8_t*)component, strlen(component));
|
||||||
if (!*ppDir)
|
if (!*ppDir)
|
||||||
return EEXIST;
|
return EEXIST;
|
||||||
}
|
}
|
||||||
@ -551,7 +544,7 @@ int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags,
|
|||||||
if (r->_errno != 0)
|
if (r->_errno != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
romfs_file* file = searchForFile(fileobj->mount, curDir, (uint8_t*)path, strlen(path)+1);
|
romfs_file* file = searchForFile(fileobj->mount, curDir, (uint8_t*)path, strlen(path));
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
if(flags & O_CREAT)
|
if(flags & O_CREAT)
|
||||||
@ -567,7 +560,7 @@ int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileobj->file = file;
|
fileobj->file = file;
|
||||||
fileobj->offset = (u64)fileobj->mount->header.fileDataOff + file->dataOff;
|
fileobj->offset = fileobj->mount->header.fileDataOff + file->dataOff;
|
||||||
fileobj->pos = 0;
|
fileobj->pos = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -669,7 +662,7 @@ int romfs_stat(struct _reent *r, const char *path, struct stat *st)
|
|||||||
if(r->_errno != 0)
|
if(r->_errno != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
romfs_dir* dir = searchForDir(mount, curDir, (uint8_t*)path, strlen(path)+1);
|
romfs_dir* dir = searchForDir(mount, curDir, (uint8_t*)path, strlen(path));
|
||||||
if(dir)
|
if(dir)
|
||||||
{
|
{
|
||||||
memset(st, 0, sizeof(*st));
|
memset(st, 0, sizeof(*st));
|
||||||
@ -684,7 +677,7 @@ int romfs_stat(struct _reent *r, const char *path, struct stat *st)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
romfs_file* file = searchForFile(mount, curDir, (uint8_t*)path, strlen(path)+1);
|
romfs_file* file = searchForFile(mount, curDir, (uint8_t*)path, strlen(path));
|
||||||
if(file)
|
if(file)
|
||||||
{
|
{
|
||||||
memset(st, 0, sizeof(*st));
|
memset(st, 0, sizeof(*st));
|
||||||
|
@ -131,6 +131,41 @@ Result fsMountSaveData(FsFileSystem* out, u8 inval, FsSave *save) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result fsOpenDataStorageByCurrentProcess(FsStorage* out) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 200;
|
||||||
|
|
||||||
|
Result rc = serviceIpcDispatch(&g_fsSrv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
out->h = r.Handles[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
// Wrapper(s) for fsMountSaveData.
|
// Wrapper(s) for fsMountSaveData.
|
||||||
Result fsMount_SaveData(FsFileSystem* out, u64 titleID, u128 userID) {
|
Result fsMount_SaveData(FsFileSystem* out, u64 titleID, u128 userID) {
|
||||||
FsSave save;
|
FsSave save;
|
||||||
@ -595,7 +630,7 @@ Result fsFsGetTotalSpace(FsFileSystem* fs, const char* path, u64* out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void fsFsClose(FsFileSystem* fs) {
|
void fsFsClose(FsFileSystem* fs) {
|
||||||
svcCloseHandle(fs->h);
|
if(fs->h != INVALID_HANDLE) svcCloseHandle(fs->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFile implementation
|
// IFile implementation
|
||||||
@ -778,12 +813,12 @@ Result fsFileGetSize(FsFile* f, u64* out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void fsFileClose(FsFile* f) {
|
void fsFileClose(FsFile* f) {
|
||||||
svcCloseHandle(f->h);
|
if(f->h != INVALID_HANDLE) svcCloseHandle(f->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDirectory implementation
|
// IDirectory implementation
|
||||||
void fsDirClose(FsDir* d) {
|
void fsDirClose(FsDir* d) {
|
||||||
svcCloseHandle(d->h);
|
if(d->h != INVALID_HANDLE) svcCloseHandle(d->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result fsDirRead(FsDir* d, u64 inval, size_t* total_entries, size_t max_entries, FsDirectoryEntry *buf) {
|
Result fsDirRead(FsDir* d, u64 inval, size_t* total_entries, size_t max_entries, FsDirectoryEntry *buf) {
|
||||||
@ -858,3 +893,44 @@ Result fsDirGetEntryCount(FsDir* d, u64* count) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IStorage implementation
|
||||||
|
Result fsStorageRead(FsStorage* s, u64 off, void* buf, size_t len) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
ipcAddRecvBuffer(&c, buf, len, 1);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u64 offset;
|
||||||
|
u64 read_size;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 0;
|
||||||
|
raw->offset = off;
|
||||||
|
raw->read_size = len;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(s->h);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsStorageClose(FsStorage* s) {
|
||||||
|
if(s->h != INVALID_HANDLE) svcCloseHandle(s->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user