fs: fix file/storage API, add fsdevCreateFile, add fsOpenFileSystemWithPatch.

This commit is contained in:
Michael Scire 2019-06-01 18:17:12 -07:00 committed by yellows8
parent a3381d3d64
commit bae4d55dfc
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
5 changed files with 207 additions and 30 deletions

View File

@ -48,6 +48,9 @@ int fsdevTranslatePath(const char *path, FsFileSystem** device, char *outpath);
/// This calls fsFsSetArchiveBit on the filesystem specified by the input path (as used in stdio).
Result fsdevSetArchiveBit(const char *path);
/// This calls fsFsCreateFile on the filesystem specified by the input path (as used in stdio).
Result fsdevCreateFile(const char* path, size_t size, int flags);
/// Recursively deletes the directory specified by the input path (as used in stdio).
Result fsdevDeleteDirectoryRecursively(const char *path);

View File

@ -109,13 +109,30 @@ typedef enum
FS_OPEN_APPEND = BIT(2), ///< Append file.
} FsFileFlags;
typedef enum
{
FS_CREATE_BIG_FILE = BIT(0), ///< Creates a ConcatenationFile (dir with archive bit) instead of file.
} FsFileCreateFlags;
/// For use with fsFsOpenDirectory.
typedef enum
{
FS_DIROPEN_DIRECTORY = BIT(0), ///< Enable reading directory entries.
FS_DIROPEN_FILE = BIT(1), ///< Enable reading file entries.
FS_DIROPEN_DIRECTORY = BIT(0), ///< Enable reading directory entries.
FS_DIROPEN_FILE = BIT(1), ///< Enable reading file entries.
FS_DIROPEN_NO_FILE_SIZE = BIT(31), ///< Causes result entries to not contain filesize information (always 0).
} FsDirectoryFlags;
typedef enum
{
FS_READOPTION_NONE = 0, ///< No Option.
} FsReadOption;
typedef enum
{
FS_WRITEOPTION_NONE = 0, ///< No option.
FS_WRITEOPTION_FLUSH = BIT(0), ///< Forces a flush after write.
} FsWriteOption;
typedef enum
{
FsStorageId_None = 0,
@ -163,6 +180,19 @@ typedef struct {
u32 value;
} FsGameCardHandle;
typedef struct {
u32 aes_ctr_key_type; ///< Contains bitflags describing how data is AES encrypted
u32 speed_emulation_type; ///< Contains bitflags describing how data is emulated.
u32 reserved[0x38/sizeof(u32)];
} FsRangeInfo;
typedef enum {
FsOperationId_Clear, ///< Fill range with zero for supported file/storage.
FsOperationId_ClearSignature, ///< Clears signature for supported file/storage.
FsOperationId_InvalidateCache, ///< Invalidates cache for supported file/storage.
FsOperationId_QueryRange, ///< Retrieves information on data for supported file/storage.
} FsOperationId;
Result fsInitialize(void);
void fsExit(void);
@ -213,6 +243,7 @@ typedef enum
/// Mount requested filesystem type from content file
Result fsOpenFileSystem(FsFileSystem* out, FsFileSystemType fsType, const char* contentPath); /// same as calling fsOpenFileSystemWithId with 0 as titleId
Result fsOpenFileSystemWithId(FsFileSystem* out, u64 titleId, FsFileSystemType fsType, const char* contentPath); /// works on all firmwares, titleId is ignored on 1.0.0
Result fsOpenFileSystemWithPatch(FsFileSystem* out, u64 titleId, FsFileSystemType fsType); /// 2.0.0+, like OpenFileSystemWithId but without content path.
// IFileSystem
Result fsFsCreateFile(FsFileSystem* fs, const char* path, size_t size, int flags);
@ -220,8 +251,8 @@ 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 fsFsRenameFile(FsFileSystem* fs, const char* cur_path, const char* new_path);
Result fsFsRenameDirectory(FsFileSystem* fs, const char* cur_path, const char* new_path);
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);
@ -238,11 +269,12 @@ void fsFsClose(FsFileSystem* fs);
Result fsFsSetArchiveBit(FsFileSystem* fs, const char *path);
// IFile
Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out);
Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len);
Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, u32 option, size_t* out);
Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len, u32 option);
Result fsFileFlush(FsFile* f);
Result fsFileSetSize(FsFile* f, u64 sz);
Result fsFileGetSize(FsFile* f, u64* out);
Result fsFileOperateRange(FsFile* f, FsOperationId op_id, u64 off, size_t len, FsRangeInfo* out);
void fsFileClose(FsFile* f);
// IDirectory
@ -256,6 +288,7 @@ Result fsStorageWrite(FsStorage* s, u64 off, const void* buf, size_t len);
Result fsStorageFlush(FsStorage* s);
Result fsStorageSetSize(FsStorage* s, u64 sz);
Result fsStorageGetSize(FsStorage* s, u64* out);
Result fsStorageOperateRange(FsStorage* s, FsOperationId op_id, u64 off, size_t len, FsRangeInfo* out);
void fsStorageClose(FsStorage* s);
// ISaveDataInfoReader

