Skip to content

Commit

Permalink
Wrapper type for signals, refactor errors and signal numbers (#595)
Browse files Browse the repository at this point in the history
Co-authored-by: tompro <[email protected]>
  • Loading branch information
SuchAFuriousDeath and tompro committed Feb 24, 2024
1 parent 00f1155 commit e0ecd19
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 313 deletions.
323 changes: 122 additions & 201 deletions src/kernel/src/errno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,105 +4,126 @@ use std::num::NonZeroI32;
// This file contains errno used in a PS4 system. The value of each errno must be the same as the
// PS4.

pub const EPERM: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(1) };
pub const ENOENT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(2) };
pub const ESRCH: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(3) };
pub const EINTR: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(4) };
pub const EIO: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(5) };
pub const ENXIO: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(6) };
pub const E2BIG: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(7) };
pub const ENOEXEC: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(8) };
pub const EBADF: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(9) };
pub const ECHILD: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(10) };
pub const EDEADLK: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(11) };
pub const ENOMEM: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(12) };
pub const EACCES: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(13) };
pub const EFAULT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(14) };
pub const ENOTBLK: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(15) };
pub const EBUSY: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(16) };
pub const EEXIST: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(17) };
pub const EXDEV: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(18) };
pub const ENODEV: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(19) };
pub const ENOTDIR: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(20) };
pub const EISDIR: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(21) };
pub const EINVAL: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(22) };
pub const ENFILE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(23) };
pub const EMFILE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(24) };
pub const ENOTTY: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(25) };
pub const ETXTBSY: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(26) };
pub const EFBIG: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(27) };
pub const ENOSPC: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(28) };
pub const ESPIPE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(29) };
pub const EROFS: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(30) };
pub const EMLINK: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(31) };
pub const EPIPE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(32) };
pub const EDOM: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(33) };
pub const ERANGE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(34) };
pub const EAGAIN: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(35) };
pub const EINPROGRESS: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(36) };
pub const EALREADY: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(37) };
pub const ENOTSOCK: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(38) };
pub const EDESTADDRREQ: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(39) };
pub const EMSGSIZE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(40) };
pub const EPROTOTYPE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(41) };
pub const ENOPROTOOPT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(42) };
pub const EPROTONOSUPPORT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(43) };
pub const ESOCKTNOSUPPORT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(44) };
pub const EOPNOTSUPP: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(45) };
pub const EPFNOSUPPORT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(46) };
pub const EAFNOSUPPORT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(47) };
pub const EADDRINUSE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(48) };
pub const EADDRNOTAVAIL: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(49) };
pub const ENETDOWN: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(50) };
pub const ENETUNREACH: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(51) };
pub const ENETRESET: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(52) };
pub const ECONNABORTED: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(53) };
pub const ECONNRESET: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(54) };
pub const ENOBUFS: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(55) };
pub const EISCONN: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(56) };
pub const ENOTCONN: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(57) };
pub const ESHUTDOWN: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(58) };
pub const ETOOMANYREFS: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(59) };
pub const ETIMEDOUT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(60) };
pub const ECONNREFUSED: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(61) };
pub const ELOOP: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(62) };
pub const ENAMETOOLONG: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(63) };
pub const EHOSTDOWN: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(64) };
pub const EHOSTUNREACH: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(65) };
pub const ENOTEMPTY: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(66) };
pub const EPROCLIM: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(67) };
pub const EUSERS: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(68) };
pub const EDQUOT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(69) };
pub const ESTALE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(70) };
pub const EREMOTE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(71) };
pub const EBADRPC: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(72) };
pub const ERPCMISMATCH: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(73) };
pub const EPROGUNAVAIL: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(74) };
pub const EPROGMISMATCH: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(75) };
pub const EPROCUNAVAIL: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(76) };
pub const ENOLCK: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(77) };
pub const ENOSYS: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(78) };
pub const EFTYPE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(79) };
pub const EAUTH: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(80) };
pub const ENEEDAUTH: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(81) };
pub const EIDRM: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(82) };
pub const ENOMSG: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(83) };
pub const EOVERFLOW: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(84) };
pub const ECANCELED: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(85) };
pub const EILSEQ: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(86) };
pub const ENOATTR: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(87) };
pub const EDOOFUS: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(88) };
pub const EBADMSG: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(89) };
pub const EMULTIHOP: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(90) };
pub const ENOLINK: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(91) };
pub const EPROTO: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(92) };
pub const ENOTCAPABLE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(93) };
pub const ECAPMODE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(94) };
pub const ENOBLK: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(95) };
pub const EICV: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(96) };
pub const ENOPLAYGOENT: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(97) };
pub const EREVOKE: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(98) };
pub const ESDKVERSION: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(99) };
macro_rules! error_numbers {
($($name:ident($num:expr) => $desc:literal,)*) => {
$(
#[allow(dead_code)]
pub const $name: NonZeroI32 = unsafe {
assert!($num > 0);
NonZeroI32::new_unchecked($num)
};
)*

fn strerror_impl(num: NonZeroI32) -> &'static str {
match num {
$( $name => $desc, )*
_ => todo!("strerror {num}", num = num.get()),
}
}
};
}

