#include <aux/compiler.h>
#include <device/device.h>
#include <fs/path.h>
#include <fs/vfs.h>
#include <libk/assert.h>
#include <libk/fieldlengthof.h>
#include <libk/std.h>
#include <libk/string.h>
#include <limine/requests.h>
#include <mm/pmm.h>
#include <path_defs.h>
#include <proc/mail.h>
#include <proc/mutex.h>
#include <proc/proc.h>
#include <proc/procgroup.h>
#include <proc/resource.h>
#include <status.h>
#include <sync/spin_lock.h>
#include <sys/debug.h>
#include <sys/mm.h>
#include <sys/proc.h>
#include <syscall/syscall.h>
#include <syscall_defs.h>
#include <write_file.h>

#define DEFINE_SYSCALL(name)                                                                       \
  uintptr_t name (struct proc* UNUSED proc, void* UNUSED regs, struct reschedule_ctx* UNUSED rctx, \
                  uintptr_t UNUSED a1, uintptr_t UNUSED a2, uintptr_t UNUSED a3,                   \
                  uintptr_t UNUSED a4, uintptr_t UNUSED a5, uintptr_t UNUSED a6)

#define SYSRESULT(x) ((uintptr_t)(x))

static void* sys_get_user_buffer (struct proc* proc, uintptr_t uvaddr, size_t size) {
  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  spin_lock (&proc->procgroup->lock);

  if (!mm_validate_buffer (&proc->procgroup->pd, (uintptr_t)uvaddr, size)) {
    spin_unlock (&proc->procgroup->lock);
    return NULL;
  }

  uintptr_t out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr);

  spin_unlock (&proc->procgroup->lock);

  uintptr_t out_kvaddr = (uintptr_t)hhdm->offset + out_paddr;

  return (void*)out_kvaddr;
}

/* int quit (void) */
DEFINE_SYSCALL (sys_quit) {
  proc_kill (proc, rctx);

  return SYSRESULT (ST_OK);
}

/* int test (void) */
DEFINE_SYSCALL (sys_test) {
  char c = (char)a1;
  DEBUG ("test syscall from %d! %c\n", proc->pid, c);
  return SYSRESULT (ST_OK);
}

/* int map (uintptr_t vaddr, size_t pages, uint32_t flags) */
DEFINE_SYSCALL (sys_map) {
  uintptr_t vaddr = a1;
  size_t pages = (size_t)a2;
  uint32_t flags = (uint32_t)a3;

  if (vaddr % PAGE_SIZE != 0)
    return SYSRESULT (-ST_UNALIGNED);

  return SYSRESULT (procgroup_map (proc->procgroup, vaddr, pages, flags, NULL));
}

/* int unmap (uintptr_t vaddr, size_t pages) */
DEFINE_SYSCALL (sys_unmap) {
  uintptr_t vaddr = a1;
  size_t pages = (size_t)a2;

  if (vaddr % PAGE_SIZE != 0)
    return SYSRESULT (-ST_UNALIGNED);

  return SYSRESULT (procgroup_unmap (proc->procgroup, vaddr, pages));
}

/* int clone (uintptr_t vstack_top, void* entry, void* argument_ptr) */
DEFINE_SYSCALL (sys_clone) {
  uintptr_t vstack_top = a1;
  uintptr_t entry = a2;
  uintptr_t argument_ptr = a3;

  struct proc* new = proc_clone (proc, vstack_top, entry, argument_ptr);

  if (new == NULL) {
    return SYSRESULT (-ST_OOM_ERROR);
  }

  int pid = new->pid;

  proc_register (new, NULL, rctx);

  return SYSRESULT (pid);
}

/* void* argument_ptr (void) */
DEFINE_SYSCALL (sys_argument_ptr) {
  spin_lock (&proc->lock);
  uintptr_t p = proc->uvaddr_argument;
  spin_unlock (&proc->lock);

  return p;
}

