s32 __FAT_Ioctlv(s32 fd, u32 cmd, ioctlv *vector, u32 inlen, u32 iolen) { s32 ret = IPC_EINVAL; /* Invalidate cache */ InvalidateVector(vector, inlen, iolen); /* Parse command */ switch (cmd) { /** Create directory **/ case IOCTL_FAT_MKDIR: { char *dirpath = (char *)vector[0].data; dbg_printf("FAT: IOCTL_FAT_MKDIR: fd = %d, dirpath = %s\n", fd, dirpath); /* Sart blinking */ Led_BlinkOn(); /* Create directory */ ret = FAT_CreateDir(dirpath); /* Stop blinking */ Led_BlinkOff(); dbg_printf("FAT: IOCTL_FAT_MKDIR: ret = %d\n", ret); break; } /** Create file **/ case IOCTL_FAT_MKFILE: { char *filepath = (char *)vector[0].data; dbg_printf("FAT: IOCTL_FAT_MKFILE: fd = %d, filepath = %s\n", fd, filepath); /* Sart blinking */ Led_BlinkOn(); /* Create file */ ret = FAT_CreateFile(filepath); /* Stop blinking */ Led_BlinkOff(); dbg_printf("FAT: IOCTL_FAT_MKFILE: ret = %d\n", ret); break; } /** Read directory **/ case IOCTL_FAT_READDIR_FS: case IOCTL_FAT_READDIR: { char *dirpath = (char *)vector[0].data; char *outbuf = NULL; u32 *outlen = NULL; u32 buflen = 0; u32 entries = 0, forFS; /* Set FS flag */ forFS = (cmd == IOCTL_FAT_READDIR_FS); dbg_printf("FAT: IOCTL_FAT_READDIR%s: fd = %d, dirpath = %s\n", forFS? "_FS" : "", fd, dirpath); /* Input values */ if (iolen > 1) { entries = *(u32 *)vector[1].data; outbuf = (char *)vector[2].data; outlen = (u32 *)vector[3].data; buflen = vector[2].len; } else outlen = (u32 *)vector[1].data; /* Read directory */ ret = FAT_ReadDir(dirpath, outbuf, buflen, outlen, entries, forFS); dbg_printf("FAT: IOCTL_FAT_READDIR%s: ret = %d\n", forFS? "_FS" : "", ret); break; } /** Delete object **/ case IOCTL_FAT_DELETE: { char *path = (char *)vector[0].data; dbg_printf("FAT: IOCTL_FAT_DELETE: fd = %d, path = %s\n", fd, path); /* Sart blinking */ Led_BlinkOn(); /* Delete file/directory */ ret = FAT_Delete(path); /* Stop blinking */ Led_BlinkOff(); dbg_printf("FAT: IOCTL_FAT_DELETE: ret = %d\n", ret); break; } /** Delete directory **/ case IOCTL_FAT_DELETEDIR: { char *dirpath = (char *)vector[0].data; dbg_printf("FAT: IOCTL_FAT_DELETEDIR: fd = %d, path = %s\n", fd, dirpath); /* Sart blinking */ Led_BlinkOn(); /* Delete directory */ ret = FAT_DeleteDir(dirpath); /* Stop blinking */ Led_BlinkOff(); dbg_printf("FAT: IOCTL_FAT_DELETEDIR: ret = %d\n", ret); break; } /** Rename object **/ case IOCTL_FAT_RENAME: { char *oldname = (char *)vector[0].data; char *newname = (char *)vector[1].data; dbg_printf("FAT: IOCTL_FAT_RENAME: fd = %d, from = %s, to = %s\n", fd, oldname, newname); /* Sart blinking */ Led_BlinkOn(); /* Rename object */ ret = FAT_Rename(oldname, newname); /* Stop blinking */ Led_BlinkOff(); dbg_printf("FAT: IOCTL_FAT_RENAME: ret = %d\n", ret); break; } /** Get stats **/ case IOCTL_FAT_STATS: { char *path = (char *)vector[0].data; void *stats = (void *)vector[1].data; dbg_printf("FAT: IOCTL_FAT_STATS: fd = %d, path = %s\n", fd, path); /* Get stats */ ret = FAT_GetStats(path, stats); dbg_printf("FAT: IOCTL_FAT_STATS: ret = %d, size = %d\n", ret, ((struct stats *)stats)->size); break; } /** Get usage **/ case IOCTL_FAT_GETUSAGE_FS: case IOCTL_FAT_GETUSAGE: { char *path = (char *)vector[0].data; u64 *size = (u64 *)vector[1].data; u32 *files = (u32 *)vector[2].data; u32 *dirs = (u32 *)vector[3].data; u32 fakedirs, fakefiles, forFS; /* Set default pointers */ if (iolen < 2) files = &fakefiles; if (iolen < 3) dirs = &fakedirs; /* Set initial values */ *size = 0; *files = 0; *dirs = 0; /* Set FS flag */ forFS = (cmd == IOCTL_FAT_GETUSAGE_FS); dbg_printf("FAT: IOCTL_FAT_GETUSAGE%s: fd = %d, path = %s\n", forFS?"_FS":"", fd, path); /* Get usage */ ret = FAT_GetUsage(path, size, files, dirs, forFS); dbg_printf("FAT: IOCTL_FAT_GETUSAGE: ret = %d, size = %dl, files = %d, dirs = %d\n", ret, *size, *files, *dirs); break; } /** Mount SD card **/ case IOCTL_FAT_MOUNT_SD: { s32 partition = inlen > 0 ? *(s32 *)vector[0].data : -1; /* Mount SD card */ ret = FAT_Mount(0, partition); break; } /** Unmount SD card **/ case IOCTL_FAT_UMOUNT_SD: { /* Unmount SD card */ ret = FAT_Unmount(0); if (ret < 0) break; /* Deinitialize SDIO */ ret = sdio_Shutdown(); if (!ret) ret = IPC_EINVAL; break; } /** Mount USB device **/ case IOCTL_FAT_MOUNT_USB: { s32 partition = inlen > 0 ? *(s32 *)vector[0].data : -1; /* Mount USB device */ ret = FAT_Mount(1, partition); break; } /** Unmount USB card **/ case IOCTL_FAT_UMOUNT_USB: { /* Unmount USB */ ret = FAT_Unmount(1); if (ret < 0) break; /* Deinitialize USB */ ret = usbstorage_Shutdown(); if (!ret) ret = IPC_EINVAL; break; } /** Get mounted partition of the given device **/ case IOCTL_FAT_GETPARTITION: { u32 device = *(u32 *)vector[0].data; u32 *partition = (u32 *)vector[1].data; /* Get partition */ ret = FAT_GetPartition(device, partition); break; } default: break; } /* Flush cache */ FlushVector(vector, inlen, iolen); return ret; }
s32 FS_Ioctl(ipcmessage *message, u32 *flag) { u32 *inbuf = message->ioctl.buffer_in; u32 *iobuf = message->ioctl.buffer_io; u32 iolen = message->ioctl.length_io; u32 cmd = message->ioctl.command; s32 ret; /* Set flag */ *flag = config.mode; /* Parse comamnd */ switch (cmd) { /** Create directory **/ case IOCTL_ISFS_CREATEDIR: { fsattr *attr = (fsattr *)inbuf; FS_printf("FS_CreateDir(): %s\n", attr->filepath); /* Check path */ ret = FS_CheckPath(attr->filepath); if (ret) { *flag = 0; break; } /* FAT mode */ if (config.mode) { char fatpath[FAT_MAXPATH]; /* Generate path */ FS_GeneratePath(attr->filepath, fatpath); /* Create directory */ return FAT_CreateDir(fatpath); } break; } /** Create file **/ case IOCTL_ISFS_CREATEFILE: { fsattr *attr = (fsattr *)inbuf; FS_printf("FS_CreateFile(): %s\n", attr->filepath); /* Check path */ ret = FS_CheckPath(attr->filepath); if (ret) { *flag = 0; break; } /* FAT mode */ if (config.mode) { char fatpath[FAT_MAXPATH]; /* Generate path */ FS_GeneratePath(attr->filepath, fatpath); /* Create file */ return FAT_CreateFile(fatpath); } break; } /** Delete object **/ case IOCTL_ISFS_DELETE: { char *filepath = (char *)inbuf; FS_printf("FS_Delete(): %s\n", filepath); /* Check path */ ret = FS_CheckPath(filepath); if (ret) { *flag = 0; break; } /* FAT mode */ if (config.mode) { char fatpath[FAT_MAXPATH]; /* Generate path */ FS_GeneratePath(filepath, fatpath); /* Delete */ return FAT_Delete(fatpath); } break; } /** Rename object **/ case IOCTL_ISFS_RENAME: { fsrename *rename = (fsrename *)inbuf; FS_printf("FS_Rename(): %s -> %s\n", rename->filepathOld, rename->filepathNew); /* Check paths */ ret = FS_CheckPath(rename->filepathOld); ret |= FS_CheckPath(rename->filepathNew); if (ret) { *flag = 0; break; } /* FAT mode */ if (config.mode) { char oldpath[FAT_MAXPATH]; char newpath[FAT_MAXPATH]; struct stats stats; /* Generate paths */ FS_GeneratePath(rename->filepathOld, oldpath); FS_GeneratePath(rename->filepathNew, newpath); /* Compare paths */ if (strcmp(oldpath, newpath)) { /* Check new path */ ret = FAT_GetStats(newpath, &stats); /* New path exists */ if (ret >= 0) { /* Delete directory */ if (stats.attrib & AM_DIR) FAT_DeleteDir(newpath); /* Delete */ FAT_Delete(newpath); } /* Rename */ return FAT_Rename(oldpath, newpath); } /* Check path exists */ return FAT_GetStats(oldpath, NULL); } break; } /** Get device stats **/ case IOCTL_ISFS_GETSTATS: { FS_printf("FS_GetStats():\n"); /* FAT mode */ if (config.mode) { fsstats *stats = (fsstats *)iobuf; /* Clear buffer */ memset(iobuf, 0, iolen); /* Fill stats */ stats->block_size = 0x4000; stats->free_blocks = 0x5DEC; stats->used_blocks = 0x1DD4; stats->unk3 = 0x10; stats->unk4 = 0x02F0; stats->free_inodes = 0x146B; stats->unk5 = 0x0394; /* Flush cache */ os_sync_after_write(iobuf, iolen); return 0; } break; } /** Get file stats **/ case IOCTL_ISFS_GETFILESTATS: { s32 fd = message->fd; FS_printf("FS_GetFileStats(): %d\n", fd); /* Disable flag */ *flag = 0; break; } /** Get attributes **/ case IOCTL_ISFS_GETATTR: { char *path = (char *)inbuf; FS_printf("FS_GetAttributes(): %s\n", path); /* Check path */ ret = FS_CheckPath(path); if (ret) { *flag = 0; break; } /* FAT mode */ if (config.mode) { fsattr *attr = (fsattr *)iobuf; char fatpath[FAT_MAXPATH]; /* Generate path */ FS_GeneratePath(path, fatpath); /* Check path */ ret = FAT_GetStats(fatpath, NULL); if (ret < 0) return ret; /* Fake attributes */ attr->owner_id = FS_GetUID(); attr->group_id = FS_GetGID(); attr->ownerperm = ISFS_OPEN_RW; attr->groupperm = ISFS_OPEN_RW; attr->otherperm = ISFS_OPEN_RW; attr->attributes = 0; /* Copy filepath */ memcpy(attr->filepath, path, ISFS_MAXPATH); /* Flush cache */ os_sync_after_write(iobuf, iolen); return 0; } break; } /** Set attributes **/ case IOCTL_ISFS_SETATTR: { fsattr *attr = (fsattr *)inbuf; FS_printf("FS_SetAttributes(): %s\n", attr->filepath); /* Check path */ ret = FS_CheckPath(attr->filepath); if (ret) { *flag = 0; break; } /* FAT mode */ if (config.mode) { char fatpath[FAT_MAXPATH]; /* Generate path */ FS_GeneratePath(attr->filepath, fatpath); /* Check path */ return FAT_GetStats(fatpath, NULL); } break; } /** Format **/ case IOCTL_ISFS_FORMAT: { FS_printf("FS_Format():\n"); /* FAT mode */ if (config.mode) return 0; break; } /** Set FS mode **/ case IOCTL_ISFS_SETMODE: { u32 val = inbuf[0]; FS_printf("FS_SetMode(): %d\n", val); /* Set flag */ *flag = 1; /* Set path */ strcpy(config.path, ""); /* FAT mode enabled */ if (val) { char fatpath[FAT_MAXPATH]; /* Initialize FAT */ ret = FAT_Init(); if (ret < 0) return ret; /* Generate path */ FS_GeneratePath("/tmp", fatpath); /* Delete "/tmp" */ FAT_DeleteDir(fatpath); } /* Set FS mode */ config.mode = val; return 0; } default: break; } /* Call handler */ return -6; }