error_numbers! {
EPERM(1) => "operation not permitted",
ENOENT(2) => "no such file or directory",
ESRCH(3) => "no such process",
EINTR(4) => "interrupted system call",
EIO(5) => "input/output error",
ENXIO(6) => "device not configured",
E2BIG(7) => "argument list too long",
ENOEXEC(8) => "exec format error",
EBADF(9) => "bad file descriptor",
ECHILD(10) => "no child processes",
EDEADLK(11) => "resource deadlock avoided",
ENOMEM(12) => "cannot allocate memory",
EACCES(13) => "permission denied",
EFAULT(14) => "bad address",
ENOTBLK(15) => "block device required",
EBUSY(16) => "device busy",
EEXIST(17) => "file exists",
EXDEV(18) => "cross-device link",
ENODEV(19) => "operation not supported by device",
ENOTDIR(20) => "not a directory",
EISDIR(21) => "is a directory",
EINVAL(22) => "invalid argument",
ENFILE(23) => "too many open files in system",
EMFILE(24) => "too many open files",
ENOTTY(25) => "inappropriate ioctl for device",
ETXTBSY(26) => "text file busy",
EFBIG(27) => "file too large",
ENOSPC(28) => "no space left on device",
ESPIPE(29) => "illegal seek",
EROFS(30) => "read-only filesystem",
EMLINK(31) => "too many links",
EPIPE(32) => "broken pipe",
EDOM(33) => "numerical argument out of domain",
ERANGE(34) => "result too large",
EAGAIN(35) => "resource temporarily unavailable",
EINPROGRESS(36) => "operation now in progress",
EALREADY(37) => "operation already in progress",
ENOTSOCK(38) => "socket operation on non-socket",
EDESTADDRREQ(39) => "destination address required",
EMSGSIZE(40) => "message too long",
EPROTOTYPE(41) => "protocol wrong type for socket",
ENOPROTOOPT(42) => "protocol not available",
EPROTONOSUPPORT(43) => "protocol not supported",
ESOCKTNOSUPPORT(44) => "socket type not supported",
EOPNOTSUPP(45) => "operation not supported",
EPFNOSUPPORT(46) => "protocol family not supported",
EAFNOSUPPORT(47) => "address family not supported by protocol",
EADDRINUSE(48) => "address already in use",
EADDRNOTAVAIL(49) => "can't assign requested address",
ENETDOWN(50) => "network is down",
ENETUNREACH(51) => "network is unreachable",
ENETRESET(52) => "network dropped connection on reset",
ECONNABORTED(53) => "software caused connection abort",
ECONNRESET(54) => "connection reset by peer",
ENOBUFS(55) => "no buffer space available",
EISCONN(56) => "socket is already connected",
ENOTCONN(57) => "socket is not connected",
ESHUTDOWN(58) => "can't send after socket shutdown",
ETOOMANYREFS(59) => "too many references: can't splice",
ETIMEDOUT(60) => "operation timed out",
ECONNREFUSED(61) => "connection refused",
ELOOP(62) => "too many levels of symbolic links",
ENAMETOOLONG(63) => "file name too long",
EHOSTDOWN(64) => "host is down",
EHOSTUNREACH(65) => "no route to host",
ENOTEMPTY(66) => "directory not empty",
EPROCLIM(67) => "too many processes",
EUSERS(68) => "too many users",
EDQUOT(69) => "disc quota exceeded",
ESTALE(70) => "stale NFS file handle",
EREMOTE(71) => "too many levels of remote in path",
EBADRPC(72) => "RPC struct is bad",
ERPCMISMATCH(73) => "RPC version wrong",
EPROGUNAVAIL(74) => "RPC prog. not avail.",
EPROGMISMATCH(75) => "program version wrong",
EPROCUNAVAIL(76) => "bad procedure for program",
ENOLCK(77) => "no locks available",
ENOSYS(78) => "function not implemented",
EFTYPE(79) => "inappropriate file type or format",
EAUTH(80) => "authentication error",
ENEEDAUTH(81) => "need authenticator",
EIDRM(82) => "identifier removed",
ENOMSG(83) => "no message of desired type",
EOVERFLOW(84) => "value too large to be stored in data type",
ECANCELED(85) => "operation canceled",
EILSEQ(86) => "illegal byte sequence",
ENOATTR(87) => "attribute not found",
EDOOFUS(88) => "function or API is being abused at run-time",
EBADMSG(89) => "bad message",
EMULTIHOP(90) => "multihop attempted",
ENOLINK(91) => "link has been severed",
EPROTO(92) => "protocol error",
ENOTCAPABLE(93) => "capabilities insufficient",
ECAPMODE(94) => "not permitted in capability mode",
ENOBLK(95) => "block not ready",
EICV(96) => "integrity check error",
ENOPLAYGOENT (97) => "file not found in PlayGo chunk definition file",
EREVOKE(98) => "file is revoked",
ESDKVERSION(99) => "SDK version of a binary file is invalid",
}