/* int sched (void) */
DEFINE_SYSCALL (sys_sched) {
  rctx_insert_cpu (rctx, thiscpu);
  return SYSRESULT (ST_OK);
}

/* int mutex_create (void) */
DEFINE_SYSCALL (sys_mutex_create) {
  struct proc_resource* mutex_resource = proc_create_resource_mutex (proc->procgroup);

  if (mutex_resource == NULL)
    return SYSRESULT (-ST_OOM_ERROR);

  spin_lock (&mutex_resource->lock);
  int rid = mutex_resource->rid;
  spin_unlock (&mutex_resource->lock);

  return SYSRESULT (rid);
}

/* int mutex_delete (int mutex_rid) */
DEFINE_SYSCALL (sys_mutex_delete) {
  int mutex_rid = (int)a1;

  struct proc_resource* mutex_resource = proc_find_resource (proc->procgroup, mutex_rid);

  if (mutex_resource == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  proc_delete_resource (proc->procgroup, mutex_resource, rctx);

  return SYSRESULT (ST_OK);
}

/* int mutex_lock (int mutex_rid) */
DEFINE_SYSCALL (sys_mutex_lock) {
  int mutex_rid = (int)a1;

  struct proc_resource* mutex_resource = proc_find_resource (proc->procgroup, mutex_rid);

  if (mutex_resource == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  proc_mutex_lock (proc, &mutex_resource->u.mutex, rctx);

  return SYSRESULT (ST_OK);
}

/* int mutex_unlock (int mutex_rid) */
DEFINE_SYSCALL (sys_mutex_unlock) {
  int mutex_rid = (int)a1;

  struct proc_resource* mutex_resource = proc_find_resource (proc->procgroup, mutex_rid);

  if (mutex_resource == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  proc_mutex_unlock (proc, &mutex_resource->u.mutex, rctx);

  return SYSRESULT (ST_OK);
}

/* int mail_send (int pgid, void* mesg, size_t mesg_size) */
DEFINE_SYSCALL (sys_mail_send) {
  int pgid = (int)a1;
  uintptr_t uvaddr_mesg = a2;
  size_t mesg_size = (size_t)a3;

  void* mesg = sys_get_user_buffer (proc, uvaddr_mesg, mesg_size);

  if (mesg == NULL)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  struct procgroup* procgroup = procgroup_find (pgid);

  if (procgroup == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  struct proc_resource* mail_resource = proc_find_resource (procgroup, 0);

  if (mail_resource == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  proc_mail_send (proc, &mail_resource->u.mail, rctx, mesg, mesg_size);

  return SYSRESULT (ST_OK);
}

/* int mail_receive (void* recv_mesg, size_t mesg_size) */
DEFINE_SYSCALL (sys_mail_receive) {
  uintptr_t uvaddr_mesg = a1;
  size_t mesg_size = (size_t)a2;

  void* mesg = sys_get_user_buffer (proc, uvaddr_mesg, mesg_size);

  if (mesg == NULL)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  struct proc_resource* mail_resource = proc_find_resource (proc->procgroup, 0);

  if (mail_resource == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  proc_mail_receive (proc, &mail_resource->u.mail, rctx, mesg, mesg_size);

  return SYSRESULT (ST_OK);
}

/* int device_do (int device_id, int cmd, void* a1, void* a2, void* a3, void* a4) */
DEFINE_SYSCALL (sys_device_do) {
  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t uvaddr_key = a1;
  int cmd = (int)a2;
  uintptr_t ua1 = a3, ka1 = 0;
  uintptr_t ua2 = a4, ka2 = 0;
  uintptr_t ua3 = a5, ka3 = 0;
  uintptr_t ua4 = a6, ka4 = 0;
  uintptr_t out_paddr;

  if (!(cmd >= 0 && cmd < (int)fieldlengthof (struct device, ops)))
    return SYSRESULT (-ST_BAD_DEVICE_OP);

  spin_lock (&proc->procgroup->lock);

  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_key);

  if (out_paddr == 0) {
    spin_unlock (&proc->procgroup->lock);
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);
  }

  const char* key = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  out_paddr = mm_v2p (&proc->procgroup->pd, ua1);
  if (out_paddr != 0)
    ka1 = (uintptr_t)hhdm->offset + out_paddr;

  out_paddr = mm_v2p (&proc->procgroup->pd, ua2);
  if (out_paddr != 0)
    ka2 = (uintptr_t)hhdm->offset + out_paddr;

  out_paddr = mm_v2p (&proc->procgroup->pd, ua3);
  if (out_paddr != 0)
    ka3 = (uintptr_t)hhdm->offset + out_paddr;

  out_paddr = mm_v2p (&proc->procgroup->pd, ua4);
  if (out_paddr != 0)
    ka4 = (uintptr_t)hhdm->offset + out_paddr;

  spin_unlock (&proc->procgroup->lock);

  struct device* device = device_find (key);

  if (device == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  spin_lock (&device->lock);

  if (device->ops[cmd] == NULL) {
    spin_unlock (&device->lock);
    return SYSRESULT (-ST_NOT_FOUND);
  }

  int ret = device_op (device, cmd, proc, rctx, ka1, ka2, ka3, ka4);

  spin_unlock (&device->lock);

  return SYSRESULT (ret);
}

/* int exec (char* volume, char* path) */
DEFINE_SYSCALL (sys_exec) {
  uintptr_t uvaddr_volume = a1;
  uintptr_t uvaddr_path = a2;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_volume);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* volume = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  struct proc* new = proc_from_file (proc, volume, path, rctx);

  if (new == NULL)
    return SYSRESULT (-ST_EXEC_ERROR);

  int pid = new->pid;
  new->exec_pid = proc->pid;

  proc_register (new, NULL, rctx);

  return SYSRESULT (pid);
}

/* int volume_open (char* volume) */
DEFINE_SYSCALL (sys_volume_open) {
  uintptr_t uvaddr_volume = a1;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_volume);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* volume = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  int ret = vfs_volume_open (proc, volume, rctx);

  if (ret < 0)
    return SYSRESULT (ret);

  spin_lock (&proc->lock);
  strncpy (proc->cwv, volume, VOLUME_MAX);
  spin_unlock (&proc->lock);

  return SYSRESULT (ST_OK);
}

/* int volume_close (void) */
DEFINE_SYSCALL (sys_volume_close) {
  spin_lock (&proc->lock);

  int ret = vfs_volume_close (proc, proc->cwv, rctx);

  if (ret == ST_OK) {
    memset (proc->cwv, 0, sizeof (proc->cwv));
  }

  spin_unlock (&proc->lock);

  return SYSRESULT (ret);
}

/* int read_file (char* path, size_t off, uint8_t* buffer, size_t size) */
DEFINE_SYSCALL (sys_read_file) {
  uintptr_t uvaddr_path = a1;
  size_t off = (size_t)a2;
  uintptr_t uvaddr_buffer = a3;
  size_t size = (size_t)a4;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  uint8_t* buffer = sys_get_user_buffer (proc, uvaddr_buffer, size);

  if (buffer == NULL)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  spin_lock (&proc->lock);
  int ret = vfs_read_file (proc, proc->cwv, path, buffer, off, size);
  spin_unlock (&proc->lock);

  return SYSRESULT (ret);
}

/* int describe (char* path, struct desc* desc) */
DEFINE_SYSCALL (sys_describe) {
  uintptr_t uvaddr_path = a1;
  uintptr_t uvaddr_desc = a2;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  struct desc* desc = sys_get_user_buffer (proc, uvaddr_desc, sizeof (struct desc));

  if (desc == NULL)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  spin_lock (&proc->lock);
  int ret = vfs_describe (proc, proc->cwv, path, desc);
  spin_unlock (&proc->lock);

  return SYSRESULT (ret);
}

/* int get_procgroup (int pid) */
DEFINE_SYSCALL (sys_get_procgroup) {
  int pid = (int)a1;

  struct proc* target_proc = proc_find_pid (pid);

  if (target_proc == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  spin_lock (&target_proc->lock);

  if (target_proc->state == PROC_DEAD) {
    spin_unlock (&target_proc->lock);
    return SYSRESULT (-ST_NOT_FOUND);
  }

  int pgid = target_proc->procgroup->pgid;

  spin_unlock (&target_proc->lock);

  return SYSRESULT (pgid);
}

/* int read_dir_entry (char* path, struct dir_entry* entry, size_t entry_num) */
DEFINE_SYSCALL (sys_read_dir_entry) {
  uintptr_t uvaddr_path = a1;
  uintptr_t uvaddr_entry = a2;
  size_t entry_num = (size_t)a3;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  struct dir_entry* entry = sys_get_user_buffer (proc, uvaddr_entry, sizeof (struct dir_entry));

  if (entry == NULL)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  spin_lock (&proc->lock);
  int ret = vfs_read_dir_entry (proc, proc->cwv, path, entry, entry_num);
  spin_unlock (&proc->lock);

  return SYSRESULT (ret);
}

/* int create_file (char* path) */
DEFINE_SYSCALL (sys_create_file) {
  uintptr_t uvaddr_path = a1;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  spin_lock (&proc->lock);
  int ret = vfs_create_file (proc, proc->cwv, path);
  spin_unlock (&proc->lock);

  return SYSRESULT (ret);
}

/* int write_file (char* path, size_t off, uint8_t* buffer, size_t size, uint32_t flags) */
DEFINE_SYSCALL (sys_write_file) {
  uintptr_t uvaddr_path = a1;
  size_t off = (size_t)a2;
  uintptr_t uvaddr_buffer = a3;
  size_t size = (size_t)a4;
  uint32_t flags = (uint32_t)a5;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  uint8_t* buffer = sys_get_user_buffer (proc, uvaddr_buffer, size);

  if (buffer == NULL)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  spin_lock (&proc->lock);
  int ret = vfs_write_file (proc, proc->cwv, path, buffer, off, size, flags);
  spin_unlock (&proc->lock);

  return SYSRESULT (ret);
}

/* int get_exec_pid (void) */
DEFINE_SYSCALL (sys_get_exec_pid) {
  spin_lock (&proc->lock);
  int exec_pid = proc->exec_pid;
  spin_unlock (&proc->lock);

  return SYSRESULT (exec_pid);
}

/* wait_for_pid (int pid) */
DEFINE_SYSCALL (sys_wait_for_pid) {
  int pid = (int)a1;

  struct proc* wait_proc = proc_find_pid (pid);

  if (wait_proc == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  spin_lock (&wait_proc->lock);

  if (wait_proc->state == PROC_DEAD) {
    spin_unlock (&wait_proc->lock);
    return SYSRESULT (-ST_NOT_FOUND);
  }

  spin_unlock (&wait_proc->lock);

  proc_wait_for (proc, rctx, wait_proc);

  return SYSRESULT (ST_OK);
}

/* int kill (int pid) */

DEFINE_SYSCALL (sys_kill) {
  int pid = (int)a1;

  struct proc* target_proc = proc_find_pid (pid);

  if (target_proc == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  spin_lock (&target_proc->lock);

  if (target_proc->state == PROC_DEAD) {
    spin_unlock (&target_proc->lock);
    return SYSRESULT (-ST_NOT_FOUND);
  }

  spin_unlock (&target_proc->lock);

  proc_kill (target_proc, rctx);

  return ST_OK;
}

/* int create_dir (char* path) */
DEFINE_SYSCALL (sys_create_dir) {
  uintptr_t uvaddr_path = a1;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  spin_lock (&proc->lock);
  int ret = vfs_create_dir (proc, proc->cwv, path);
  spin_unlock (&proc->lock);

  return SYSRESULT (ret);
}

/* int remove (char* path) */
DEFINE_SYSCALL (sys_remove) {
  uintptr_t uvaddr_path = a1;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);
  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path);
  spin_unlock (&proc->procgroup->lock);

  if (out_paddr == 0)
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);

  const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  spin_lock (&proc->lock);
  int ret = vfs_remove (proc, proc->cwv, path);
  spin_unlock (&proc->lock);

  return SYSRESULT (ret);
}

/* int create_volume (char* key, int fs_type, char* device_key) */
DEFINE_SYSCALL (sys_create_volume) {
  uintptr_t uvaddr_key = a1;
  int type = (int)a2;
  uintptr_t uvaddr_device_key = a3;

  struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

  uintptr_t out_paddr;

  spin_lock (&proc->procgroup->lock);

  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_key);

  if (out_paddr == 0) {
    spin_unlock (&proc->procgroup->lock);
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);
  }

  const char* key = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_device_key);

  if (out_paddr == 0) {
    spin_unlock (&proc->procgroup->lock);
    return SYSRESULT (-ST_BAD_ADDRESS_SPACE);
  }

  const char* device_key = (const char*)((uintptr_t)hhdm->offset + out_paddr);

  spin_unlock (&proc->procgroup->lock);

  struct device* device = device_find (device_key);

  if (device == NULL)
    return SYSRESULT (-ST_NOT_FOUND);

  return SYSRESULT (vfs_create_volume (key, type, device, false));
}

