From 8cf419802a41d80a7cd3ce8cb33f9d98f85941b3 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 4 Jun 2019 04:51:21 +1000 Subject: [PATCH] Implement fsOpenContentStorageFileSystem, fsGetRightsIdByPath & fsGetRightsIdAndKeyGenerationByPath (#288) * Implement fsOpenContentStorageFileSystem, fsGetRightsIdByPath & fsGetRightsIdAndKeyGenerationByPath --- nx/include/switch/services/fs.h | 11 +++ nx/include/switch/services/ncm.h | 6 +- nx/source/services/fs.c | 125 +++++++++++++++++++++++++++++++ nx/source/services/ncm.c | 6 +- 4 files changed, 140 insertions(+), 8 deletions(-) diff --git a/nx/include/switch/services/fs.h b/nx/include/switch/services/fs.h index 73655332..70acd30f 100644 --- a/nx/include/switch/services/fs.h +++ b/nx/include/switch/services/fs.h @@ -20,6 +20,10 @@ /// For use with \ref FsSave and \ref FsSaveDataInfo. #define FS_SAVEDATA_USERID_COMMONSAVE 0 +typedef struct { + u8 c[0x10]; +} FsRightsId; + typedef struct { Service s; } FsFileSystem; @@ -230,10 +234,17 @@ Result fsMountSdcard(FsFileSystem* out); 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 fsOpenDataStorageByCurrentProcess(FsStorage* out); Result fsOpenDataStorageByDataId(FsStorage* out, u64 dataId, FsStorageId storageId); Result fsOpenDeviceOperator(FsDeviceOperator* out); Result fsOpenSdCardDetectionEventNotifier(FsEventNotifier* out); + +/// Retrieves the rights id corresponding to the content path. Only available on [2.0.0+]. +Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id); + +/// Retrieves the rights id and key generation corresponding to the content path. Only available on [3.0.0+]. +Result fsGetRightsIdAndKeyGenerationByPath(const char* path, u8* out_key_generation, FsRightsId* out_rights_id); // todo: Rest of commands here /// FsFileSystem can be mounted with fs_dev for use with stdio, see fs_dev.h. diff --git a/nx/include/switch/services/ncm.h b/nx/include/switch/services/ncm.h index 94e008d0..139cc74f 100644 --- a/nx/include/switch/services/ncm.h +++ b/nx/include/switch/services/ncm.h @@ -74,10 +74,6 @@ typedef struct { u64 baseTitleId; } NcmApplicationContentMetaKey; -typedef struct { - u8 c[0x10]; -} NcmRightsId; - Result ncmInitialize(void); void ncmExit(void); @@ -97,7 +93,7 @@ Result ncmContentStorageCleanupAllPlaceHolder(NcmContentStorage* cs); Result ncmContentStorageGetSize(NcmContentStorage* cs, const NcmNcaId* ncaId, u64* out); Result ncmContentStorageDisableForcibly(NcmContentStorage* cs); Result ncmContentStorageReadContentIdFile(NcmContentStorage* cs, const NcmNcaId* ncaId, u64 offset, void* outBuf, size_t bufSize); -Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, const NcmNcaId* ncaId, NcmRightsId* rightsIdOut, u32* keyGenerationOut); +Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, const NcmNcaId* ncaId, FsRightsId* rightsIdOut, u32* keyGenerationOut); Result ncmContentMetaDatabaseSet(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u64 inDataSize, const NcmContentMetaRecordsHeader* srcRecordsData); Result ncmContentMetaDatabaseGet(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u64 outDataSize, NcmContentMetaRecordsHeader* outRecordsData, u64* sizeRead); diff --git a/nx/source/services/fs.c b/nx/source/services/fs.c index f2492d51..1653e5bc 100644 --- a/nx/source/services/fs.c +++ b/nx/source/services/fs.c @@ -317,6 +317,44 @@ Result fsOpenSaveDataIterator(FsSaveDataIterator* out, s32 SaveDataSpaceId) { return rc; } +Result fsOpenContentStorageFileSystem(FsFileSystem* out, FsContentStorageId content_storage_id) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 content_storage_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 110; + raw->content_storage_id = content_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); @@ -465,6 +503,93 @@ Result fsOpenSdCardDetectionEventNotifier(FsEventNotifier* out) { return rc; } +Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + char send_path[FS_MAX_PATH] = {0}; + IpcCommand c; + ipcInitialize(&c); + ipcAddSendStatic(&c, send_path, FS_MAX_PATH, 0); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 609; + + strncpy(send_path, path, FS_MAX_PATH-1); + Result rc = serviceIpcDispatch(&g_fsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + FsRightsId rights_id; + } *resp; + + serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (out_rights_id) *out_rights_id = resp->rights_id; + } + } + + return rc; +} + +Result fsGetRightsIdAndKeyGenerationByPath(const char* path, u8* out_key_generation, FsRightsId* out_rights_id) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + char send_path[FS_MAX_PATH] = {0}; + IpcCommand c; + ipcInitialize(&c); + ipcAddSendStatic(&c, send_path, FS_MAX_PATH, 0); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 610; + + strncpy(send_path, path, FS_MAX_PATH-1); + Result rc = serviceIpcDispatch(&g_fsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u8 key_generation; + u8 padding[0x7]; + FsRightsId rights_id; + } *resp; + + serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (out_key_generation) *out_key_generation = resp->key_generation; + if (out_rights_id) *out_rights_id = resp->rights_id; + } + } + + return rc; +} + Result fsIsExFatSupported(bool* out) { if (hosversionBefore(2,0,0)) { diff --git a/nx/source/services/ncm.c b/nx/source/services/ncm.c index 25cbd8a7..100cfb6c 100644 --- a/nx/source/services/ncm.c +++ b/nx/source/services/ncm.c @@ -542,7 +542,7 @@ Result ncmContentStorageReadContentIdFile(NcmContentStorage* cs, const NcmNcaId* return rc; } -Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, const NcmNcaId* ncaId, NcmRightsId* rightsIdOut, u32* keyGenerationOut) { +Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, const NcmNcaId* ncaId, FsRightsId* rightsIdOut, u32* keyGenerationOut) { IpcCommand c; ipcInitialize(&c); @@ -566,14 +566,14 @@ Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, const Nc struct { u64 magic; u64 result; - NcmRightsId rights_id; + FsRightsId rights_id; u32 key_generation; } *resp = r.Raw; rc = resp->result; if (R_SUCCEEDED(rc)) { - if (rightsIdOut) memcpy(rightsIdOut, &resp->rights_id, sizeof(NcmRightsId)); + if (rightsIdOut) memcpy(rightsIdOut, &resp->rights_id, sizeof(FsRightsId)); if (keyGenerationOut) *keyGenerationOut = resp->key_generation; } }