#pragma once /// \file syscalls/helpers.h /// Utility functions for use in syscall handler implementations #include #include "capabilities.h" #include "objects/kobject.h" #include "objects/process.h" namespace syscalls { template T * construct_handle(j6_handle_t *id, Args... args) { T *o = new T {args...}; *id = g_cap_table.create(o, T::creation_caps); obj::process &p = obj::process::current(); p.add_handle(*id); return o; } template j6_status_t get_handle(j6_handle_t id, j6_cap_t caps, T *&object) { if (id == j6_handle_invalid) { object = nullptr; return j6_status_ok; } capability *capdata = g_cap_table.retain(id); if (!capdata || capdata->type != T::type) return j6_err_invalid_arg; obj::process &p = obj::process::current(); if (!p.has_handle(id) || (capdata->caps & caps) != caps) return j6_err_denied; object = static_cast(capdata->object); return j6_status_ok; } template inline j6_status_t get_handle(j6_handle_t *id, j6_cap_t caps, T *&object) { return get_handle(*id, caps, object); } template <> inline j6_status_t get_handle(j6_handle_t id, j6_cap_t caps, obj::kobject *&object) { if (id == j6_handle_invalid) { object = nullptr; return j6_status_ok; } capability *capdata = g_cap_table.retain(id); if (!capdata) return j6_err_invalid_arg; obj::process &p = obj::process::current(); if (!p.has_handle(id) || (capdata->caps & caps) != caps) return j6_err_denied; object = capdata->object; return j6_status_ok; } inline void release_handle(j6_handle_t id) { g_cap_table.release(id); } inline void release_handle(j6_handle_t *id) { g_cap_table.release(*id); } } // namespace syscalls