/// An object that is mappable to PS4 errno.
pub trait Errno: Error {
Expand All @@ -123,108 +144,8 @@ impl<T: Errno + 'static> From<T> for Box<dyn Errno> {

/// Get human readable text.
pub fn strerror(num: NonZeroI32) -> &'static str {
match num {
EPERM => "operation not permitted",
ENOENT => "no such file or directory",
ESRCH => "no such process",
EINTR => "interrupted system call",
EIO => "input/output error",
ENXIO => "device not configured",
E2BIG => "argument list too long",
ENOEXEC => "exec format error",
EBADF => "bad file descriptor",
ECHILD => "no child processes",
EDEADLK => "resource deadlock avoided",
ENOMEM => "cannot allocate memory",
EACCES => "permission denied",
EFAULT => "bad address",
ENOTBLK => "block device required",
EBUSY => "device busy",
EEXIST => "file exists",
EXDEV => "cross-device link",
ENODEV => "operation not supported by device",
ENOTDIR => "not a directory",
EISDIR => "is a directory",
EINVAL => "invalid argument",
ENFILE => "too many open files in system",
EMFILE => "too many open files",
ENOTTY => "inappropriate ioctl for device",
ETXTBSY => "text file busy",
EFBIG => "file too large",
ENOSPC => "no space left on device",
ESPIPE => "illegal seek",
EROFS => "read-only filesystem",
EMLINK => "too many links",
EPIPE => "broken pipe",
EDOM => "numerical argument out of domain",
ERANGE => "result too large",
EAGAIN => "resource temporarily unavailable",
EINPROGRESS => "operation now in progress",
EALREADY => "operation already in progress",
ENOTSOCK => "socket operation on non-socket",
EDESTADDRREQ => "destination address required",
EMSGSIZE => "message too long",
EPROTOTYPE => "protocol wrong type for socket",
ENOPROTOOPT => "protocol not available",
EPROTONOSUPPORT => "protocol not supported",
ESOCKTNOSUPPORT => "socket type not supported",
EOPNOTSUPP => "operation not supported",
EPFNOSUPPORT => "protocol family not supported",
EAFNOSUPPORT => "address family not supported by protocol family",
EADDRINUSE => "address already in use",
EADDRNOTAVAIL => "can't assign requested address",
ENETDOWN => "network is down",
ENETUNREACH => "network is unreachable",
ENETRESET => "network dropped connection on reset",
ECONNABORTED => "software caused connection abort",
ECONNRESET => "connection reset by peer",
ENOBUFS => "no buffer space available",
EISCONN => "socket is already connected",
ENOTCONN => "socket is not connected",
ESHUTDOWN => "can't send after socket shutdown",
ETOOMANYREFS => "too many references: can't splice",
ETIMEDOUT => "operation timed out",
ECONNREFUSED => "connection refused",
ELOOP => "too many levels of symbolic links",
ENAMETOOLONG => "file name too long",
EHOSTDOWN => "host is down",
EHOSTUNREACH => "no route to host",
ENOTEMPTY => "directory not empty",
EPROCLIM => "too many processes",
EUSERS => "too many users",
EDQUOT => "disc quota exceeded",
ESTALE => "stale NFS file handle",
EREMOTE => "too many levels of remote in path",
EBADRPC => "RPC struct is bad",
ERPCMISMATCH => "RPC version wrong",
EPROGUNAVAIL => "RPC prog. not avail",
EPROGMISMATCH => "program version wrong",
EPROCUNAVAIL => "bad procedure for program",
ENOLCK => "no locks available",
ENOSYS => "function not implemented",
EFTYPE => "inappropriate file type or format",
EAUTH => "authentication error",
ENEEDAUTH => "need authenticator",
EIDRM => "identifier removed",
ENOMSG => "no message of desired type",
EOVERFLOW => "value too large to be stored in data type",
ECANCELED => "operation canceled",
EILSEQ => "illegal byte sequence",
ENOATTR => "attribute not found",
EDOOFUS => "function or API is being abused at run-time",
EBADMSG => "bad message",
EMULTIHOP => "multi-hop attempted",
ENOLINK => "link has been severed",
EPROTO => "protocol error",
ENOTCAPABLE => "capabilities insufficient",
ECAPMODE => "not permitted in capability mode",
ENOBLK => "block not ready",
EICV => "integrity check error",
ENOPLAYGOENT => "file not found in PlayGo chunk definition file",
EREVOKE => "file is revoked",
ESDKVERSION => "SDK version of a binary file is invalid",
v => todo!("strerror {v}"),
}
// This function is generated inside the macro `error_numbers!`.
strerror_impl(num)
}

