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:
yellows8 2018-03-26 14:45:12 -04:00
parent 45b36774e0
commit 26d2e6d7f4
2 changed files with 162 additions and 17 deletions

View File

@ -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);

View File

@ -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;
}
} }