View File

@ -381,6 +381,16 @@ Result fsdevSetArchiveBit(const char *path) {
return fsFsSetArchiveBit(&device->fs, fs_path);
}
Result fsdevCreateFile(const char* path, size_t size, int flags) {
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
if(fsdev_getfspath(_REENT, path, &device, fs_path)==-1)
return MAKERESULT(Module_Libnx, LibnxError_NotFound);
return fsFsCreateFile(&device->fs, fs_path, size, flags);
}
Result fsdevDeleteDirectoryRecursively(const char *path) {
char fs_path[FS_MAX_PATH];
fsdev_fsdevice *device = NULL;
@ -680,7 +690,7 @@ fsdev_write(struct _reent *r,
}
}
rc = fsFileWrite(&file->fd, file->offset, ptr, len);
rc = fsFileWrite(&file->fd, file->offset, ptr, len, FS_WRITEOPTION_NONE);
if(rc == 0xD401)
return fsdev_write_safe(r, fd, ptr, len);
if(R_FAILED(rc))
@ -734,7 +744,7 @@ fsdev_write_safe(struct _reent *r,
memcpy(tmp_buffer, ptr, toWrite);
/* write the data */
rc = fsFileWrite(&file->fd, file->offset, tmp_buffer, toWrite);
rc = fsFileWrite(&file->fd, file->offset, tmp_buffer, toWrite, FS_WRITEOPTION_NONE);
if(R_FAILED(rc))
{
@ -789,7 +799,7 @@ fsdev_read(struct _reent *r,
}
/* read the data */
rc = fsFileRead(&file->fd, file->offset, ptr, len, &bytes);
rc = fsFileRead(&file->fd, file->offset, ptr, len, FS_READOPTION_NONE, &bytes);
if(rc == 0xD401)
return fsdev_read_safe(r, fd, ptr, len);
if(R_SUCCEEDED(rc))
@ -836,7 +846,7 @@ fsdev_read_safe(struct _reent *r,
toRead = sizeof(tmp_buffer);
/* read the data */
rc = fsFileRead(&file->fd, file->offset, tmp_buffer, toRead, &bytes);
rc = fsFileRead(&file->fd, file->offset, tmp_buffer, toRead, FS_READOPTION_NONE, &bytes);
if(bytes > toRead)
bytes = toRead;

View File

@ -56,7 +56,7 @@ static ssize_t _romfs_read(romfs_mount *mount, u64 offset, void* buffer, u64 siz
Result rc = 0;
if(mount->fd_type == RomfsSource_FsFile)
{
rc = fsFileRead(&mount->fd, pos, buffer, size, &read);
rc = fsFileRead(&mount->fd, pos, buffer, size, FS_READOPTION_NONE, &read);
}
else if(mount->fd_type == RomfsSource_FsStorage)
{

View File

@ -19,7 +19,7 @@ Result fsInitialize(void)
return 0;
Result rc = smGetService(&g_fsSrv, "fsp-srv");
if (R_SUCCEEDED(rc)) {
rc = serviceConvertToDomain(&g_fsSrv);
}
@ -549,9 +549,9 @@ Result fsOpenFileSystemWithId(FsFileSystem* out, u64 titleId, FsFileSystemType f
u32 fsType;
u64 titleId;
} *raw;
raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 8;
raw->fsType = fsType;
@ -563,9 +563,9 @@ Result fsOpenFileSystemWithId(FsFileSystem* out, u64 titleId, FsFileSystemType f
u64 cmd_id;
u32 fsType;
} *raw;
raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->fsType = fsType;
@ -593,6 +593,50 @@ Result fsOpenFileSystemWithId(FsFileSystem* out, u64 titleId, FsFileSystemType f
return rc;
}
Result fsOpenFileSystemWithPatch(FsFileSystem* out, u64 titleId, FsFileSystemType fsType) {
if (hosversionBefore(2,0,0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 fsType;
u64 titleId;
} *raw;
raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 7;
raw->fsType = fsType;
raw->titleId = titleId;
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;
}
// IFileSystem impl
Result fsFsCreateFile(FsFileSystem* fs, const char* path, size_t size, int flags) {
IpcCommand c;
@ -602,7 +646,6 @@ Result fsFsCreateFile(FsFileSystem* fs, const char* path, size_t size, int flags
struct {
u64 magic;
u64 cmd_id;
u64 zero;
u32 flags;
u64 size;
} *raw;
@ -611,7 +654,6 @@ Result fsFsCreateFile(FsFileSystem* fs, const char* path, size_t size, int flags
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->zero = 0;
raw->flags = flags;
raw->size = size;
@ -765,11 +807,11 @@ Result fsFsDeleteDirectoryRecursively(FsFileSystem* fs, const char* path) {
return rc;
}
Result fsFsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) {
Result fsFsRenameFile(FsFileSystem* fs, const char* cur_path, const char* new_path) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0);
ipcAddSendStatic(&c, path1, FS_MAX_PATH, 1);
ipcAddSendStatic(&c, cur_path, FS_MAX_PATH, 0);
ipcAddSendStatic(&c, new_path, FS_MAX_PATH, 1);
struct {
u64 magic;
@ -799,11 +841,11 @@ Result fsFsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) {
return rc;
}
Result fsFsRenameDirectory(FsFileSystem* fs, const char* path0, const char* path1) {
Result fsFsRenameDirectory(FsFileSystem* fs, const char* cur_path, const char* new_path) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0);
ipcAddSendStatic(&c, path1, FS_MAX_PATH, 1);
ipcAddSendStatic(&c, cur_path, FS_MAX_PATH, 0);
ipcAddSendStatic(&c, new_path, FS_MAX_PATH, 1);
struct {
u64 magic;
@ -1187,7 +1229,7 @@ void fsFsClose(FsFileSystem* fs) {
}
// IFile implementation
Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out) {
Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, u32 option, size_t* out) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, buf, len, 1);
@ -1195,7 +1237,7 @@ Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out) {
struct {
u64 magic;
u64 cmd_id;
u64 zero;
u32 option;
u64 offset;
u64 read_size;
} *raw;
@ -1204,7 +1246,7 @@ Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out) {
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->zero = 0;
raw->option = option;
raw->offset = off;
raw->read_size = len;
@ -1231,7 +1273,7 @@ Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out) {
return rc;
}
Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len) {
Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len, u32 option) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, buf, len, 1);
@ -1239,7 +1281,7 @@ Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len) {
struct {
u64 magic;
u64 cmd_id;
u64 zero;
u32 option;
u64 offset;
u64 write_size;
} *raw;
@ -1248,7 +1290,7 @@ Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len) {
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
raw->zero = 0;
raw->option = option;
raw->offset = off;
raw->write_size = len;
@ -1370,6 +1412,51 @@ Result fsFileGetSize(FsFile* f, u64* out) {
return rc;
}
Result fsFileOperateRange(FsFile* f, FsOperationId op_id, u64 off, size_t len, FsRangeInfo* out) {
if (hosversionBefore(4,0,0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 op_id;
u64 off;
u64 len;
} *raw;
raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 5;
raw->op_id = op_id;
raw->off = off;
raw->len = len;
Result rc = serviceIpcDispatch(&f->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
FsRangeInfo range_info;
} *resp;
serviceIpcParse(&f->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->range_info;
}
return rc;
}
void fsFileClose(FsFile* f) {
serviceClose(&f->s);
}
@ -1628,6 +1715,50 @@ Result fsStorageGetSize(FsStorage* s, u64* out) {
return rc;
}
Result fsStorageOperateRange(FsStorage* s, FsOperationId op_id, u64 off, size_t len, FsRangeInfo* out) {
if (hosversionBefore(4,0,0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 op_id;
u64 off;
u64 len;
} *raw;
raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 5;
raw->op_id = op_id;
raw->off = off;
raw->len = len;
Result rc = serviceIpcDispatch(&s->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
FsRangeInfo range_info;
} *resp;
serviceIpcParse(&s->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->range_info;
}
return rc;
}
void fsStorageClose(FsStorage* s) {
serviceClose(&s->s);
}