impl Errno for Infallible {
Expand Down
14 changes: 6 additions & 8 deletions src/kernel/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ use crate::errno::{EINVAL, ENAMETOOLONG, EPERM, ERANGE, ESRCH};
use crate::fs::Vnode;
use crate::idt::Idt;
use crate::info;
use crate::signal::SigChldFlags;
use crate::signal::{
strsignal, SignalAct, SignalFlags, SignalSet, SIGCHLD, SIGKILL, SIGSTOP, SIG_BLOCK, SIG_DFL,
SIG_IGN, SIG_MAXSIG, SIG_SETMASK, SIG_UNBLOCK,
SIG_IGN, SIG_SETMASK, SIG_UNBLOCK,
};
use crate::signal::{SigChldFlags, Signal};
use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls};
use crate::ucred::{AuthInfo, Gid, Privilege, Ucred, Uid};
use gmtx::{Gutex, GutexGroup, GutexWriteGuard};
Expand Down Expand Up @@ -281,15 +281,13 @@ impl VProc {

fn sys_sigaction(self: &Arc<Self>, _: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
// Get arguments.
let sig: i32 = i.args[0].try_into().unwrap();
let sig = {
let sig: i32 = i.args[0].try_into().unwrap();
Signal::new(sig).ok_or(SysErr::Raw(EINVAL))?
};
let act: *const SignalAct = i.args[1].into();
let oact: *mut SignalAct = i.args[2].into();

if sig == 0 || sig > SIG_MAXSIG {
return Err(SysErr::Raw(EINVAL));
}
let sig = NonZeroI32::new(sig).unwrap();

// Save the old actions.
let mut acts = self.sigacts.write();

Expand Down
Loading

0 comments on commit e0ecd19

Please sign in to comment.