From 758db03ca45bef7076c371c80a272bec24ea20a6 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Sat, 17 Aug 2019 10:36:43 -0500 Subject: [PATCH] Add some FS commands (#321) * Implement fsOpenCustomStorageFileSystem * Add more FS commands fsExtendSaveDataFileSystem fsSetGlobalAccessLogMode fsGetGlobalAccessLogMode * Savedata sizes are signed. --- nx/include/switch/services/fs.h | 19 +++- nx/source/services/fs.c | 156 ++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 4 deletions(-) diff --git a/nx/include/switch/services/fs.h b/nx/include/switch/services/fs.h index 14155c5a..59af3c7a 100644 --- a/nx/include/switch/services/fs.h +++ b/nx/include/switch/services/fs.h @@ -84,16 +84,16 @@ typedef struct { u64 timestamp; ///< POSIX timestamp. u32 flags; ///< Save data flags. See \ref FsSaveDataFlags. u32 unk_x54; ///< Normally 0. Possibly unused? - u64 dataSize; ///< Usable save data size. - u64 journalSize; ///< Journal size of the save data. + s64 dataSize; ///< Usable save data size. + s64 journalSize; ///< Journal size of the save data. u64 commitId; ///< Id of the latest commit. u8 unused[0x190]; ///< Uninitialized. } FsSaveDataExtraData; /// SaveCreate Struct typedef struct { - u64 size; ///< Size of the save data. - u64 journalSize; ///< Journal size of the save data. + s64 size; ///< Size of the save data. + s64 journalSize; ///< Journal size of the save data. u64 blockSize; ///< Block size of the save data. u64 ownerId; ///< Title id of the owner of this save data. 0 for SystemSaveData. u32 flags; ///< Save data flags. See \ref FsSaveDataFlags. @@ -179,6 +179,12 @@ typedef enum FS_CONTENTSTORAGEID_SdCard = 2, } FsContentStorageId; +typedef enum +{ + FsCustomStorageId_NandUser = 0, + FsCustomStorageId_SdCard = 1, +} FsCustomStorageId; + typedef enum { FsSaveDataSpaceId_NandSystem = 0, @@ -272,6 +278,7 @@ Result fsOpenGameCardFileSystem(FsFileSystem* out, const FsGameCardHandle* handl Result fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(void* buf, size_t len, FsSaveDataSpaceId saveDataSpaceId, u64 saveID); Result fsReadSaveDataFileSystemExtraData(void* buf, size_t len, u64 saveID); Result fsWriteSaveDataFileSystemExtraData(const void* buf, size_t len, FsSaveDataSpaceId saveDataSpaceId, u64 saveID); +Result fsExtendSaveDataFileSystem(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, s64 dataSize, s64 journalSize); /// 3.0.0+ /// Do not call this directly, see fs_dev.h. Result fsMountSdcard(FsFileSystem* out); @@ -280,6 +287,7 @@ Result fsMountSaveData(FsFileSystem* out, u8 inval, FsSave *save); Result fsMountSystemSaveData(FsFileSystem* out, u8 inval, FsSave *save); Result fsOpenSaveDataIterator(FsSaveDataIterator* out, s32 saveDataSpaceId); Result fsOpenContentStorageFileSystem(FsFileSystem* out, FsContentStorageId content_storage_id); +Result fsOpenCustomStorageFileSystem(FsFileSystem* out, FsCustomStorageId custom_storage_id); /// 7.0.0+ Result fsOpenDataStorageByCurrentProcess(FsStorage* out); Result fsOpenDataStorageByDataId(FsStorage* out, u64 dataId, FsStorageId storageId); Result fsOpenDeviceOperator(FsDeviceOperator* out); @@ -292,6 +300,9 @@ Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id); Result fsGetRightsIdAndKeyGenerationByPath(const char* path, u8* out_key_generation, FsRightsId* out_rights_id); Result fsDisableAutoSaveDataCreation(void); + +Result fsSetGlobalAccessLogMode(u32 mode); +Result fsGetGlobalAccessLogMode(u32* out_mode); // todo: Rest of commands here // Wrapper(s) for fsCreateSaveDataFileSystemBySystemSaveDataId. diff --git a/nx/source/services/fs.c b/nx/source/services/fs.c index 5e4fdbb2..c384efd8 100644 --- a/nx/source/services/fs.c +++ b/nx/source/services/fs.c @@ -427,6 +427,47 @@ Result fsOpenContentStorageFileSystem(FsFileSystem* out, FsContentStorageId cont return rc; } +Result fsOpenCustomStorageFileSystem(FsFileSystem* out, FsCustomStorageId custom_storage_id) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 custom_storage_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 130; + raw->custom_storage_id = custom_storage_id; + + Result rc = serviceIpcDispatch(&g_fsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); + } + } + + return rc; +} + Result fsOpenDataStorageByCurrentProcess(FsStorage* out) { IpcCommand c; ipcInitialize(&c); @@ -891,6 +932,121 @@ Result fsWriteSaveDataFileSystemExtraData(const void* buf, size_t len, FsSaveDat return rc; } +Result fsExtendSaveDataFileSystem(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, s64 dataSize, s64 journalSize) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 saveDataSpaceId; + u64 saveID; + s64 dataSize; + s64 journalSize; + } *raw; + + raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 32; + raw->saveDataSpaceId = saveDataSpaceId; + raw->saveID = saveID; + raw->dataSize = dataSize; + raw->saveID = saveID; + raw->journalSize = journalSize; + + Result rc = serviceIpcDispatch(&g_fsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result fsSetGlobalAccessLogMode(u32 mode) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 mode; + } *raw; + + raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1004; + raw->mode = mode; + + Result rc = serviceIpcDispatch(&g_fsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result fsGetGlobalAccessLogMode(u32* out_mode) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1005; + + Result rc = serviceIpcDispatch(&g_fsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u32 mode; + } *resp; + + serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *out_mode = resp->mode; + } + } + + return rc; +} + // Wrapper(s) for fsCreateSaveDataFileSystemBySystemSaveDataId. Result fsCreate_SystemSaveDataWithOwner(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, u128 userID, u64 ownerId, u64 size, u64 journalSize, u32 flags) { FsSave save = {