mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-22 04:52:39 +02:00
Implemented FsSaveDataIterator (aka ISaveDataInfoReader). In fs*Close(), set the handle to INVALID_HANDLE after closing the handle. Changed ContentStorageId in FsSave to SaveDataType. Added enums FsSaveDataSpaceId and FsSaveDataType. Removed FS_MOUNTSAVEDATA_INVAL_DEFAULT/FS_MOUNTSYSTEMSAVEDATA_INVAL_DEFAULT.
This commit is contained in:
parent
45b36774e0
commit
26d2e6d7f4
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @file fs.h
|
* @file fs.h
|
||||||
* @brief Filesystem (fsp-srv) service IPC wrapper.
|
* @brief Filesystem (fsp-srv) service IPC wrapper.
|
||||||
* Normally applications should just use standard stdio not FS-serv directly. However this can be used if obtaining a FsFileSystem, FsFile, or FsStorage, for mounting with fs_dev/romfs_dev.
|
* Normally applications should just use standard stdio not FS-serv directly. However this can be used if obtaining a FsFileSystem, FsFile, or FsStorage, for mounting with fs_dev/romfs_dev, etc.
|
||||||
* @author plutoo
|
* @author plutoo
|
||||||
* @author yellows8
|
* @author yellows8
|
||||||
* @copyright libnx Authors
|
* @copyright libnx Authors
|
||||||
@ -14,16 +14,10 @@
|
|||||||
|
|
||||||
#define FS_MAX_PATH 0x301
|
#define FS_MAX_PATH 0x301
|
||||||
|
|
||||||
/// For use with fsMountSaveData().
|
|
||||||
#define FS_MOUNTSAVEDATA_INVAL_DEFAULT 0x1
|
|
||||||
|
|
||||||
/// For use with fsMountSystemSaveData().
|
|
||||||
#define FS_MOUNTSYSTEMSAVEDATA_INVAL_DEFAULT 0x0
|
|
||||||
|
|
||||||
/// For use with FsSave.
|
/// For use with FsSave.
|
||||||
#define FS_SAVEDATA_CURRENT_TITLEID 0
|
#define FS_SAVEDATA_CURRENT_TITLEID 0
|
||||||
|
|
||||||
/// For use with FsSave.
|
/// For use with \ref FsSave and \ref FsSaveDataInfo.
|
||||||
#define FS_SAVEDATA_USERID_COMMONSAVE 0
|
#define FS_SAVEDATA_USERID_COMMONSAVE 0
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -42,6 +36,10 @@ typedef struct {
|
|||||||
Handle h;
|
Handle h;
|
||||||
} FsStorage;
|
} FsStorage;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Handle h;
|
||||||
|
} FsSaveDataIterator;
|
||||||
|
|
||||||
/// Directory entry.
|
/// Directory entry.
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -58,12 +56,25 @@ typedef struct
|
|||||||
u64 titleID; ///< titleID of the savedata to access when accessing other titles' savedata via SaveData, otherwise FS_SAVEDATA_CURRENT_TITLEID.
|
u64 titleID; ///< titleID of the savedata to access when accessing other titles' savedata via SaveData, otherwise FS_SAVEDATA_CURRENT_TITLEID.
|
||||||
u128 userID; ///< userID of the user-specific savedata to access, otherwise FS_SAVEDATA_USERID_COMMONSAVE. See account.h.
|
u128 userID; ///< userID of the user-specific savedata to access, otherwise FS_SAVEDATA_USERID_COMMONSAVE. See account.h.
|
||||||
u64 saveID; ///< saveID, 0 for SaveData.
|
u64 saveID; ///< saveID, 0 for SaveData.
|
||||||
u64 ContentStorageId; ///< ContentStorageId? See FsContentStorageId.
|
u64 SaveDataType; ///< See \ref FsSaveDataType.
|
||||||
u64 unk_x28; ///< 0 for SystemSaveData/SaveData.
|
u64 unk_x28; ///< 0 for SystemSaveData/SaveData.
|
||||||
u64 unk_x30; ///< 0 for SystemSaveData/SaveData.
|
u64 unk_x30; ///< 0 for SystemSaveData/SaveData.
|
||||||
u64 unk_x38; ///< 0 for SystemSaveData/SaveData.
|
u64 unk_x38; ///< 0 for SystemSaveData/SaveData.
|
||||||
} PACKED FsSave;
|
} PACKED FsSave;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u64 saveID_unk;
|
||||||
|
u8 SaveDataSpaceId; ///< See \ref FsSaveDataSpaceId.
|
||||||
|
u8 SaveDataType; ///< See \ref FsSaveDataType.
|
||||||
|
u8 pad[6];
|
||||||
|
u128 userID; ///< See userID for \ref FsSave.
|
||||||
|
u64 saveID; ///< See saveID for \ref FsSave.
|
||||||
|
u64 titleID; ///< titleID for FsSaveDataType_SaveData.
|
||||||
|
u64 size; ///< Raw saveimage size.
|
||||||
|
u8 unk_x38[0x28]; ///< Unknown. Usually zeros?
|
||||||
|
} PACKED FsSaveDataInfo;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ENTRYTYPE_DIR = 0,
|
ENTRYTYPE_DIR = 0,
|
||||||
ENTRYTYPE_FILE = 1
|
ENTRYTYPE_FILE = 1
|
||||||
@ -90,6 +101,26 @@ typedef enum
|
|||||||
FS_CONTENTSTORAGEID_SdCard = 2,
|
FS_CONTENTSTORAGEID_SdCard = 2,
|
||||||
} FsContentStorageId;
|
} FsContentStorageId;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FsSaveDataSpaceId_NandSystem = 0,
|
||||||
|
FsSaveDataSpaceId_NandUser = 1,
|
||||||
|
FsSaveDataSpaceId_SdCard = 2,
|
||||||
|
FsSaveDataSpaceId_TemporaryStorage = 3,
|
||||||
|
|
||||||
|
FsSaveDataSpaceId_All = -1, ///< Pseudo value for fsOpenSaveDataIterator().
|
||||||
|
} FsSaveDataSpaceId;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FsSaveDataType_SystemSaveData = 0,
|
||||||
|
FsSaveDataType_SaveData = 1,
|
||||||
|
FsSaveDataType_BcatDeliveryCacheStorage = 2,
|
||||||
|
FsSaveDataType_DeviceSaveData = 3,
|
||||||
|
FsSaveDataType_TemporaryStorage = 4, ///< [3.0.0+]
|
||||||
|
FsSaveDataType_CacheStorage = 5, ///< [3.0.0+]
|
||||||
|
} FsSaveDataType;
|
||||||
|
|
||||||
Result fsInitialize(void);
|
Result fsInitialize(void);
|
||||||
void fsExit(void);
|
void fsExit(void);
|
||||||
|
|
||||||
@ -100,6 +131,7 @@ Result fsMountSdcard(FsFileSystem* out);
|
|||||||
|
|
||||||
Result fsMountSaveData(FsFileSystem* out, u8 inval, FsSave *save);
|
Result fsMountSaveData(FsFileSystem* out, u8 inval, FsSave *save);
|
||||||
Result fsMountSystemSaveData(FsFileSystem* out, u8 inval, FsSave *save);
|
Result fsMountSystemSaveData(FsFileSystem* out, u8 inval, FsSave *save);
|
||||||
|
Result fsOpenSaveDataIterator(FsSaveDataIterator* out, s32 SaveDataSpaceId);
|
||||||
Result fsOpenDataStorageByCurrentProcess(FsStorage* out);
|
Result fsOpenDataStorageByCurrentProcess(FsStorage* out);
|
||||||
// todo: Rest of commands here
|
// todo: Rest of commands here
|
||||||
|
|
||||||
@ -145,3 +177,9 @@ void fsDirClose(FsDir* d);
|
|||||||
// IStorage
|
// IStorage
|
||||||
Result fsStorageRead(FsStorage* s, u64 off, void* buf, size_t len);
|
Result fsStorageRead(FsStorage* s, u64 off, void* buf, size_t len);
|
||||||
void fsStorageClose(FsStorage* s);
|
void fsStorageClose(FsStorage* s);
|
||||||
|
|
||||||
|
// ISaveDataInfoReader
|
||||||
|
|
||||||
|
/// Read FsSaveDataInfo data into the buf array.
|
||||||
|
Result fsSaveDataIteratorRead(FsSaveDataIterator *s, FsSaveDataInfo* buf, size_t max_entries, size_t* total_entries);
|
||||||
|
void fsSaveDataIteratorClose(FsSaveDataIterator *s);
|
||||||
|
@ -177,6 +177,56 @@ Result fsMountSystemSaveData(FsFileSystem* out, u8 inval, FsSave *save) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result fsOpenSaveDataIterator(FsSaveDataIterator* out, s32 SaveDataSpaceId) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u8 SaveDataSpaceId;
|
||||||
|
} *raw2;
|
||||||
|
|
||||||
|
if (SaveDataSpaceId == FsSaveDataSpaceId_All) {
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 60;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
raw2 = ipcPrepareHeader(&c, sizeof(*raw2));
|
||||||
|
|
||||||
|
raw2->magic = SFCI_MAGIC;
|
||||||
|
raw2->cmd_id = 61;
|
||||||
|
raw2->SaveDataSpaceId = SaveDataSpaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
Result fsOpenDataStorageByCurrentProcess(FsStorage* out) {
|
Result fsOpenDataStorageByCurrentProcess(FsStorage* out) {
|
||||||
IpcCommand c;
|
IpcCommand c;
|
||||||
ipcInitialize(&c);
|
ipcInitialize(&c);
|
||||||
@ -219,9 +269,9 @@ Result fsMount_SaveData(FsFileSystem* out, u64 titleID, u128 userID) {
|
|||||||
memset(&save, 0, sizeof(save));
|
memset(&save, 0, sizeof(save));
|
||||||
save.titleID = titleID;
|
save.titleID = titleID;
|
||||||
save.userID = userID;
|
save.userID = userID;
|
||||||
save.ContentStorageId = FS_CONTENTSTORAGEID_NandUser;
|
save.SaveDataType = FsSaveDataType_SaveData;
|
||||||
|
|
||||||
return fsMountSaveData(out, FS_MOUNTSAVEDATA_INVAL_DEFAULT, &save);
|
return fsMountSaveData(out, FsSaveDataSpaceId_NandUser, &save);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result fsMount_SystemSaveData(FsFileSystem* out, u64 saveID) {
|
Result fsMount_SystemSaveData(FsFileSystem* out, u64 saveID) {
|
||||||
@ -229,9 +279,9 @@ Result fsMount_SystemSaveData(FsFileSystem* out, u64 saveID) {
|
|||||||
|
|
||||||
memset(&save, 0, sizeof(save));
|
memset(&save, 0, sizeof(save));
|
||||||
save.saveID = saveID;
|
save.saveID = saveID;
|
||||||
save.ContentStorageId = FS_CONTENTSTORAGEID_NandSystem;
|
save.SaveDataType = FsSaveDataType_SystemSaveData;
|
||||||
|
|
||||||
return fsMountSystemSaveData(out, FS_MOUNTSYSTEMSAVEDATA_INVAL_DEFAULT, &save);
|
return fsMountSystemSaveData(out, FsSaveDataSpaceId_NandSystem, &save);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFileSystem impl
|
// IFileSystem impl
|
||||||
@ -686,7 +736,10 @@ Result fsFsGetTotalSpace(FsFileSystem* fs, const char* path, u64* out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void fsFsClose(FsFileSystem* fs) {
|
void fsFsClose(FsFileSystem* fs) {
|
||||||
if(fs->h != INVALID_HANDLE) svcCloseHandle(fs->h);
|
if(fs->h != INVALID_HANDLE) {
|
||||||
|
svcCloseHandle(fs->h);
|
||||||
|
fs->h = INVALID_HANDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFile implementation
|
// IFile implementation
|
||||||
@ -869,12 +922,18 @@ Result fsFileGetSize(FsFile* f, u64* out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void fsFileClose(FsFile* f) {
|
void fsFileClose(FsFile* f) {
|
||||||
if(f->h != INVALID_HANDLE) svcCloseHandle(f->h);
|
if(f->h != INVALID_HANDLE) {
|
||||||
|
svcCloseHandle(f->h);
|
||||||
|
f->h = INVALID_HANDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDirectory implementation
|
// IDirectory implementation
|
||||||
void fsDirClose(FsDir* d) {
|
void fsDirClose(FsDir* d) {
|
||||||
if(d->h != INVALID_HANDLE) svcCloseHandle(d->h);
|
if(d->h != INVALID_HANDLE) {
|
||||||
|
svcCloseHandle(d->h);
|
||||||
|
d->h = INVALID_HANDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@ -987,6 +1046,54 @@ Result fsStorageRead(FsStorage* s, u64 off, void* buf, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void fsStorageClose(FsStorage* s) {
|
void fsStorageClose(FsStorage* s) {
|
||||||
if(s->h != INVALID_HANDLE) svcCloseHandle(s->h);
|
if(s->h != INVALID_HANDLE) {
|
||||||
|
svcCloseHandle(s->h);
|
||||||
|
s->h = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISaveDataInfoReader
|
||||||
|
Result fsSaveDataIteratorRead(FsSaveDataIterator *s, FsSaveDataInfo* buf, size_t max_entries, size_t* total_entries) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
ipcAddRecvBuffer(&c, buf, sizeof(FsSaveDataInfo)*max_entries, 0);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 0;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(s->h);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 total_entries;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (total_entries) *total_entries = resp->total_entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsSaveDataIteratorClose(FsSaveDataIterator* s) {
|
||||||
|
if(s->h != INVALID_HANDLE) {
|
||||||
|
svcCloseHandle(s->h);
|
||||||
|
s->h = INVALID_HANDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user