#include #include #include "syscall.h" #include "sysdefs/ioctl.h" #include "errors.h" #include "path/path.h" #include "vfs/vfs.h" #include "kprintf.h" #include "proc/proc.h" #include "spinlock/spinlock.h" #define IOCTL_MP_MAX 0xff #define IOCTL_PATH_MAX VFS_PATH_MAX int32_t SYSCALL3(sys_ioctl, ioh1, cmd1, optsptr1) { uint64_t ioh = ioh1; uint64_t cmd = cmd1; int32_t ret = E_BADIO; switch (cmd) { case IOCTL_OPENF: { IOCtlOF *ioctlof = (IOCtlOF *)(void *)optsptr1; if (ioctlof == NULL) { ret = E_INVALIDARGUMENT; goto done; } char mp[IOCTL_MP_MAX]; char path[IOCTL_PATH_MAX]; if (ioctlof->path == NULL) { ret = E_INVALIDARGUMENT; goto done; } path_parse(ioctlof->path, mp, path); VfsObj *vobj = vfs_open(mp, path, ioctlof->flags); if (vobj == NULL) { ret = E_NOENTRY; goto done; } spinlock_acquire(&PROCS.spinlock); Proc *proc = PROCS.current; if (proc->vobjcnt < PROC_VFSHANDLES_MAX) { proc->vobjs[proc->vobjcnt++] = vobj; ret = proc->vobjcnt - 1; } else { ret = E_NOMEMORY; } spinlock_release(&PROCS.spinlock); } break; case IOCTL_CLOSEF: { spinlock_acquire(&PROCS.spinlock); Proc *proc = PROCS.current; VfsObj *vobj = proc->vobjs[ioh]; spinlock_release(&PROCS.spinlock); if (vobj == NULL) { ret = E_INVALIDARGUMENT; goto done; } vfs_close(vobj); ret = E_OK; } break; case IOCTL_WRITE: { IOCtlWF *ioctlwf = (IOCtlWF *)(void *)optsptr1; if (ioctlwf == NULL) { ret = E_INVALIDARGUMENT; goto done; } if (ioctlwf->buffer == NULL) { ret = E_INVALIDARGUMENT; goto done; } if (ioh >= PROC_VFSHANDLES_MAX) { ret = E_INVALIDARGUMENT; goto done; } spinlock_acquire(&PROCS.spinlock); Proc *proc = PROCS.current; VfsObj *vobj = proc->vobjs[ioh]; spinlock_release(&PROCS.spinlock); if (vobj == NULL) { ret = E_INVALIDARGUMENT; goto done; } ret = vobj->write(vobj, ioctlwf->buffer, ioctlwf->len, ioctlwf->off); } break; case IOCTL_READ: { IOCtlRF *ioctlrf = (IOCtlRF *)(void *)optsptr1; if (ioctlrf == NULL) { ret = E_INVALIDARGUMENT; goto done; } if (ioctlrf->buffer == NULL) { ret = E_INVALIDARGUMENT; goto done; } if (ioh >= PROC_VFSHANDLES_MAX) { ret = E_INVALIDARGUMENT; goto done; } spinlock_acquire(&PROCS.spinlock); Proc *proc = PROCS.current; VfsObj *vobj = proc->vobjs[ioh]; spinlock_release(&PROCS.spinlock); if (vobj == NULL) { ret = E_INVALIDARGUMENT; goto done; } ret = vobj->read(vobj, ioctlrf->buffer, ioctlrf->len, ioctlrf->off); } break; default: { ret = E_INVALIDARGUMENT; goto done; } break; } done: return ret; }