예제 #1
0
s32 handleFFSIoctl(ipcmessage *msg)
{
	s32 ret = 0;

	u32 cmd = msg->ioctl.command;
	u32 length_io = msg->ioctl.length_io;
	u32 *buffer_io = msg->ioctl.buffer_io;
	u32 *buffer_in = msg->ioctl.buffer_in;

	switch(cmd) {
	case FFS_IOCTL_CREATEDIR: {
		if (emulationType == FFS_EMU_NONE)
			goto originalIoctl;

		char dirname[MAX_FILENAME_SIZE];
		preappend_nand_dev_name((const char *) buffer_in, dirname);
		ret = FAT_MakeDir(dirname);
		break;
	}
	case FFS_IOCTL_CREATEFILE: {
		if (emulationType == FFS_EMU_NONE)
			goto originalIoctl;

		char filename[MAX_FILENAME_SIZE];
		preappend_nand_dev_name((const char *) buffer_in, filename);
		ret = FAT_MakeFile(filename);
		break;
	}
	case FFS_IOCTL_DELETE: {
		if (emulationType == FFS_EMU_NONE)
			goto originalIoctl;

		char filename[MAX_FILENAME_SIZE];
		preappend_nand_dev_name((const char *) buffer_in, filename);
		ret = FAT_Delete(filename);
		break;
	}
	case FFS_IOCTL_RENAME: {
		u8 *names = (u8 *) buffer_in;
		if (emulationType == FFS_EMU_NONE)
			goto originalIoctl;

		char newname[MAX_FILENAME_SIZE];
		char oldname[MAX_FILENAME_SIZE];
		struct stat filestat;

		preappend_nand_dev_name((const char *)names, oldname);
		preappend_nand_dev_name((const char *) names+OFFSET_NEW_NAME, newname);

		// Check if newname exists
		if (FAT_Stat(newname, &filestat) >=0) {
			if (S_ISDIR(filestat.st_mode))
				FAT_DeleteDir(newname);
			else
				FAT_Delete(newname);
		}

		ret = FAT_Rename(oldname, newname);
		break;
	}
	case FFS_IOCTL_GETSTATS: {
		char drive[MAX_FILENAME_SIZE];
		struct statvfs vfsstat;
		if (emulationType == FFS_EMU_NONE)
			goto originalIoctl;

		preappend_nand_dev_name("/", drive);
		ret = FAT_VFSStats(drive, &vfsstat);
		if (ret >= 0) {
			fsstats *s = (fsstats *) buffer_io;
			Memset(buffer_io, 0, length_io);

			s->block_size  = vfsstat.f_bsize;
			s->free_blocks = vfsstat.f_bfree;
			s->free_inodes = vfsstat.f_ffree;
			s->used_blocks = vfsstat.f_blocks - vfsstat.f_bfree;

			os_sync_after_write(buffer_io, length_io);
		}

		break;
	}
	case FFS_IOCTL_GETFILESTATS: {
		if (emulationType == FFS_EMU_NONE) 
			goto originalIoctl;

		if (msg->fd > FFS_FD_MAGIC)
			goto originalIoctl;

		struct fstats *s = (struct fstats *) buffer_io;

		ret = FAT_FileStats(msg->fd, s);
		break;
	}
	case FFS_IOCTL_GETATTR: {
		if (emulationType == FFS_EMU_NONE) 
			goto originalIoctl;

		char name[MAX_FILENAME_SIZE];
		preappend_nand_dev_name((const char *)buffer_in, name);
		ret = FAT_Stat(name, NULL); // if it exists, return the same permissions always
		if (ret >= 0) {
			fsattr *attributes = (fsattr *) buffer_io;
			attributes->owner_id   = 0;
			attributes->group_id   = 0;
			attributes->attributes = 0;
			attributes->ownerperm  = ISFS_OPEN_RW;
			attributes->groupperm  = ISFS_OPEN_RW;
			attributes->otherperm  = ISFS_OPEN_RW;

			os_sync_after_write(buffer_io, length_io);
			ret = 0;
		}
		break;
	}
	case FFS_IOCTL_SETATTR: {
		if (emulationType == FFS_EMU_NONE) 
			goto originalIoctl;

		char name[MAX_FILENAME_SIZE];
		preappend_nand_dev_name((const char *)buffer_in, name);

		ret = FAT_Stat(name, NULL); // Ignore permission, success if the file exists
		break;
	}
	case FFS_IOCTL_FORMAT: {
		if (emulationType == FFS_EMU_NONE)
			goto originalIoctl;
		ret = 0;
		break;
	}

	case FFS_IOCTL_SETNANDEMULATION: {
		char tmpdir[MAX_FILENAME_SIZE];
		u32 state = buffer_in[0];
		if (state) {
			preappend_nand_dev_name("/tmp", tmpdir);
			if (FAT_Init() >= 0) {
				FAT_DeleteDir(tmpdir);
			}
		}
		emulationType = state;
		break;
	}
	originalIoctl:
	default:
		ret = FFS_HandleIoctl(msg);
		break;
	}
	return ret;
}
예제 #2
0
파일: main.c 프로젝트: kenji-tan/fat-module
s32 FAT_Ioctlv(s32 fd, u32 cmd, ioctlv *vector, u32 inlen, u32 iolen)
{
	s32 ret = IPC_EINVAL;

	/* Invalidate ache */
	InvalidateVector(vector, inlen, iolen);

	/* Parse command */
	switch (cmd) {
	/** Create directory **/
	case IOCTL_FAT_MKDIR: {
		char *dirpath = (char *)vector[0].data;

		/* Create directory */
		ret = FAT_CreateDir(dirpath);

		break;
	}

	/** Create file **/
	case IOCTL_FAT_MKFILE: {
		char *filepath = (char *)vector[0].data;

		/* Create file */
		ret = FAT_CreateFile(filepath);

		break;
	}

	/** Read directory **/
	case IOCTL_FAT_READDIR: {
		char *dirpath = (char *)vector[0].data;
		char *outbuf  = NULL;
		u32  *outlen  = NULL;
		u32   buflen  = 0;

		u32 entries = 0;

		/* 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;

		/* Clear buffer */
		if (outbuf)
			memset(outbuf, 0, buflen);

		/* Read directory */
		ret = FAT_ReadDir(dirpath, outbuf, outlen, entries);

		break;
	}

	/** Read directory (LFN) **/
	case IOCTL_FAT_READDIR_LFN: {
		char *dirpath = (char *)vector[0].data;
		char *outbuf  = NULL;
		u32  *outlen  = NULL;
		u32   buflen  = 0;

		u32 entries = 0;

		/* 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;

		/* Clear buffer */
		if (outbuf)
			memset(outbuf, 0, buflen);

		/* Read directory (LFN) */
		ret = FAT_ReadDirLfn(dirpath, outbuf, outlen, entries);

		break;
	}

	/** Delete object **/
	case IOCTL_FAT_DELETE: {
		char *path = (char *)vector[0].data;

		/* Delete file/directory */
		ret = FAT_Delete(path);

		break;
	}

	/** Delete directory **/
	case IOCTL_FAT_DELETEDIR: {
		char *dirpath = (char *)vector[0].data;

		/* Delete directory */
		ret = FAT_DeleteDir(dirpath);

		break;
	}

	/** Rename object **/
	case IOCTL_FAT_RENAME: {
		char *oldname = (char *)vector[0].data;
		char *newname = (char *)vector[1].data;

		/* Rename file/directory */
		ret = FAT_Rename(oldname, newname);

		break;
	}

	/** Get stats **/
	case IOCTL_FAT_STAT: {
		char *path  = (char *)vector[0].data;
		void *stats = vector[1].data;

		/* Get stats */
		ret = FAT_Stat(path, stats);

		break;
	}

	/** Get filesystem stats **/
	case IOCTL_FAT_VFSSTATS: {
		char *path  = (char *)vector[0].data;
		void *stats = vector[1].data;

		/* Get filesystem stats */
		ret = FAT_GetVfsStats(path, stats);

		break;
	}

	/** Get usage **/
	case IOCTL_FAT_GETUSAGE: {
		char *path   = (char *)vector[0].data;
		u32  *blocks =  (u32 *)vector[1].data;
		u32  *inodes =  (u32 *)vector[2].data;

		u64 size;

		/* Reset values */
		*blocks = 0;
		*inodes = 0;

		/* Get usage */
		ret = FAT_GetUsage(path, &size, inodes);

		/* Not a directory */
		if (ret == -ENOTDIR) {
			ret = 0;
			break;
		}

		/* Calculate blocks */
		*blocks = (size / 0x4000);

		break;
	}


	/** Mount SD card **/
	case IOCTL_FAT_MOUNTSD: {
		/* Initialize SDIO */
		ret = !__io_wiisd.startup();
		if (ret)
			break;

		/* Mount SD card */
		ret = !fatMountSimple("sd", &__io_wiisd);

		break;
	}

	/** Unmount SD card **/
	case IOCTL_FAT_UMOUNTSD: {
		/* Unmount SD card */
		fatUnmount("sd");

		/* Deinitialize SDIO */
		ret = !__io_wiisd.shutdown();

		break;
	}

	/** Mount USB card **/
	case IOCTL_FAT_MOUNTUSB: {
		/* Initialize USB */
		ret = !__io_usbstorage.startup();
		if (ret)
			break;

		/* Mount USB */
		ret = !fatMountSimple("usb", &__io_usbstorage);

		break;
	}

	/** Unmount USB card **/
	case IOCTL_FAT_UMOUNTUSB: {
		/* Unmount USB */
		fatUnmount("usb");

		/* Deinitialize USB */
		ret = !__io_usbstorage.shutdown();

		break;
	}

	default:
		break;
	}

	/* Flush cache */
	FlushVector(vector, inlen, iolen);

	return ret;
}