diff --git a/wupserver/source/fsa.c b/wupserver/source/fsa.c index 40f0d7d..e9bb52c 100644 --- a/wupserver/source/fsa.c +++ b/wupserver/source/fsa.c @@ -19,6 +19,48 @@ static void freeIobuf(void* ptr) svcFree(0xCAFF, ptr); } +int _ioctl_fd_handle(int fd, int handle, int ioctl_num, u32* out_data, u32 out_data_size) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = handle; + + int ret = svcIoctl(fd, ioctl_num, inbuf, 0x520, outbuf, 0x293); + + if(out_data && out_data_size) memcpy(out_data, &outbuf[1], out_data_size); + + freeIobuf(iobuf); + return ret; +} + +int _ioctl_fd_path_args(int fd, char* path, int ioctl_num, int args, u32 arg1, u32 arg2, u32 arg3, u32* out_data, u32 out_data_size) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + switch (args) { + case 3: inbuf[0x28C / 4] = arg3; + case 2: inbuf[0x288 / 4] = arg2; + case 1: inbuf[0x284 / 4] = arg1; + } + + int ret = svcIoctl(fd, ioctl_num, inbuf, 0x520, outbuf, 0x293); + + if(out_data && out_data_size) memcpy(out_data, &outbuf[1], out_data_size); + + freeIobuf(iobuf); + return ret; +} + +int _ioctl_fd_path(int fd, char* path, int ioctl_num, u32* out_data, u32 out_data_size) +{ + return _ioctl_fd_path_args(fd, path, ioctl_num, 0, 0, 0, 0, out_data, out_data_size); +} + int FSA_Mount(int fd, char* device_path, char* volume_path, u32 flags, char* arg_string, int arg_string_len) { u8* iobuf = allocIobuf(); @@ -48,123 +90,106 @@ int FSA_Mount(int fd, char* device_path, char* volume_path, u32 flags, char* arg int FSA_Unmount(int fd, char* path, u32 flags) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - strncpy((char*)&inbuf[0x01], path, 0x27F); - inbuf[0x284 / 4] = flags; - - int ret = svcIoctl(fd, 0x02, inbuf, 0x520, outbuf, 0x293); - - freeIobuf(iobuf); - return ret; + return _ioctl_fd_path_args(fd, path, 0x02, 1, flags, 0, 0, NULL, 0); } int FSA_FlushVolume(int fd, char* volume_path) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - strncpy((char*)&inbuf[0x01], volume_path, 0x27F); - - int ret = svcIoctl(fd, 0x1B, inbuf, 0x520, outbuf, 0x293); + return _ioctl_fd_path(fd, volume_path, 0x1B, NULL, 0); +} - freeIobuf(iobuf); - return ret; +int FSA_RollbackVolume(int fd, char* volume_path) +{ + return _ioctl_fd_path(fd, volume_path, 0x1C, NULL, 0); } int FSA_MakeDir(int fd, char* path, u32 flags) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - strncpy((char*)&inbuf[0x01], path, 0x27F); - inbuf[0x284 / 4] = flags; - - int ret = svcIoctl(fd, 0x07, inbuf, 0x520, outbuf, 0x293); - - freeIobuf(iobuf); - return ret; + return _ioctl_fd_path_args(fd, path, 0x07, 1, flags, 0, 0, NULL, 0); } int FSA_OpenDir(int fd, char* path, int* outHandle) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - strncpy((char*)&inbuf[0x01], path, 0x27F); - - int ret = svcIoctl(fd, 0x0A, inbuf, 0x520, outbuf, 0x293); - - if(outHandle) *outHandle = outbuf[1]; - - freeIobuf(iobuf); - return ret; + return _ioctl_fd_path(fd, path, 0x0A, (u32*)outHandle, sizeof(int)); } int FSA_ReadDir(int fd, int handle, directoryEntry_s* out_data) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - inbuf[1] = handle; + return _ioctl_fd_handle(fd, handle, 0x0B, (u32*)out_data, sizeof(directoryEntry_s)); +} - int ret = svcIoctl(fd, 0x0B, inbuf, 0x520, outbuf, 0x293); +int FSA_RewindDir(int fd, int handle) +{ + return _ioctl_fd_handle(fd, handle, 0x0C, NULL, 0); +} - if(out_data) memcpy(out_data, &outbuf[1], sizeof(directoryEntry_s)); +int FSA_CloseDir(int fd, int handle) +{ + return _ioctl_fd_handle(fd, handle, 0x0D, NULL, 0); +} - freeIobuf(iobuf); - return ret; +int FSA_ChangeDir(int fd, char* path) +{ + return _ioctl_fd_path(fd, path, 0x05, NULL, 0); } -int FSA_RewindDir(int fd, int handle) +int FSA_GetCwd(int fd, char* out_data, int output_size) { u8* iobuf = allocIobuf(); u32* inbuf = (u32*)iobuf; u32* outbuf = (u32*)&iobuf[0x520]; - inbuf[1] = handle; + int ret = svcIoctl(fd, 0x06, inbuf, 0x520, outbuf, 0x293); - int ret = svcIoctl(fd, 0x0C, inbuf, 0x520, outbuf, 0x293); + if (output_size > 0x27F) output_size = 0x27F; + if(out_data) strncpy(out_data, (char*)&outbuf[1], output_size); freeIobuf(iobuf); return ret; } -int FSA_CloseDir(int fd, int handle) +int FSA_MakeQuota(int fd, char* path, u32 flags, u64 size) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - inbuf[1] = handle; + return _ioctl_fd_path_args(fd, path, 0x07, 3, flags, (size >> 32), (size & 0xFFFFFFFF), NULL, 0); +} - int ret = svcIoctl(fd, 0x0D, inbuf, 0x520, outbuf, 0x293); +int FSA_FlushQuota(int fd, char* quota_path) +{ + return _ioctl_fd_path(fd, quota_path, 0x1E, NULL, 0); +} - freeIobuf(iobuf); - return ret; +static int _FSA_RollbackQuota(int fd, char* quota_path, int flag) +{ + return _ioctl_fd_path_args(fd, quota_path, 0x1F, 1, flag, 0, 0, NULL, 0); } -int FSA_ChangeDir(int fd, char* path) +int FSA_RollbackQuota(int fd, char* quota_path) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; + return _FSA_RollbackQuota(fd, quota_path, 0); +} - strncpy((char*)&inbuf[0x01], path, 0x27F); +int FSA_RollbackQuotaForce(int fd, char* quota_path) +{ + return _FSA_RollbackQuota(fd, quota_path, 0x80000000); +} - int ret = svcIoctl(fd, 0x05, inbuf, 0x520, outbuf, 0x293); +int FSA_RegisterFlushQuota(int fd, char* quota_path) +{ + return _ioctl_fd_path(fd, quota_path, 0x22, NULL, 0); +} - freeIobuf(iobuf); - return ret; +int FSA_FlushMultiQuota(int fd, char* quota_path) +{ + return _ioctl_fd_path(fd, quota_path, 0x23, NULL, 0); } -int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle) +//int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle) +//{ +// return FSA_OpenFileEx(fd, path, mode, outHandle, 0, 0x600, 0); +//} + +// flags - 1 - maybe open/create unencrypted file?, 2 - preallocated size +int FSA_OpenFileEx(int fd, char* path, char* mode, int* outHandle, u32 flags, int create_mode, u32 create_alloc_size) { u8* iobuf = allocIobuf(); u32* inbuf = (u32*)iobuf; @@ -172,6 +197,9 @@ int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle) strncpy((char*)&inbuf[0x01], path, 0x27F); strncpy((char*)&inbuf[0xA1], mode, 0x10); + inbuf[0xA5] = flags; + inbuf[0xA6] = create_mode; + inbuf[0xA7] = create_alloc_size; int ret = svcIoctl(fd, 0x0E, inbuf, 0x520, outbuf, 0x293); @@ -181,7 +209,7 @@ int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle) return ret; } -int _FSA_ReadWriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags, bool read) +int _FSA_ReadWriteFileWithPos(int fd, void* data, u32 size, u32 cnt, int pos, int fileHandle, u32 flags, bool read) { u8* iobuf = allocIobuf(); u8* inbuf8 = iobuf; @@ -192,6 +220,7 @@ int _FSA_ReadWriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u3 inbuf[0x08 / 4] = size; inbuf[0x0C / 4] = cnt; + inbuf[0x10 / 4] = pos; inbuf[0x14 / 4] = fileHandle; inbuf[0x18 / 4] = flags; @@ -212,44 +241,71 @@ int _FSA_ReadWriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u3 return ret; } -int FSA_ReadFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags) +//int FSA_ReadFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags) +//{ +// return _FSA_ReadWriteFileWithPos(fd, data, size, cnt, 0, fileHandle, flags & (~1), true); +//} + +//int FSA_WriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags) +//{ +// return _FSA_ReadWriteFileWithPos(fd, data, size, cnt, 0, fileHandle, flags & (~1), false); +//} + +int FSA_ReadFileWithPos(int fd, void* data, u32 size, u32 cnt, u32 position, int fileHandle, u32 flags) { - return _FSA_ReadWriteFile(fd, data, size, cnt, fileHandle, flags, true); + return _FSA_ReadWriteFileWithPos(fd, data, size, cnt, position, fileHandle, flags, true); } -int FSA_WriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags) +int FSA_WriteFileWithPos(int fd, void* data, u32 size, u32 cnt, u32 position, int fileHandle, u32 flags) { - return _FSA_ReadWriteFile(fd, data, size, cnt, fileHandle, flags, false); + return _FSA_ReadWriteFileWithPos(fd, data, size, cnt, position, fileHandle, flags, false); } -int FSA_StatFile(int fd, int handle, fileStat_s* out_data) +//int FSA_AppendFile(int fd, u32 size, u32 cnt, int fileHandle) { +// return FSA_AppendFileEx(fd, size, cnt, 0); +//} + +// flags - 1 - affects the way the blocks are allocated - maybe will cause it to allocate it at the end of the quota? +int FSA_AppendFileEx(int fd, u32 size, u32 cnt, int fileHandle, u32 flags) { u8* iobuf = allocIobuf(); u32* inbuf = (u32*)iobuf; u32* outbuf = (u32*)&iobuf[0x520]; - inbuf[1] = handle; + inbuf[1] = size; + inbuf[2] = cnt; + inbuf[3] = fileHandle; + inbuf[4] = flags; - int ret = svcIoctl(fd, 0x14, inbuf, 0x520, outbuf, 0x293); - - if(out_data) memcpy(out_data, &outbuf[1], sizeof(fileStat_s)); + int ret = svcIoctl(fd, 0x19, inbuf, 0x520, outbuf, 0x293); freeIobuf(iobuf); return ret; } +int FSA_GetStatFile(int fd, int handle, FSStat* out_data) +{ + return _ioctl_fd_handle(fd, handle, 0x14, (u32*)out_data, sizeof(FSStat)); +} + int FSA_CloseFile(int fd, int fileHandle) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; + return _ioctl_fd_handle(fd, fileHandle, 0x15, NULL, 0); +} - inbuf[1] = fileHandle; +int FSA_FlushFile(int fd, int fileHandle) +{ + return _ioctl_fd_handle(fd, fileHandle, 0x17, NULL, 0); +} - int ret = svcIoctl(fd, 0x15, inbuf, 0x520, outbuf, 0x293); +int FSA_TruncateFile(int fd, int fileHandle) +{ + return _ioctl_fd_handle(fd, fileHandle, 0x1A, NULL, 0); +} - freeIobuf(iobuf); - return ret; +int FSA_GetPosFile(int fd, int fileHandle, u32* out_position) +{ + return _ioctl_fd_handle(fd, fileHandle, 0x11, out_position, sizeof(u32)); } int FSA_SetPosFile(int fd, int fileHandle, u32 position) @@ -267,57 +323,72 @@ int FSA_SetPosFile(int fd, int fileHandle, u32 position) return ret; } -int FSA_GetStat(int fd, char *path, fileStat_s* out_data) +int FSA_IsEof(int fd, int fileHandle) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - strncpy((char*)&inbuf[0x01], path, 0x27F); - inbuf[0x284/4] = 5; - - int ret = svcIoctl(fd, 0x18, inbuf, 0x520, outbuf, 0x293); - - if(out_data) memcpy(out_data, &outbuf[1], sizeof(fileStat_s)); + return _ioctl_fd_handle(fd, fileHandle, 0x13, NULL, 0); +} - freeIobuf(iobuf); - return ret; +int FSA_GetStat(int fd, char *path, FSStat* out_data) +{ + return FSA_GetInfo(fd, path, 5, (u32*)out_data); } int FSA_Remove(int fd, char *path) +{ + return _ioctl_fd_path(fd, path, 0x08, NULL, 0); +} + +int FSA_Rename(int fd, char *old_path, char *new_path) { u8* iobuf = allocIobuf(); u32* inbuf = (u32*)iobuf; u32* outbuf = (u32*)&iobuf[0x520]; - strncpy((char*)&inbuf[0x01], path, 0x27F); + strncpy((char*)&inbuf[0x01], old_path, 0x27F); + strncpy((char*)&inbuf[0x01 + (0x280/4)], new_path, 0x27F); - int ret = svcIoctl(fd, 0x08, inbuf, 0x520, outbuf, 0x293); + int ret = svcIoctl(fd, 0x09, inbuf, 0x520, outbuf, 0x293); freeIobuf(iobuf); return ret; } -int FSA_ChangeMode(int fd, char *path, int mode) +int FSA_ChangeMode(int fd, char *path, int mode, int mask) +{ + return _ioctl_fd_path_args(fd, path, 0x20, 2, mode, mask, 0, NULL, 0); // 0x777 - mask +} + +int FSA_ChangeOwner(int fd, char *path, u32 owner, u32 group) { u8* iobuf = allocIobuf(); u32* inbuf = (u32*)iobuf; u32* outbuf = (u32*)&iobuf[0x520]; strncpy((char*)&inbuf[0x01], path, 0x27F); - inbuf[0x284/4] = mode; - inbuf[0x288/4] = 0x777; // mask + inbuf[0x284/4] = 0; // ignored + inbuf[0x288/4] = owner; + inbuf[0x28C/4] = 0; // ignored + inbuf[0x290/4] = group; - int ret = svcIoctl(fd, 0x20, inbuf, 0x520, outbuf, 0x293); + int ret = svcIoctl(fd, 0x70, inbuf, 0x520, outbuf, 0x293); freeIobuf(iobuf); return ret; } +// 0 - FSA_GetFreeSpaceSize +// 1 - FSA_GetDirSize +// 2 - FSA_GetEntryNum +// 3 - FSA_GetFileSystemInfo +// 4 - FSA_GetDeviceInfo +// 5 - FSA_GetStat +// 6 - FSA_GetBadBlockInfo +// 7 - FSA_GetJournalFreeSpaceS +// 8 - FSA_GetFragmentBlockInfo // type 4 : // 0x08 : device size in sectors (u64) // 0x10 : device sector size (u32) -int FSA_GetDeviceInfo(int fd, char* device_path, int type, u32* out_data) +int FSA_GetInfo(int fd, char* device_path, int type, u32* out_data) { u8* iobuf = allocIobuf(); u32* inbuf = (u32*)iobuf; @@ -333,22 +404,22 @@ int FSA_GetDeviceInfo(int fd, char* device_path, int type, u32* out_data) switch(type) { case 0: case 1: case 7: - size = 0x8; + size = sizeof(u64); break; case 2: - size = 0x4; + size = sizeof(u32); break; case 3: - size = 0x1E; + size = sizeof(FileSystemInfo); break; case 4: - size = 0x28; + size = sizeof(DeviceInfo); break; case 5: - size = 0x64; + size = sizeof(FSStat); break; case 6: case 8: - size = 0x14; + size = sizeof(BlockInfo); break; } @@ -360,36 +431,15 @@ int FSA_GetDeviceInfo(int fd, char* device_path, int type, u32* out_data) int FSA_RawOpen(int fd, char* device_path, int* outHandle) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - strncpy((char*)&inbuf[0x01], device_path, 0x27F); - - int ret = svcIoctl(fd, 0x6A, inbuf, 0x520, outbuf, 0x293); - - if(outHandle) *outHandle = outbuf[1]; - - freeIobuf(iobuf); - return ret; + return _ioctl_fd_path(fd, device_path, 0x6A, (u32*)outHandle, sizeof(int)); } int FSA_RawClose(int fd, int device_handle) { - u8* iobuf = allocIobuf(); - u32* inbuf = (u32*)iobuf; - u32* outbuf = (u32*)&iobuf[0x520]; - - inbuf[1] = device_handle; - - int ret = svcIoctl(fd, 0x6D, inbuf, 0x520, outbuf, 0x293); - - freeIobuf(iobuf); - return ret; + return _ioctl_fd_handle(fd, device_handle, 0x6D, NULL, 0); } -// offset in blocks of 0x1000 bytes -int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) +int _FSA_RawReadWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle, bool read) { u8* iobuf = allocIobuf(); u8* inbuf8 = iobuf; @@ -398,7 +448,6 @@ int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, u32* inbuf = (u32*)inbuf8; u32* outbuf = (u32*)outbuf8; - // note : offset_bytes = blocks_offset * size_bytes inbuf[0x08 / 4] = (blocks_offset >> 32); inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF); inbuf[0x10 / 4] = cnt; @@ -414,38 +463,21 @@ int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, iovec[2].ptr = outbuf; iovec[2].len = 0x293; - int ret = svcIoctlv(fd, 0x6B, 1, 2, iovec); + int ret; + if(read) ret = svcIoctlv(fd, 0x6B, 1, 2, iovec); + else ret = svcIoctlv(fd, 0x6C, 2, 1, iovec); freeIobuf(iobuf); return ret; } -int FSA_RawWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) +// offset in blocks of 0x1000 bytes +int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) { - u8* iobuf = allocIobuf(); - u8* inbuf8 = iobuf; - u8* outbuf8 = &iobuf[0x520]; - iovec_s* iovec = (iovec_s*)&iobuf[0x7C0]; - u32* inbuf = (u32*)inbuf8; - u32* outbuf = (u32*)outbuf8; - - inbuf[0x08 / 4] = (blocks_offset >> 32); - inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF); - inbuf[0x10 / 4] = cnt; - inbuf[0x14 / 4] = size_bytes; - inbuf[0x18 / 4] = device_handle; - - iovec[0].ptr = inbuf; - iovec[0].len = 0x520; - - iovec[1].ptr = data; - iovec[1].len = size_bytes * cnt; - - iovec[2].ptr = outbuf; - iovec[2].len = 0x293; - - int ret = svcIoctlv(fd, 0x6C, 2, 1, iovec); + return _FSA_RawReadWrite(fd, data, size_bytes, cnt, blocks_offset, device_handle, true); +} - freeIobuf(iobuf); - return ret; +int FSA_RawWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) +{ + return _FSA_RawReadWrite(fd, data, size_bytes, cnt, blocks_offset, device_handle, false); } diff --git a/wupserver/source/fsa.h b/wupserver/source/fsa.h index 88366bf..8b1d01f 100644 --- a/wupserver/source/fsa.h +++ b/wupserver/source/fsa.h @@ -1,39 +1,71 @@ #ifndef FSA_H #define FSA_H +#define IOS_ERROR_UNKNOWN_VALUE 0xFFFFFFD6 +#define IOS_ERROR_INVALID_ARG 0xFFFFFFE3 +#define IOS_ERROR_INVALID_SIZE 0xFFFFFFE9 +#define IOS_ERROR_UNKNOWN 0xFFFFFFF7 +#define IOS_ERROR_NOEXISTS 0xFFFFFFFA + +#define FLAG_IS_LINK 0x00010000 +#define FLAG_IS_UNENCRYPTED 0x00800000 +#define FLAG_IS_FILE 0x01000000 +#define FLAG_IS_QUOTA 0x60000000 +#define FLAG_IS_DIRECTORY 0x80000000 + typedef struct { u32 flag; u32 permission; u32 owner_id; u32 group_id; - u32 size; // size in bytes - u32 physsize; // physical size on disk in bytes - u32 unk[3]; - u32 id; - u32 ctime; - u32 mtime; - u32 unk2[0x0D]; -}fileStat_s; + u32 size; // size in bytes + u32 physsize; // physical size on disk in bytes + u64 quota_size; + u32 id; + u64 ctime; + u64 mtime; + u8 attributes[48]; +} FSStat; typedef struct { - fileStat_s stat; + FSStat stat; char name[0x100]; -}directoryEntry_s; +} directoryEntry_s; + +typedef struct +{ + u8 unknown[0x1E]; +} FileSystemInfo; + +typedef struct +{ + u8 unknown[0x28]; +} DeviceInfo; -#define DIR_ENTRY_IS_DIRECTORY 0x80000000 +typedef struct +{ + u64 blocks_count; + u64 some_count; + u32 block_size; +} BlockInfo; #define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0) #define FSA_MOUNTFLAGS_GLOBAL (1 << 1) +#define FSA_OPENFLAGS_OPEN_UNENCRYPTED (1 << 0) +#define FSA_OPENFLAGS_PREALLOC_SPACE (1 << 1) + int FSA_Open(); int FSA_Mount(int fd, char* device_path, char* volume_path, u32 flags, char* arg_string, int arg_string_len); int FSA_Unmount(int fd, char* path, u32 flags); int FSA_FlushVolume(int fd, char* volume_path); +int FSA_RollbackVolume(int fd, char* volume_path); -int FSA_GetDeviceInfo(int fd, char* device_path, int type, u32* out_data); +int FSA_GetInfo(int fd, char* device_path, int type, u32* out_data); +int FSA_GetStat(int fd, char *path, FSStat* out_data); int FSA_MakeDir(int fd, char* path, u32 flags); int FSA_OpenDir(int fd, char* path, int* outHandle); @@ -41,16 +73,32 @@ int FSA_ReadDir(int fd, int handle, directoryEntry_s* out_data); int FSA_RewindDir(int fd, int handle); int FSA_CloseDir(int fd, int handle); int FSA_ChangeDir(int fd, char* path); +int FSA_GetCwd(int fd, char* out_data, int output_size); + +int FSA_MakeQuota(int fd, char* path, u32 flags, u64 size); +int FSA_FlushQuota(int fd, char* quota_path); +int FSA_RollbackQuota(int fd, char* quota_path); +int FSA_RollbackQuotaForce(int fd, char* quota_path); -int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle); -int FSA_ReadFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags); -int FSA_WriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags); -int FSA_StatFile(int fd, int handle, fileStat_s* out_data); +//int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle); +int FSA_OpenFileEx(int fd, char* path, char* mode, int* outHandle, u32 flags, int create_mode, u32 create_alloc_size); +//int FSA_ReadFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags); +//int FSA_WriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags); +int FSA_ReadFileWithPos(int fd, void* data, u32 size, u32 cnt, u32 position, int fileHandle, u32 flags); +int FSA_WriteFileWithPos(int fd, void* data, u32 size, u32 cnt, u32 position, int fileHandle, u32 flags); +//int FSA_AppendFile(int fd, u32 size, u32 cnt, int fileHandle); +int FSA_AppendFileEx(int fd, u32 size, u32 cnt, int fileHandle, u32 flags); +int FSA_GetStatFile(int fd, int handle, FSStat* out_data); int FSA_CloseFile(int fd, int fileHandle); +int FSA_FlushFile(int fd, int handle); +int FSA_TruncateFile(int fd, int handle); +int FSA_GetPosFile(int fd, int fileHandle, u32* out_position); int FSA_SetPosFile(int fd, int fileHandle, u32 position); -int FSA_GetStat(int fd, char *path, fileStat_s* out_data); +int FSA_IsEof(int fd, int fileHandle); int FSA_Remove(int fd, char *path); -int FSA_ChangeMode(int fd, char *path, int mode); +int FSA_Rename(int fd, char *old_path, char *new_path); +int FSA_ChangeMode(int fd, char *path, int mode, int mask); +int FSA_ChangeOwner(int fd, char *path, u32 owner, u32 group); int FSA_RawOpen(int fd, char* device_path, int* outHandle); int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 sector_offset, int device_handle); diff --git a/wupserver/source/ipc.c b/wupserver/source/ipc.c index cc70a3f..f4e1ac3 100644 --- a/wupserver/source/ipc.c +++ b/wupserver/source/ipc.c @@ -50,7 +50,7 @@ #define IOCTL_FSA_CLOSE 0x41 #define IOCTL_FSA_MOUNT 0x42 #define IOCTL_FSA_UNMOUNT 0x43 -#define IOCTL_FSA_GETDEVICEINFO 0x44 +#define IOCTL_FSA_GETINFO 0x44 #define IOCTL_FSA_OPENDIR 0x45 #define IOCTL_FSA_READDIR 0x46 #define IOCTL_FSA_CLOSEDIR 0x47 @@ -58,7 +58,7 @@ #define IOCTL_FSA_OPENFILE 0x49 #define IOCTL_FSA_READFILE 0x4A #define IOCTL_FSA_WRITEFILE 0x4B -#define IOCTL_FSA_STATFILE 0x4C +#define IOCTL_FSA_GETSTATFILE 0x4C #define IOCTL_FSA_CLOSEFILE 0x4D #define IOCTL_FSA_SETFILEPOS 0x4E #define IOCTL_FSA_GETSTAT 0x4F @@ -73,6 +73,23 @@ #define IOCTL_FSA_CHANGEMODE 0x58 #define IOCTL_FSA_FLUSHVOLUME 0x59 #define IOCTL_CHECK_IF_IOSUHAX 0x5B +#define IOCTL_FSA_CHANGEOWNER 0x5C +#define IOCTL_FSA_OPENFILEEX 0x5D +#define IOCTL_FSA_READFILEWITHPOS 0x5E +#define IOCTL_FSA_WRITEFILEWITHPOS 0x5F +#define IOCTL_FSA_APPENDFILE 0x60 +#define IOCTL_FSA_APPENDFILEEX 0x61 +#define IOCTL_FSA_FLUSHFILE 0x62 +#define IOCTL_FSA_TRUNCATEFILE 0x63 +#define IOCTL_FSA_GETPOSFILE 0x64 +#define IOCTL_FSA_ISEOF 0x65 +#define IOCTL_FSA_ROLLBACKVOLUME 0x66 +#define IOCTL_FSA_GETCWD 0x67 +#define IOCTL_FSA_MAKEQUOTA 0x68 +#define IOCTL_FSA_FLUSHQUOTA 0x69 +#define IOCTL_FSA_ROLLBACKQUOTA 0x6A +#define IOCTL_FSA_ROLLBACKQUOTAFORCE 0x6B +#define IOCTL_FSA_CHANGEMODEEX 0x6C //static u8 threadStack[0x1000] __attribute__((aligned(0x20))); @@ -232,20 +249,45 @@ static int ipc_ioctl(ipcmessage *message) break; } case IOCTL_FSA_FLUSHVOLUME: + case IOCTL_FSA_REMOVE: + case IOCTL_FSA_CHDIR: + case IOCTL_FSA_ROLLBACKVOLUME: + case IOCTL_FSA_FLUSHQUOTA: + case IOCTL_FSA_ROLLBACKQUOTA: + case IOCTL_FSA_ROLLBACKQUOTAFORCE: { int fd = message->ioctl.buffer_in[0]; char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + int (* func)(int, char*); // do not initialize + + switch(message->ioctl.command) { + case IOCTL_FSA_FLUSHVOLUME: func = FSA_FlushVolume; break; + case IOCTL_FSA_REMOVE: func = FSA_Remove; break; + case IOCTL_FSA_CHDIR: func = FSA_ChangeDir; break; + case IOCTL_FSA_ROLLBACKVOLUME: func = FSA_RollbackVolume; break; + case IOCTL_FSA_FLUSHQUOTA: func = FSA_FlushQuota; break; + case IOCTL_FSA_ROLLBACKQUOTA: func = FSA_RollbackQuota; break; + case IOCTL_FSA_ROLLBACKQUOTAFORCE: func = FSA_RollbackQuotaForce; break; + } + message->ioctl.buffer_io[0] = func(fd, path); + break; + } + case IOCTL_FSA_RENAME: + { + int fd = message->ioctl.buffer_in[0]; + char *old_path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + char *new_path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[2]; - message->ioctl.buffer_io[0] = FSA_FlushVolume(fd, path); + message->ioctl.buffer_io[0] = FSA_Rename(fd, old_path, new_path); break; } - case IOCTL_FSA_GETDEVICEINFO: + case IOCTL_FSA_GETINFO: { int fd = message->ioctl.buffer_in[0]; char *device_path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; int type = message->ioctl.buffer_in[2]; - message->ioctl.buffer_io[0] = FSA_GetDeviceInfo(fd, device_path, type, message->ioctl.buffer_io + 1); + message->ioctl.buffer_io[0] = FSA_GetInfo(fd, device_path, type, message->ioctl.buffer_io + 1); break; } case IOCTL_FSA_OPENDIR: @@ -256,76 +298,144 @@ static int ipc_ioctl(ipcmessage *message) message->ioctl.buffer_io[0] = FSA_OpenDir(fd, path, (int*)message->ioctl.buffer_io + 1); break; } - case IOCTL_FSA_READDIR: + case IOCTL_FSA_MAKEDIR: { int fd = message->ioctl.buffer_in[0]; - int handle = message->ioctl.buffer_in[1]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + u32 flags = message->ioctl.buffer_in[2]; - message->ioctl.buffer_io[0] = FSA_ReadDir(fd, handle, (directoryEntry_s*)(message->ioctl.buffer_io + 1)); + message->ioctl.buffer_io[0] = FSA_MakeDir(fd, path, flags); break; } - case IOCTL_FSA_CLOSEDIR: + case IOCTL_FSA_GETCWD: { int fd = message->ioctl.buffer_in[0]; - int handle = message->ioctl.buffer_in[1]; + int output_size = message->ioctl.buffer_in[1]; - message->ioctl.buffer_io[0] = FSA_CloseDir(fd, handle); + message->ioctl.buffer_io[0] = FSA_GetCwd(fd, (char*)(message->ioctl.buffer_io + 1), output_size); break; } - case IOCTL_FSA_MAKEDIR: + case IOCTL_FSA_MAKEQUOTA: { int fd = message->ioctl.buffer_in[0]; char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; u32 flags = message->ioctl.buffer_in[2]; + u64 size = ((u64)message->ioctl.buffer_in[3] << 32ULL) | message->ioctl.buffer_in[4]; - message->ioctl.buffer_io[0] = FSA_MakeDir(fd, path, flags); + message->ioctl.buffer_io[0] = FSA_MakeQuota(fd, path, flags, size); break; } case IOCTL_FSA_OPENFILE: + case IOCTL_FSA_OPENFILEEX: { int fd = message->ioctl.buffer_in[0]; char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; char *mode = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[2]; + u32 flags = 0x600; + int create_mode = 0; + u32 create_alloc_size = 0; + if (message->ioctl.command == IOCTL_FSA_OPENFILEEX) { + flags = message->ioctl.buffer_in[3]; + create_mode = message->ioctl.buffer_in[4]; + create_alloc_size = message->ioctl.buffer_in[5]; + } - message->ioctl.buffer_io[0] = FSA_OpenFile(fd, path, mode, (int*)message->ioctl.buffer_io + 1); + message->ioctl.buffer_io[0] = FSA_OpenFileEx(fd, path, mode, (int*)message->ioctl.buffer_io + 1, flags, create_mode, create_alloc_size); break; } case IOCTL_FSA_READFILE: + case IOCTL_FSA_READFILEWITHPOS: + case IOCTL_FSA_WRITEFILE: + case IOCTL_FSA_WRITEFILEWITHPOS: { int fd = message->ioctl.buffer_in[0]; u32 size = message->ioctl.buffer_in[1]; u32 cnt = message->ioctl.buffer_in[2]; - int fileHandle = message->ioctl.buffer_in[3]; - u32 flags = message->ioctl.buffer_in[4]; - - message->ioctl.buffer_io[0] = FSA_ReadFile(fd, ((u8*)message->ioctl.buffer_io) + 0x40, size, cnt, fileHandle, flags); + int i = 3; + u32 pos = 0; + int fileHandle; + u32 flags; + u8* buffer; + int (* func)(int, void*, u32, u32, u32, int, u32); // do not initialize + switch(message->ioctl.command) { + case IOCTL_FSA_READFILEWITHPOS: + case IOCTL_FSA_WRITEFILEWITHPOS: + pos = message->ioctl.buffer_in[i++]; + } + fileHandle = message->ioctl.buffer_in[i++]; + flags = message->ioctl.buffer_in[i++] & (~1); + + switch(message->ioctl.command) { + case IOCTL_FSA_READFILEWITHPOS: + flags |= 1; + case IOCTL_FSA_READFILE: + func = FSA_ReadFileWithPos; + buffer = ((u8*)message->ioctl.buffer_io); + break; + case IOCTL_FSA_WRITEFILEWITHPOS: + flags |= 1; + case IOCTL_FSA_WRITEFILE: + func = FSA_WriteFileWithPos; + buffer = ((u8*)message->ioctl.buffer_in); + break; + } + + message->ioctl.buffer_io[0] = func(fd, buffer + 0x40, size, cnt, pos, fileHandle, flags); break; } - case IOCTL_FSA_WRITEFILE: + + case IOCTL_FSA_APPENDFILE: + case IOCTL_FSA_APPENDFILEEX: { int fd = message->ioctl.buffer_in[0]; u32 size = message->ioctl.buffer_in[1]; u32 cnt = message->ioctl.buffer_in[2]; int fileHandle = message->ioctl.buffer_in[3]; - u32 flags = message->ioctl.buffer_in[4]; + u32 flags = 0; + if (message->ioctl.command == IOCTL_FSA_APPENDFILEEX) { + flags = message->ioctl.buffer_in[4]; + } - message->ioctl.buffer_io[0] = FSA_WriteFile(fd, ((u8*)message->ioctl.buffer_in) + 0x40, size, cnt, fileHandle, flags); - break; + message->ioctl.buffer_io[0] = FSA_AppendFileEx(fd, size, cnt, fileHandle, flags); } - case IOCTL_FSA_STATFILE: + case IOCTL_FSA_READDIR: + case IOCTL_FSA_GETSTATFILE: + case IOCTL_FSA_GETPOSFILE: { int fd = message->ioctl.buffer_in[0]; - int fileHandle = message->ioctl.buffer_in[1]; + int handle = message->ioctl.buffer_in[1]; + int (* func)(int, int, void*); // do not initialize - message->ioctl.buffer_io[0] = FSA_StatFile(fd, fileHandle, (fileStat_s*)(message->ioctl.buffer_io + 1)); + switch(message->ioctl.command) { + case IOCTL_FSA_READDIR: func = (int (*)(int, int, void*))FSA_ReadDir; break; + case IOCTL_FSA_GETSTATFILE: func = (int (*)(int, int, void*))FSA_GetStatFile; break; + case IOCTL_FSA_GETPOSFILE: func = (int (*)(int, int, void*))FSA_GetPosFile; break; + } + message->ioctl.buffer_io[0] = func(fd, handle, (void*)(message->ioctl.buffer_io + 1)); break; } + case IOCTL_FSA_REWINDDIR: + case IOCTL_FSA_CLOSEDIR: + case IOCTL_FSA_RAW_CLOSE: case IOCTL_FSA_CLOSEFILE: + case IOCTL_FSA_FLUSHFILE: + case IOCTL_FSA_TRUNCATEFILE: + case IOCTL_FSA_ISEOF: { int fd = message->ioctl.buffer_in[0]; - int fileHandle = message->ioctl.buffer_in[1]; - - message->ioctl.buffer_io[0] = FSA_CloseFile(fd, fileHandle); + int handle = message->ioctl.buffer_in[1]; + int (* func)(int, int); // do not initialize + + switch(message->ioctl.command) { + case IOCTL_FSA_REWINDDIR: func = FSA_RewindDir; break; + case IOCTL_FSA_CLOSEDIR: func = FSA_CloseDir; break; + case IOCTL_FSA_RAW_CLOSE: func = FSA_RawClose; break; + case IOCTL_FSA_CLOSEFILE: func = FSA_CloseFile; break; + case IOCTL_FSA_FLUSHFILE: func = FSA_FlushFile; break; + case IOCTL_FSA_TRUNCATEFILE: func = FSA_TruncateFile; break; + case IOCTL_FSA_ISEOF: func = FSA_IsEof; break; + } + message->ioctl.buffer_io[0] = func(fd, handle); break; } case IOCTL_FSA_SETFILEPOS: @@ -342,31 +452,7 @@ static int ipc_ioctl(ipcmessage *message) int fd = message->ioctl.buffer_in[0]; char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; - message->ioctl.buffer_io[0] = FSA_GetStat(fd, path, (fileStat_s*)(message->ioctl.buffer_io + 1)); - break; - } - case IOCTL_FSA_REMOVE: - { - int fd = message->ioctl.buffer_in[0]; - char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; - - message->ioctl.buffer_io[0] = FSA_Remove(fd, path); - break; - } - case IOCTL_FSA_REWINDDIR: - { - int fd = message->ioctl.buffer_in[0]; - int dirFd = message->ioctl.buffer_in[1]; - - message->ioctl.buffer_io[0] = FSA_RewindDir(fd, dirFd); - break; - } - case IOCTL_FSA_CHDIR: - { - int fd = message->ioctl.buffer_in[0]; - char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; - - message->ioctl.buffer_io[0] = FSA_ChangeDir(fd, path); + message->ioctl.buffer_io[0] = FSA_GetStat(fd, path, (FSStat*)(message->ioctl.buffer_io + 1)); break; } case IOCTL_FSA_RAW_OPEN: @@ -378,53 +464,63 @@ static int ipc_ioctl(ipcmessage *message) break; } case IOCTL_FSA_RAW_READ: + case IOCTL_FSA_RAW_WRITE: { int fd = message->ioctl.buffer_in[0]; u32 block_size = message->ioctl.buffer_in[1]; u32 cnt = message->ioctl.buffer_in[2]; u64 sector_offset = ((u64)message->ioctl.buffer_in[3] << 32ULL) | message->ioctl.buffer_in[4]; int deviceHandle = message->ioctl.buffer_in[5]; + u8* buffer; + int (* func)(int, void*, u32, u32, u64, int); // do not initialize - message->ioctl.buffer_io[0] = FSA_RawRead(fd, ((u8*)message->ioctl.buffer_io) + 0x40, block_size, cnt, sector_offset, deviceHandle); + switch(message->ioctl.command) { + case IOCTL_FSA_RAW_READ: + func = FSA_RawRead; + buffer = ((u8*)message->ioctl.buffer_io); + break; + case IOCTL_FSA_RAW_WRITE: + func = FSA_RawWrite; + buffer = ((u8*)message->ioctl.buffer_in); + break; + } + + message->ioctl.buffer_io[0] = func(fd, buffer + 0x40, block_size, cnt, sector_offset, deviceHandle); break; } - case IOCTL_FSA_RAW_WRITE: + case IOCTL_FSA_CHANGEMODE: + case IOCTL_FSA_CHANGEMODEEX: { int fd = message->ioctl.buffer_in[0]; - u32 block_size = message->ioctl.buffer_in[1]; - u32 cnt = message->ioctl.buffer_in[2]; - u64 sector_offset = ((u64)message->ioctl.buffer_in[3] << 32ULL) | message->ioctl.buffer_in[4]; - int deviceHandle = message->ioctl.buffer_in[5]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + int mode = message->ioctl.buffer_in[2]; + int mask = 0x777; + if (message->ioctl.command == IOCTL_FSA_CHANGEMODEEX) { + mask = message->ioctl.buffer_in[3]; + } - message->ioctl.buffer_io[0] = FSA_RawWrite(fd, ((u8*)message->ioctl.buffer_in) + 0x40, block_size, cnt, sector_offset, deviceHandle); + message->ioctl.buffer_io[0] = FSA_ChangeMode(fd, path, mode, mask); break; } - case IOCTL_FSA_RAW_CLOSE: + case IOCTL_FSA_CHANGEOWNER: { int fd = message->ioctl.buffer_in[0]; - int deviceHandle = message->ioctl.buffer_in[1]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + u32 owner = message->ioctl.buffer_in[2]; + u32 group = message->ioctl.buffer_in[3]; - message->ioctl.buffer_io[0] = FSA_RawClose(fd, deviceHandle); + message->ioctl.buffer_io[0] = FSA_ChangeOwner(fd, path, owner, group); break; } - case IOCTL_FSA_CHANGEMODE: + case IOCTL_CHECK_IF_IOSUHAX: { - int fd = message->ioctl.buffer_in[0]; - char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; - int mode = message->ioctl.buffer_in[2]; - - message->ioctl.buffer_io[0] = FSA_ChangeMode(fd, path, mode); + message->ioctl.buffer_io[0] = IOSUHAX_MAGIC_WORD; break; } - case IOCTL_CHECK_IF_IOSUHAX: - { - message->ioctl.buffer_io[0] = IOSUHAX_MAGIC_WORD; - break; - } default: res = IOS_ERROR_INVALID_ARG; break; - } + } return res; } @@ -436,9 +532,9 @@ int ipc_thread(void *arg) /*u32* messageQueue = svcAllocAlign(0xCAFF, 0x20, 0x20); int queueId = svcCreateMessageQueue(messageQueue, 0x10);*/ // mcp main thread message queue listening on "/dev/mcp" - int queueId = *(int*)0x5070AEC; - int exit = 0; - while(!exit) + int queueId = *(int*)0x5070AEC; + int exit = 0; + while(!exit) { res = svcReceiveMessage(queueId, &message, 0); if(res < 0)