diff --git a/source/iosuhax.c b/source/iosuhax.c index e7321d0..8763fa0 100644 --- a/source/iosuhax.c +++ b/source/iosuhax.c @@ -40,7 +40,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 @@ -48,7 +48,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 @@ -63,6 +63,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_GETFILEPOS 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 int iosuhaxHandle = -1; @@ -286,14 +303,44 @@ int IOSUHAX_FSA_FlushVolume(int fsaFd, const char *volume_path) return result; } -int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data) +int IOSUHAX_FSA_RollbackVolume(int fsaFd, const char *volume_path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(volume_path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], volume_path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_ROLLBACKVOLUME, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int _IOSUHAX_FSA_GetInfo(int fsaFd, const char* path, int type, uint32_t* out_data, int out_data_size) { if(iosuhaxHandle < 0) return iosuhaxHandle; const int input_cnt = 3; - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) @@ -302,22 +349,67 @@ int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint io_buf[0] = fsaFd; io_buf[1] = sizeof(uint32_t) * input_cnt; io_buf[2] = type; - strcpy(((char*)io_buf) + io_buf[1], device_path); + strcpy(((char*)io_buf) + io_buf[1], path); uint32_t out_buf[1 + 0x64 / 4]; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETDEVICEINFO, io_buf, io_buf_size, out_buf, sizeof(out_buf)); + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETINFO, io_buf, io_buf_size, out_buf, sizeof(out_buf)); if(res < 0) { free(io_buf); return res; } - memcpy(out_data, out_buf + 1, 0x64); + memcpy(out_data, out_buf + 1, out_data_size); free(io_buf); return out_buf[0]; } +int IOSUHAX_FSA_GetFreeSpaceSize(int fsaFd, const char *path, uint64_t* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, path, 0, (uint32_t*)out_data, sizeof(uint64_t)); +} + +int IOSUHAX_FSA_GetDirSize(int fsaFd, const char *path, uint64_t* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, path, 1, (uint32_t*)out_data, sizeof(uint64_t)); +} + +int IOSUHAX_FSA_GetEntryNum(int fsaFd, const char *path, uint32_t* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, path, 2, (uint32_t*)out_data, sizeof(uint32_t)); +} + +int IOSUHAX_FSA_GetFileSystemInfo(int fsaFd, const char *path, FileSystemInfo* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, path, 3, (uint32_t*)out_data, sizeof(FileSystemInfo)); +} + +int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, DeviceInfo* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, device_path, 4, (uint32_t*)out_data, sizeof(DeviceInfo)); +} + +int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, FSStat* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, path, 5, (uint32_t*)out_data, sizeof(FSStat)); +} + +int IOSUHAX_FSA_GetBadBlockInfo(int fsaFd, const char *path, BlockInfo* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, path, 6, (uint32_t*)out_data, sizeof(BlockInfo)); +} + +int IOSUHAX_FSA_GetJournalFreeSpaceSize(int fsaFd, const char *path, uint64_t* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, path, 7, (uint32_t*)out_data, sizeof(uint64_t)); +} + +int IOSUHAX_FSA_GetFragmentBlockInfo(int fsaFd, const char *path, BlockInfo* out_data) +{ + return _IOSUHAX_FSA_GetInfo(fsaFd, path, 8, (uint32_t*)out_data, sizeof(BlockInfo)); +} + int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags) { if(iosuhaxHandle < 0) @@ -506,177 +598,158 @@ int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path) return result; } -int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle) +int IOSUHAX_FSA_GetCwd(int fsaFd, char *out_path, int out_size) { if(iosuhaxHandle < 0) return iosuhaxHandle; - const int input_cnt = 3; + const int input_cnt = 2; - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + strlen(mode) + 2; + int io_buf_size = sizeof(uint32_t) * input_cnt; + if (out_size > 0x27F) out_size = 0x27F; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) return -2; io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = io_buf[1] + strlen(path) + 1; - strcpy(((char*)io_buf) + io_buf[1], path); - strcpy(((char*)io_buf) + io_buf[2], mode); + io_buf[1] = out_size; - int result_vec[2]; + int result_vec_size = 4 + 0x280; + uint8_t *result_vec = (uint8_t*) memalign(0x20, result_vec_size); + if(!result_vec) + { + free(io_buf); + return -2; + } - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENFILE, io_buf, io_buf_size, result_vec, sizeof(result_vec)); + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETCWD, io_buf, io_buf_size, result_vec, result_vec_size); if(res < 0) { + free(result_vec); free(io_buf); return res; } - *outHandle = result_vec[1]; + int result = *(int*)result_vec; + strncpy(out_path, (char*)result_vec + 4, out_size); free(io_buf); - return result_vec[0]; + free(result_vec); + return result; } -int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) +int IOSUHAX_FSA_MakeQuota(int fsaFd, const char* quota_path, uint32_t flags, uint64_t size) { if(iosuhaxHandle < 0) return iosuhaxHandle; const int input_cnt = 5; - int io_buf_size = sizeof(uint32_t) * input_cnt; + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(quota_path) + 1; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) return -2; io_buf[0] = fsaFd; - io_buf[1] = size; - io_buf[2] = cnt; - io_buf[3] = fileHandle; - io_buf[4] = flags; - - int out_buf_size = ((size * cnt + 0x40) + 0x3F) & ~0x3F; - - uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = flags; + io_buf[3] = (size >> 32) & 0xFFFFFFFF; + io_buf[4] = size & 0xFFFFFFFF; + strcpy(((char*)io_buf) + io_buf[1], quota_path); - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READFILE, io_buf, io_buf_size, out_buffer, out_buf_size); + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MAKEDIR, io_buf, io_buf_size, &result, sizeof(result)); if(res < 0) { - free(out_buffer); free(io_buf); return res; } - //! data is put to offset 0x40 to align the buffer output - memcpy(data, ((uint8_t*)out_buffer) + 0x40, size * cnt); - - int result = out_buffer[0]; - - free(out_buffer); free(io_buf); return result; } -int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) +int IOSUHAX_FSA_FlushQuota(int fsaFd, const char *quota_path) { if(iosuhaxHandle < 0) return iosuhaxHandle; - const int input_cnt = 5; + const int input_cnt = 2; - int io_buf_size = ((sizeof(uint32_t) * input_cnt + size * cnt + 0x40) + 0x3F) & ~0x3F; + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(quota_path) + 1; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) return -2; io_buf[0] = fsaFd; - io_buf[1] = size; - io_buf[2] = cnt; - io_buf[3] = fileHandle; - io_buf[4] = flags; - - //! data is put to offset 0x40 to align the buffer input - memcpy(((uint8_t*)io_buf) + 0x40, data, size * cnt); + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], quota_path); int result; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_WRITEFILE, io_buf, io_buf_size, &result, sizeof(result)); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_FLUSHQUOTA, io_buf, io_buf_size, &result, sizeof(result)); if(res < 0) { free(io_buf); return res; } + free(io_buf); return result; } -int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data) +int IOSUHAX_FSA_RollbackQuota(int fsaFd, const char *quota_path) { if(iosuhaxHandle < 0) return iosuhaxHandle; const int input_cnt = 2; - int io_buf_size = sizeof(uint32_t) * input_cnt; + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(quota_path) + 1; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) return -2; io_buf[0] = fsaFd; - io_buf[1] = fileHandle; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], quota_path); - int out_buf_size = 4 + sizeof(fileStat_s); - uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } + int result; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_STATFILE, io_buf, io_buf_size, out_buffer, out_buf_size); + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_ROLLBACKQUOTA, io_buf, io_buf_size, &result, sizeof(result)); if(res < 0) { free(io_buf); - free(out_buffer); return res; } - int result = out_buffer[0]; - memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); - free(io_buf); - free(out_buffer); return result; } -int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle) +int IOSUHAX_FSA_RollbackQuotaForce(int fsaFd, const char *quota_path) { if(iosuhaxHandle < 0) return iosuhaxHandle; const int input_cnt = 2; - int io_buf_size = sizeof(uint32_t) * input_cnt; + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(quota_path) + 1; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) return -2; io_buf[0] = fsaFd; - io_buf[1] = fileHandle; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], quota_path); int result; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEFILE, io_buf, io_buf_size, &result, sizeof(result)); + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_ROLLBACKQUOTAFORCE, io_buf, io_buf_size, &result, sizeof(result)); if(res < 0) { free(io_buf); @@ -687,44 +760,47 @@ int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle) return result; } -int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position) +int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle) { if(iosuhaxHandle < 0) return iosuhaxHandle; const int input_cnt = 3; - int io_buf_size = sizeof(uint32_t) * input_cnt; + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + strlen(mode) + 2; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) return -2; io_buf[0] = fsaFd; - io_buf[1] = fileHandle; - io_buf[2] = position; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = io_buf[1] + strlen(path) + 1; + strcpy(((char*)io_buf) + io_buf[1], path); + strcpy(((char*)io_buf) + io_buf[2], mode); - int result; + int result_vec[2]; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_SETFILEPOS, io_buf, io_buf_size, &result, sizeof(result)); + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENFILE, io_buf, io_buf_size, result_vec, sizeof(result_vec)); if(res < 0) { free(io_buf); return res; } + *outHandle = result_vec[1]; free(io_buf); - return result; + return result_vec[0]; } -int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data) +int IOSUHAX_FSA_OpenFileEx(int fsaFd, const char* path, const char* mode, int* outHandle, uint32_t flags, int create_mode, uint32_t create_alloc_size) { if(iosuhaxHandle < 0) return iosuhaxHandle; - const int input_cnt = 2; + const int input_cnt = 6; - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + strlen(mode) + 2; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) @@ -732,83 +808,621 @@ int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data) io_buf[0] = fsaFd; io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); + io_buf[2] = io_buf[1] + strlen(path) + 1; + io_buf[3] = flags; + io_buf[4] = create_mode; + io_buf[5] = create_alloc_size; + strcpy(((char*)io_buf) + io_buf[1], path); + strcpy(((char*)io_buf) + io_buf[2], mode); - int out_buf_size = 4 + sizeof(fileStat_s); - uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); + int result_vec[2]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENFILEEX, io_buf, io_buf_size, result_vec, sizeof(result_vec)); + if(res < 0) + { + free(io_buf); + return res; + } + + *outHandle = result_vec[1]; + free(io_buf); + return result_vec[0]; +} + +int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 5; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = fileHandle; + io_buf[4] = flags; + + int out_buf_size = ((size * cnt + 0x40) + 0x3F) & ~0x3F; + + uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); if(!out_buffer) { free(io_buf); return -2; } - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETSTAT, io_buf, io_buf_size, out_buffer, out_buf_size); + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READFILE, io_buf, io_buf_size, out_buffer, out_buf_size); if(res < 0) { - free(io_buf); free(out_buffer); + free(io_buf); return res; } + //! data is put to offset 0x40 to align the buffer output + memcpy(data, ((uint8_t*)out_buffer) + 0x40, size * cnt); + int result = out_buffer[0]; - memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); - free(io_buf); free(out_buffer); + free(io_buf); return result; } -int IOSUHAX_FSA_Remove(int fsaFd, const char *path) +int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) { if(iosuhaxHandle < 0) return iosuhaxHandle; - const int input_cnt = 2; + const int input_cnt = 5; - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + int io_buf_size = ((sizeof(uint32_t) * input_cnt + size * cnt + 0x40) + 0x3F) & ~0x3F; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) return -2; io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = fileHandle; + io_buf[4] = flags; - int result; + //! data is put to offset 0x40 to align the buffer input + memcpy(((uint8_t*)io_buf) + 0x40, data, size * cnt); - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REMOVE, io_buf, io_buf_size, &result, sizeof(result)); + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_WRITEFILE, io_buf, io_buf_size, &result, sizeof(result)); if(res < 0) { free(io_buf); return res; } - free(io_buf); return result; } -int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode) +int IOSUHAX_FSA_ReadFileWithPos(int fsaFd, void* data, uint32_t size, uint32_t cnt, uint32_t position, int fileHandle, uint32_t flags) { if(iosuhaxHandle < 0) return iosuhaxHandle; - const int input_cnt = 3; + const int input_cnt = 6; - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + int io_buf_size = sizeof(uint32_t) * input_cnt; uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); if(!io_buf) return -2; io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = mode; - strcpy(((char*)io_buf) + io_buf[1], path); + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = position; + io_buf[4] = fileHandle; + io_buf[5] = flags; - int result; + int out_buf_size = ((size * cnt + 0x40) + 0x3F) & ~0x3F; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHANGEMODE, io_buf, io_buf_size, &result, sizeof(result)); + uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READFILEWITHPOS, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(out_buffer); + free(io_buf); + return res; + } + + //! data is put to offset 0x40 to align the buffer output + memcpy(data, ((uint8_t*)out_buffer) + 0x40, size * cnt); + + int result = out_buffer[0]; + + free(out_buffer); + free(io_buf); + return result; +} + +int IOSUHAX_FSA_WriteFileWithPos(int fsaFd, const void* data, uint32_t size, uint32_t cnt, uint32_t position, int fileHandle, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 6; + + int io_buf_size = ((sizeof(uint32_t) * input_cnt + size * cnt + 0x40) + 0x3F) & ~0x3F; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = position; + io_buf[4] = fileHandle; + io_buf[5] = flags; + + //! data is put to offset 0x40 to align the buffer input + memcpy(((uint8_t*)io_buf) + 0x40, data, size * cnt); + + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_WRITEFILEWITHPOS, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + free(io_buf); + return result; +} + +int IOSUHAX_FSA_AppendFile(int fsaFd, uint32_t size, uint32_t cnt, int fileHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 4; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = fileHandle; + + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_APPENDFILE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + free(io_buf); + return result; +} + +int IOSUHAX_FSA_AppendFileEx(int fsaFd, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 5; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = fileHandle; + io_buf[4] = flags; + + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_APPENDFILEEX, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + free(io_buf); + return result; +} + +int IOSUHAX_FSA_GetStatFile(int fsaFd, int fileHandle, FSStat* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int out_buf_size = 4 + sizeof(FSStat); + uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETSTATFILE, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(io_buf); + free(out_buffer); + return res; + } + + int result = out_buffer[0]; + memcpy(out_data, out_buffer + 1, sizeof(FSStat)); + + free(io_buf); + free(out_buffer); + return result; +} + +int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEFILE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_FlushFile(int fsaFd, int fileHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_FLUSHFILE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_TruncateFile(int fsaFd, int fileHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_TRUNCATEFILE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_GetFilePos(int fsaFd, int fileHandle, uint32_t* position) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int out_buf_size = 4 + sizeof(uint32_t); + uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETFILEPOS, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(io_buf); + free(out_buffer); + return res; + } + + int result = out_buffer[0]; + *position = out_buffer[1]; + + free(io_buf); + free(out_buffer); + return result; +} + +int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + io_buf[2] = position; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_SETFILEPOS, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_IsEof(int fsaFd, int fileHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_ISEOF, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_Remove(int fsaFd, const char *path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REMOVE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_Rename(int fsaFd, const char *old_path, const char *new_path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(old_path) + strlen(new_path) + 2; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + memset(io_buf, 0, io_buf_size); + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = io_buf[1] + strlen(old_path) + 1; + + strcpy(((char*)io_buf) + io_buf[1], old_path); + strcpy(((char*)io_buf) + io_buf[2], new_path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RENAME, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = mode; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHANGEMODE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_ChangeModeEx(int fsaFd, const char* path, int mode, int mask) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 4; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = mode; + io_buf[3] = mask; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHANGEMODEEX, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_ChangeOwner(int fsaFd, const char* path, uint32_t owner, uint32_t group) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 4; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = owner; + io_buf[3] = group; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHANGEOWNER, io_buf, io_buf_size, &result, sizeof(result)); if(res < 0) { free(io_buf); diff --git a/source/iosuhax.h b/source/iosuhax.h index 4e52ebf..631675c 100644 --- a/source/iosuhax.h +++ b/source/iosuhax.h @@ -36,32 +36,56 @@ extern "C" { #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 { uint32_t flag; uint32_t permission; uint32_t owner_id; uint32_t group_id; - uint32_t size; // size in bytes - uint32_t physsize; // physical size on disk in bytes - uint32_t unk[3]; - uint32_t id; - uint32_t ctime; - uint32_t mtime; - uint32_t unk2[0x0D]; -}fileStat_s; + uint32_t size; // size in bytes + uint32_t physsize; // physical size on disk in bytes + uint64_t quota_size; + uint32_t id; + uint64_t ctime; + uint64_t mtime; + uint8_t attributes[48]; +} FSStat; typedef struct { - fileStat_s stat; - char name[0x100]; + FSStat stat; + char name[0x100]; }directoryEntry_s; -#define DIR_ENTRY_IS_DIRECTORY 0x80000000 +typedef struct +{ + uint8_t unknown[0x1E]; +} FileSystemInfo; + +typedef struct +{ + uint8_t unknown[0x28]; +} DeviceInfo; + +typedef struct +{ + uint64_t blocks_count; + uint64_t some_count; + uint32_t 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 IOSUHAX_Open(const char *dev); // if dev == NULL the default path /dev/iosuhax will be used int IOSUHAX_Close(void); @@ -77,8 +101,17 @@ int IOSUHAX_FSA_Close(int fsaFd); int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len); int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags); int IOSUHAX_FSA_FlushVolume(int fsaFd, const char* volume_path); - -int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data); +int IOSUHAX_FSA_RollbackVolume(int fsaFd, const char* volume_path); + +int IOSUHAX_FSA_GetFreeSpaceSize(int fsaFd, const char *path, uint64_t* out_data); +int IOSUHAX_FSA_GetDirSize(int fsaFd, const char *path, uint64_t* out_data); +int IOSUHAX_FSA_GetEntryNum(int fsaFd, const char *path, uint32_t* out_data); +int IOSUHAX_FSA_GetFileSystemInfo(int fsaFd, const char *path, FileSystemInfo* out_data); +int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, DeviceInfo* out_data); +int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, FSStat* out_data); +int IOSUHAX_FSA_GetBadBlockInfo(int fsaFd, const char *path, BlockInfo* out_data); +int IOSUHAX_FSA_GetJournalFreeSpaceSize(int fsaFd, const char *path, uint64_t* out_data); +int IOSUHAX_FSA_GetFragmentBlockInfo(int fsaFd, const char *path, BlockInfo* out_data); int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags); int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle); @@ -86,16 +119,31 @@ int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data); int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle); int IOSUHAX_FSA_CloseDir(int fsaFd, int handle); int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path); +int IOSUHAX_FSA_GetCwd(int fsaFd, char *out_path, int out_size); + +int IOSUHAX_FSA_MakeQuota(int fsaFd, const char* quota_path, uint32_t flags, uint64_t size); +int IOSUHAX_FSA_FlushQuota(int fsaFd, const char* quota_path); +int IOSUHAX_FSA_RollbackQuota(int fsaFd, const char* quota_path); +int IOSUHAX_FSA_RollbackQuotaForce(int fsaFd, const char* quota_path); int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle); +int IOSUHAX_FSA_OpenFileEx(int fsaFd, const char* path, const char* mode, int* outHandle, uint32_t flags, int create_mode, uint32_t create_alloc_size); int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); -int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data); +int IOSUHAX_FSA_ReadFileWithPos(int fsaFd, void* data, uint32_t size, uint32_t cnt, uint32_t position, int fileHandle, uint32_t flags); +int IOSUHAX_FSA_WriteFileWithPos(int fsaFd, const void* data, uint32_t size, uint32_t cnt, uint32_t position, int fileHandle, uint32_t flags); +int IOSUHAX_FSA_GetStatFile(int fsaFd, int fileHandle, FSStat* out_data); int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle); +int IOSUHAX_FSA_FlushFile(int fsaFd, int fileHandle); +int IOSUHAX_FSA_TruncateFile(int fsaFd, int fileHandle); +int IOSUHAX_FSA_GetFilePos(int fsaFd, int fileHandle, uint32_t* position); int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position); -int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data); +int IOSUHAX_FSA_IsEof(int fsaFd, int fileHandle); int IOSUHAX_FSA_Remove(int fsaFd, const char *path); +int IOSUHAX_FSA_Rename(int fsaFd, const char *old_path, const char *new_path); int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode); +int IOSUHAX_FSA_ChangeModeEx(int fsaFd, const char* path, int mode, int mask); +int IOSUHAX_FSA_ChangeOwner(int fsaFd, const char* path, uint32_t owner, uint32_t group); int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle); int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); diff --git a/source/iosuhax_devoptab.c b/source/iosuhax_devoptab.c index 6ac0580..5b6e580 100644 --- a/source/iosuhax_devoptab.c +++ b/source/iosuhax_devoptab.c @@ -158,8 +158,8 @@ static int fs_dev_open_r (struct _reent *r, void *fileStruct, const char *path, if(result == 0) { - fileStat_s stats; - result = IOSUHAX_FSA_StatFile(dev->fsaFd, fd, &stats); + FSStat stats; + result = IOSUHAX_FSA_GetStatFile(dev->fsaFd, fd, &stats); if(result != 0) { IOSUHAX_FSA_CloseFile(dev->fsaFd, fd); r->_errno = result; @@ -343,8 +343,8 @@ static int fs_dev_fstat_r (struct _reent *r, int fd, struct stat *st) // Zero out the stat buffer memset(st, 0, sizeof(struct stat)); - fileStat_s stats; - int result = IOSUHAX_FSA_StatFile(file->dev->fsaFd, fd, &stats); + FSStat stats; + int result = IOSUHAX_FSA_GetStatFile(file->dev->fsaFd, fd, &stats); if(result != 0) { r->_errno = result; OSUnlockMutex(file->dev->pMutex); @@ -414,7 +414,7 @@ static int fs_dev_stat_r (struct _reent *r, const char *path, struct stat *st) return -1; } - fileStat_s stats; + FSStat stats; int result = IOSUHAX_FSA_GetStat(dev->fsaFd, real_path, &stats); @@ -638,7 +638,7 @@ static int fs_dev_statvfs_r (struct _reent *r, const char *path, struct statvfs uint64_t size; - int result = IOSUHAX_FSA_GetDeviceInfo(dev->fsaFd, real_path, 0x00, (uint32_t*)&size); + int result = IOSUHAX_FSA_GetFreeSpaceSize(dev->fsaFd, real_path, &size); free(real_path);