mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-04 18:42:15 +02:00
fs: fix file/storage API, add fsdevCreateFile, add fsOpenFileSystemWithPatch.
This commit is contained in:
parent
a3381d3d64
commit
bae4d55dfc
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user