#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 SYSCALL5(sys_ioctl, ioh1, cmd1, arg1, arg2, arg3) { uint64_t ioh = ioh1; uint64_t cmd = cmd1; int32_t ret = E_BADIO; switch (cmd) { case IOCTL_OPENF: { const char *opath = (const char *)arg1; uint64_t oflags = arg2; if (opath == NULL) { ret = E_INVALIDARGUMENT; goto done; } char mp[IOCTL_MP_MAX]; char path[IOCTL_PATH_MAX]; path_parse(opath, mp, path); VfsObj *vobj = vfs_open(mp, path, oflags); if (vobj == NULL) { ret = E_NOENTRY; goto done; } spinlock_acquire(&PROCS.spinlock); Proc *proc = PROCS.current; spinlock_release(&PROCS.spinlock); if (proc->vobjcnt < PROC_VFSHANDLES_MAX) { proc->vobjs[proc->vobjcnt++] = vobj; ret = proc->vobjcnt - 1; } else { ret = E_NOMEMORY; } } break; case IOCTL_CLOSEF: { if (ioh >= PROC_VFSHANDLES_MAX) { ret = E_INVALIDARGUMENT; goto done; } spinlock_acquire(&PROCS.spinlock); Proc *proc = PROCS.current; spinlock_release(&PROCS.spinlock); VfsObj *vobj = proc->vobjs[ioh]; if (vobj == NULL) { ret = E_INVALIDARGUMENT; goto done; } size_t i = 0; for (; i < PROC_VFSHANDLES_MAX; i++) { if (proc->vobjs[i] == vobj) { break; } } vfs_close(vobj); proc->vobjs[i] = NULL; ret = E_OK; } break; case IOCTL_WRITE: { const uint8_t *const buffer = (const uint8_t *const)arg1; size_t len = (size_t)arg2; size_t off = (size_t)arg3; if (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; spinlock_release(&PROCS.spinlock); VfsObj *vobj = proc->vobjs[ioh]; if (vobj == NULL) { ret = E_INVALIDARGUMENT; goto done; } ret = vobj->write(vobj, buffer, len, off); } break; case IOCTL_READ: { uint8_t *const buffer = (uint8_t *const)arg1; size_t len = (size_t)arg2; size_t off = (size_t)arg3; if (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; spinlock_release(&PROCS.spinlock); VfsObj *vobj = proc->vobjs[ioh]; if (vobj == NULL) { ret = E_INVALIDARGUMENT; goto done; } ret = vobj->read(vobj, buffer, len, off); } break; case IOCTL_STAT: { const char *opath = (const char *)arg2; if (opath == NULL) { ret = E_INVALIDARGUMENT; goto done; } IoctlStat *iostat = (IoctlStat *)arg1; if (iostat == NULL) { ret = E_INVALIDARGUMENT; goto done; } char mp[IOCTL_MP_MAX]; char path[IOCTL_PATH_MAX]; path_parse(opath, mp, path); VfsStat stat1; ret = vfs_stat(mp, path, &stat1); if (ret != E_OK) { goto done; } iostat->size = stat1.size; iostat->type = stat1.type; } break; case IOCTL_FETCHDIRENT: { const char *opath = (const char *)arg1; if (opath == NULL) { ret = E_INVALIDARGUMENT; goto done; } IoctlDirent *direntbuf = (IoctlDirent *)arg2; if (direntbuf == NULL) { ret = E_INVALIDARGUMENT; goto done; } size_t idx = (size_t)arg3; char mp[IOCTL_MP_MAX]; char path[IOCTL_PATH_MAX]; path_parse(opath, mp, path); ret = vfs_fetchdirent(mp, path, direntbuf, idx); } break; default: { ret = E_INVALIDARGUMENT; goto done; } break; } done: return ret; }