diff --git a/source/iosuhax.c b/source/iosuhax.c index 5c6da2f..99a560e 100644 --- a/source/iosuhax.c +++ b/source/iosuhax.c @@ -58,6 +58,7 @@ #define IOCTL_FSA_RAW_READ 0x55 #define IOCTL_FSA_RAW_WRITE 0x56 #define IOCTL_FSA_RAW_CLOSE 0x57 +#define IOCTL_FSA_CHANGEMODE 0x58 static int iosuhaxHandle = -1; @@ -742,6 +743,37 @@ int IOSUHAX_FSA_Remove(int fsaFd, const char *path) 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_RawOpen(int fsaFd, const char* device_path, int* outHandle) { if(iosuhaxHandle < 0) diff --git a/source/iosuhax.h b/source/iosuhax.h index d267cac..e7eb4c3 100644 --- a/source/iosuhax.h +++ b/source/iosuhax.h @@ -94,6 +94,7 @@ int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle); 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_Remove(int fsaFd, const char *path); +int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode); 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 1bfe0fa..6ac0580 100644 --- a/source/iosuhax_devoptab.c +++ b/source/iosuhax_devoptab.c @@ -585,6 +585,37 @@ static int fs_dev_mkdir_r (struct _reent *r, const char *path, int mode) return 0; } +static int fs_dev_chmod_r (struct _reent *r, const char *path, int mode) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_ChangeMode(dev->fsaFd, real_path, mode); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + static int fs_dev_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) { fs_dev_private_t *dev = fs_dev_get_device_data(path); @@ -801,7 +832,7 @@ static const devoptab_t devops_fs = { fs_dev_statvfs_r, fs_dev_ftruncate_r, fs_dev_fsync_r, - NULL, /* fs_dev_chmod_r */ + fs_dev_chmod_r, NULL, /* fs_dev_fchmod_r */ NULL /* Device data */ };