Introducing fs..

This commit is contained in:
plutoo 2017-10-07 22:49:16 +02:00
parent 3926969ebc
commit 74b14f4c63
4 changed files with 782 additions and 4 deletions

View File

@ -19,6 +19,7 @@ extern "C" {
#include <switch/kernel/virtmem.h> #include <switch/kernel/virtmem.h>
#include <switch/services/sm.h> #include <switch/services/sm.h>
#include <switch/services/fs.h>
#include <switch/services/bsd.h> #include <switch/services/bsd.h>
#include <switch/services/fatal.h> #include <switch/services/fatal.h>
#include <switch/services/vi.h> #include <switch/services/vi.h>

View File

@ -8,13 +8,13 @@ typedef struct {
size_t NumSend; // A size_t NumSend; // A
size_t NumRecv; // B size_t NumRecv; // B
size_t NumTransfer; // W size_t NumTransfer; // W
void* Buffers[4]; const void* Buffers[4];
size_t BufferSizes[4]; size_t BufferSizes[4];
u8 Flags[4]; u8 Flags[4];
size_t NumStaticIn; // X size_t NumStaticIn; // X
size_t NumStaticOut; // C size_t NumStaticOut; // C
void* Statics[4]; const void* Statics[4];
size_t StaticSizes[4]; size_t StaticSizes[4];
u8 Indices[4]; u8 Indices[4];
@ -53,7 +53,7 @@ typedef struct {
u32 Packed; u32 Packed;
} IpcStaticRecvDescriptor; } IpcStaticRecvDescriptor;
static inline void ipcAddSendBuffer(IpcCommand* cmd, void* buffer, size_t size, u8 flags) { static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t size, u8 flags) {
size_t off = cmd->NumSend; size_t off = cmd->NumSend;
cmd->Buffers[off] = buffer; cmd->Buffers[off] = buffer;
cmd->BufferSizes[off] = size; cmd->BufferSizes[off] = size;
@ -77,7 +77,7 @@ static inline void ipcAddTransferBuffer(IpcCommand* cmd, void* buffer, size_t si
cmd->NumTransfer++; cmd->NumTransfer++;
} }
static inline void ipcAddSendStatic(IpcCommand* cmd, void* buffer, size_t size, u8 index) { static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t size, u8 index) {
size_t off = cmd->NumStaticIn; size_t off = cmd->NumStaticIn;
cmd->Statics[off] = buffer; cmd->Statics[off] = buffer;
cmd->StaticSizes[off] = size; cmd->StaticSizes[off] = size;

View File

@ -0,0 +1,57 @@
// Copyright 2017 plutoo
// We use wrapped handles for type safety.
typedef struct {
Handle h;
} FsFileSystem;
typedef struct {
Handle h;
} FsFile;
typedef struct {
Handle h;
} FsDir;
typedef struct {
Handle h;
} FsStorage;
typedef enum {
ENTRYTYPE_FILE=0,
ENTRYTYPE_DIR =1
} FsEntryType;
#define FS_MAX_PATH 0x301
Result fsInitialize();
Result fsMountSdcard(FsFileSystem* out);
// todo: Rest of commands here
// IFileSystem
Result fsFsCreateFile(FsFileSystem* fs, const char* path, size_t size, int flags);
Result fsFsDeleteFile(FsFileSystem* fs, const char* path);
Result fsFsCreateDirectory(FsFileSystem* fs, const char* path);
Result fsFsDeleteDirectory(FsFileSystem* fs, const char* path);
Result fsFsDeleteDirectoryRecursively(FsFileSystem* fs, const char* path);
Result fsFsRenameFile(FsFileSystem* fs, const char* path0, const char* path1);
Result fsFsRenameDirectory(FsFileSystem* fs, const char* path0, const char* path1);
Result fsFsGetEntryType(FsFileSystem* fs, const char* path, FsEntryType* out);
Result fsFsOpenFile(FsFileSystem* fs, const char* path, int flags, FsFile* out);
Result fsFsOpenDirectory(FsFileSystem* fs, const char* path, int flags, FsDir* out);
Result fsFsCommit(FsFileSystem* fs);
Result fsFsGetFreeSpace(FsFileSystem* fs, u64* out);
Result fsFsGetTotalSpace(FsFileSystem* fs, u64* out);
void fsFsClose(FsFileSystem* fs);
// IFile
Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out);
Result fsFileWrite(FsFile* f, u64 off, void* buf, size_t len, size_t* out);
Result fsFileFlush(FsFile* f);
Result fsFileSetSize(FsFile* f, u64 sz);
Result fsFileGetSize(FsFile* f, u64* out);
void fsFileClose(FsFile* f);
// todo: IDirectory
// todo: IStorage

720
nx/source/services/fs.c Normal file
View File

@ -0,0 +1,720 @@
// Copyright 2017 plutoo
#include <switch.h>
static Handle g_fsHandle = -1;
Result fsInitialize() {
Result rc = smGetService(&g_fsHandle, "fsp-srv");
if (R_SUCCEEDED(rc)) {
if (R_SUCCEEDED(rc)) {
IpcCommand c;
ipcInitialize(&c);
ipcSendPid(&c);
struct {
u64 magic;
u64 cmd_id;
u64 unk;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
raw->unk = 0;
rc = ipcDispatch(g_fsHandle);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
}
}
return rc;
}
Result fsMountSdcard(FsFileSystem* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 18;
Result rc = ipcDispatch(g_fsHandle);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
out->h = r.Handles[0];
}
}
return rc;
}
// IFileSystem impl
Result fsFsCreateFile(FsFileSystem* fs, const char* path, size_t size, int flags) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
u64 zero;
u64 size;
u32 flags;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->zero = 0;
raw->size = size;
raw->flags = flags;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsFsDeleteFile(FsFileSystem* fs, const char* path) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsFsCreateDirectory(FsFileSystem* fs, const char* path) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 2;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsFsDeleteDirectory(FsFileSystem* fs, const char* path) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 3;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsFsDeleteDirectoryRecursively(FsFileSystem* fs, const char* path) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 4;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0);
ipcAddSendStatic(&c, path1, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 5;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsRenameDirectory(FsFileSystem* fs, const char* path0, const char* path1) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0);
ipcAddSendStatic(&c, path1, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 6;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsFsGetEntryType(FsFileSystem* fs, const char* path, FsEntryType* out) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 7;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
u32 type;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out = resp->type;
}
}
return rc;
}
Result fsFsOpenFile(FsFileSystem* fs, const char* path, int flags, FsFile* out) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
u32 flags;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 8;
raw->flags = flags;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
out->h = r.Handles[0];
}
}
return rc;
}
Result fsFsOpenDirectory(FsFileSystem* fs, const char* path, int flags, FsDir* out) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path, FS_MAX_PATH, 0);
struct {
u64 magic;
u64 cmd_id;
u32 flags;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 9;
raw->flags = flags;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
out->h = r.Handles[0];
}
}
return rc;
}
Result fsFsCommit(FsFileSystem* fs) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 10;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsFsGetFreeSpace(FsFileSystem* fs, u64* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 11;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
u64 space;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out = resp->space;
}
}
return rc;
}
Result fsFsGetTotalSpace(FsFileSystem* fs, u64* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 12;
Result rc = ipcDispatch(fs->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
u64 space;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out = resp->space;
}
}
return rc;
}
void fsFsClose(FsFileSystem* fs) {
svcCloseHandle(fs->h);
}
// IFile implementation
Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, buf, len, 1);
struct {
u64 magic;
u64 cmd_id;
u64 zero;
u64 offset;
u64 read_size;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->zero = 0;
raw->offset = off;
raw->read_size = len;
Result rc = ipcDispatch(f->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
u64 bytes_read;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out = resp->bytes_read;
}
}
return rc;
}
Result fsFileWrite(FsFile* f, u64 off, void* buf, size_t len, size_t* out) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, buf, len, 1);
struct {
u64 magic;
u64 cmd_id;
u64 zero;
u64 offset;
u64 write_size;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
raw->zero = 0;
raw->offset = off;
raw->write_size = len;
Result rc = ipcDispatch(f->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
u64 bytes_written;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out = resp->bytes_written;
}
}
return rc;
}
Result fsFileFlush(FsFile* f) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 2;
Result rc = ipcDispatch(f->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsFileSetSize(FsFile* f, u64 sz) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 size;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 3;
raw->size = sz;
Result rc = ipcDispatch(f->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result fsFileGetSize(FsFile* f, u64* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 4;
Result rc = ipcDispatch(f->h);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
u64 size;
} *resp = r.Raw;
rc = resp->size;
}
return rc;
}
void fsFileClose(FsFile* f) {
svcCloseHandle(f->h);
}