static syscall_handler_func_t handler_table[] = {
    [SYS_QUIT] = &sys_quit,
    [SYS_TEST] = &sys_test,
    [SYS_MAP] = &sys_map,
    [SYS_UNMAP] = &sys_unmap,
    [SYS_CLONE] = &sys_clone,
    [SYS_ARGUMENT_PTR] = &sys_argument_ptr,
    [SYS_SCHED] = &sys_sched,
    [SYS_MUTEX_CREATE] = &sys_mutex_create,
    [SYS_MUTEX_DELETE] = &sys_mutex_delete,
    [SYS_MUTEX_LOCK] = &sys_mutex_lock,
    [SYS_MUTEX_UNLOCK] = &sys_mutex_unlock,
    [SYS_DEVICE_DO] = &sys_device_do,
    [SYS_EXEC] = &sys_exec,
    [SYS_VOLUME_OPEN] = &sys_volume_open,
    [SYS_VOLUME_CLOSE] = &sys_volume_close,
    [SYS_READ_FILE] = &sys_read_file,
    [SYS_DESCRIBE] = &sys_describe,
    [SYS_MAIL_SEND] = &sys_mail_send,
    [SYS_MAIL_RECEIVE] = &sys_mail_receive,
    [SYS_GET_PROCGROUP] = &sys_get_procgroup,
    [SYS_GET_EXEC_PID] = &sys_get_exec_pid,
    [SYS_READ_DIR_ENTRY] = &sys_read_dir_entry,
    [SYS_CREATE_FILE] = &sys_create_file,
    [SYS_WRITE_FILE] = &sys_write_file,
    [SYS_WAIT_FOR_PID] = &sys_wait_for_pid,
    [SYS_KILL] = &sys_kill,
    [SYS_CREATE_DIR] = &sys_create_dir,
    [SYS_REMOVE] = &sys_remove,
    [SYS_CREATE_VOLUME] = &sys_create_volume,
};

syscall_handler_func_t syscall_find_handler (int syscall_num) {
  if (!(syscall_num >= 0 &&
        syscall_num < (int)(sizeof (handler_table) / sizeof (handler_table[0])))) {
    return NULL;
  }

  return handler_table[syscall_num];
}
