diff --git a/src/call.rs b/src/call.rs new file mode 100644 index 0000000..65ce8e3 --- /dev/null +++ b/src/call.rs @@ -0,0 +1,222 @@ +use super::arch::*; +use super::data::{Stat, TimeSpec}; +use super::error::Result; +use super::number::*; + +use core::mem; + +/// Set the end of the process's heap +/// +/// When `addr` is `0`, this function will return the current break. +/// +/// When `addr` is nonzero, this function will attempt to set the end of the process's +/// heap to `addr` and return the new program break. The new program break should be +/// checked by the allocator, it may not be exactly `addr`, as it may be aligned to a page +/// boundary. +/// +/// On error, `Err(ENOMEM)` will be returned indicating that no memory is available +pub unsafe fn brk(addr: usize) -> Result { + syscall1(SYS_BRK, addr) +} + +/// Change the process's working directory +/// +/// This function will attempt to set the process's working directory to `path`, which can be +/// either a relative, scheme relative, or absolute path. +/// +/// On success, `Ok(0)` will be returned. On error, one of the following errors will be returned. +/// +/// # Errors +/// +/// * `EACCES` - permission is denied for one of the components of `path`, or `path` +/// * `EFAULT` - `path` does not point to the process's addressible memory +/// * `EIO` - an I/O error occured +/// * `ENOENT` - `path` does not exit +/// * `ENOTDIR` - `path` is not a directory +pub fn chdir(path: &str) -> Result { + unsafe { syscall2(SYS_CHDIR, path.as_ptr() as usize, path.len()) } +} + +pub unsafe fn clone(flags: usize) -> Result { + syscall1_clobber(SYS_CLONE, flags) +} + +pub fn close(fd: usize) -> Result { + unsafe { syscall1(SYS_CLOSE, fd) } +} + +pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result { + unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) } +} + +pub fn dup(fd: usize, buf: &[u8]) -> Result { + unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) } +} + +pub fn execve(path: &str, args: &[[usize; 2]]) -> Result { + unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(), args.as_ptr() as usize, args.len()) } +} + +pub fn exit(status: usize) -> Result { + unsafe { syscall1(SYS_EXIT, status) } +} + +pub fn fevent(fd: usize, flags: usize) -> Result { + unsafe { syscall2(SYS_FEVENT, fd, flags) } +} + +pub unsafe fn fmap(fd: usize, offset: usize, size: usize) -> Result { + syscall3(SYS_FMAP, fd, offset, size) +} + +pub unsafe fn funmap(addr: usize) -> Result { + syscall1(SYS_FUNMAP, addr) +} + +pub fn fpath(fd: usize, buf: &mut [u8]) -> Result { + unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) } +} + +pub fn fstat(fd: usize, stat: &mut Stat) -> Result { + unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::()) } +} + +pub fn fsync(fd: usize) -> Result { + unsafe { syscall1(SYS_FSYNC, fd) } +} + +pub fn ftruncate(fd: usize, len: usize) -> Result { + unsafe { syscall2(SYS_FTRUNCATE, fd, len) } +} + +pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) -> Result { + syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize) +} + +pub fn getcwd(buf: &mut [u8]) -> Result { + unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) } +} + +pub fn getegid() -> Result { + unsafe { syscall0(SYS_GETEGID) } +} + +pub fn geteuid() -> Result { + unsafe { syscall0(SYS_GETEUID) } +} + +pub fn getgid() -> Result { + unsafe { syscall0(SYS_GETGID) } +} + +pub fn getpid() -> Result { + unsafe { syscall0(SYS_GETPID) } +} + +pub fn getuid() -> Result { + unsafe { syscall0(SYS_GETUID) } +} + +pub unsafe fn iopl(level: usize) -> Result { + syscall1(SYS_IOPL, level) +} + +pub fn kill(pid: usize, sig: usize) -> Result { + unsafe { syscall2(SYS_KILL, pid, sig) } +} + +pub unsafe fn link(old: *const u8, new: *const u8) -> Result { + syscall2(SYS_LINK, old as usize, new as usize) +} + +pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result { + unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) } +} + +pub fn mkdir(path: &str, mode: u16) -> Result { + unsafe { syscall3(SYS_MKDIR, path.as_ptr() as usize, path.len(), mode as usize) } +} + +pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result { + unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize, rem as *mut TimeSpec as usize) } +} + +pub fn open(path: &str, flags: usize) -> Result { + unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) } +} + +pub unsafe fn physalloc(size: usize) -> Result { + syscall1(SYS_PHYSALLOC, size) +} + +pub unsafe fn physfree(physical_address: usize, size: usize) -> Result { + syscall2(SYS_PHYSFREE, physical_address, size) +} + +pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result { + syscall3(SYS_PHYSMAP, physical_address, size, flags) +} + +pub unsafe fn physunmap(virtual_address: usize) -> Result { + syscall1(SYS_PHYSUNMAP, virtual_address) +} + +pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result { + unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) } +} + +pub fn read(fd: usize, buf: &mut [u8]) -> Result { + unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) } +} + +pub fn rmdir(path: &str) -> Result { + unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) } +} + +pub fn setgid(gid: usize) -> Result { + unsafe { syscall1(SYS_SETGID, gid) } +} + +pub fn setuid(uid: usize) -> Result { + unsafe { syscall1(SYS_SETUID, uid) } +} + +pub fn unlink(path: &str) -> Result { + unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) } +} + +pub unsafe fn virttophys(virtual_address: usize) -> Result { + syscall1(SYS_VIRTTOPHYS, virtual_address) +} + +/// Check if a child process has exited or received a signal +/// +/// The kernel +pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result { + unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) } +} + +/// Write a buffer to a file descriptor +/// +/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning +/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which +/// were written. +/// +/// # Errors +/// +/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block +/// * `EBADF` - the file descriptor is not valid or is not open for writing +/// * `EFAULT` - `buf` does not point to the process's addressible memory +/// * `EIO` - an I/O error occured +/// * `ENOSPC` - the device containing the file descriptor has no room for data +/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed +pub fn write(fd: usize, buf: &[u8]) -> Result { + unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) } +} + +/// Yield the process's time slice to the kernel +/// +/// This function will return Ok(0) on success +pub fn sched_yield() -> Result { + unsafe { syscall0(SYS_YIELD) } +} diff --git a/src/lib.rs b/src/lib.rs index a025a7d..5139f07 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,14 +2,13 @@ #![no_std] pub use self::arch::*; +pub use self::call::*; pub use self::data::*; pub use self::error::*; pub use self::flag::*; pub use self::number::*; pub use self::scheme::*; -use core::mem; - #[cfg(target_arch = "x86")] #[path="x86.rs"] mod arch; @@ -18,184 +17,20 @@ mod arch; #[path="x86_64.rs"] mod arch; +/// Function definitions +pub mod call; + +/// Complex structures that are used for some system calls pub mod data; +/// All errors that can be generated by a system call pub mod error; +/// Flags used as an argument to many system calls pub mod flag; +/// Call numbers used by each system call pub mod number; +/// A trait useful for scheme handlers pub mod scheme; - -pub unsafe fn brk(addr: usize) -> Result { - syscall1(SYS_BRK, addr) -} - -pub fn chdir(path: &str) -> Result { - unsafe { syscall2(SYS_CHDIR, path.as_ptr() as usize, path.len()) } -} - -pub unsafe fn clone(flags: usize) -> Result { - syscall1_clobber(SYS_CLONE, flags) -} - -pub fn close(fd: usize) -> Result { - unsafe { syscall1(SYS_CLOSE, fd) } -} - -pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result { - unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) } -} - -pub fn dup(fd: usize, buf: &[u8]) -> Result { - unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) } -} - -pub fn execve(path: &str, args: &[[usize; 2]]) -> Result { - unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(), args.as_ptr() as usize, args.len()) } -} - -pub fn exit(status: usize) -> Result { - unsafe { syscall1(SYS_EXIT, status) } -} - -pub fn fevent(fd: usize, flags: usize) -> Result { - unsafe { syscall2(SYS_FEVENT, fd, flags) } -} - -pub unsafe fn fmap(fd: usize, offset: usize, size: usize) -> Result { - syscall3(SYS_FMAP, fd, offset, size) -} - -pub unsafe fn funmap(addr: usize) -> Result { - syscall1(SYS_FUNMAP, addr) -} - -pub fn fpath(fd: usize, buf: &mut [u8]) -> Result { - unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) } -} - -pub fn fstat(fd: usize, stat: &mut Stat) -> Result { - unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::()) } -} - -pub fn fsync(fd: usize) -> Result { - unsafe { syscall1(SYS_FSYNC, fd) } -} - -pub fn ftruncate(fd: usize, len: usize) -> Result { - unsafe { syscall2(SYS_FTRUNCATE, fd, len) } -} - -pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) -> Result { - syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize) -} - -pub fn getcwd(buf: &mut [u8]) -> Result { - unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) } -} - -pub fn getegid() -> Result { - unsafe { syscall0(SYS_GETEGID) } -} - -pub fn geteuid() -> Result { - unsafe { syscall0(SYS_GETEUID) } -} - -pub fn getgid() -> Result { - unsafe { syscall0(SYS_GETGID) } -} - -pub fn getpid() -> Result { - unsafe { syscall0(SYS_GETPID) } -} - -pub fn getuid() -> Result { - unsafe { syscall0(SYS_GETUID) } -} - -pub unsafe fn iopl(level: usize) -> Result { - syscall1(SYS_IOPL, level) -} - -pub fn kill(pid: usize, sig: usize) -> Result { - unsafe { syscall2(SYS_KILL, pid, sig) } -} - -pub unsafe fn link(old: *const u8, new: *const u8) -> Result { - syscall2(SYS_LINK, old as usize, new as usize) -} - -pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result { - unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) } -} - -pub fn mkdir(path: &str, mode: u16) -> Result { - unsafe { syscall3(SYS_MKDIR, path.as_ptr() as usize, path.len(), mode as usize) } -} - -pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result { - unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize, rem as *mut TimeSpec as usize) } -} - -pub fn open(path: &str, flags: usize) -> Result { - unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) } -} - -pub unsafe fn physalloc(size: usize) -> Result { - syscall1(SYS_PHYSALLOC, size) -} - -pub unsafe fn physfree(physical_address: usize, size: usize) -> Result { - syscall2(SYS_PHYSFREE, physical_address, size) -} - -pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result { - syscall3(SYS_PHYSMAP, physical_address, size, flags) -} - -pub unsafe fn physunmap(virtual_address: usize) -> Result { - syscall1(SYS_PHYSUNMAP, virtual_address) -} - -pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result { - unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) } -} - -pub fn read(fd: usize, buf: &mut [u8]) -> Result { - unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) } -} - -pub fn rmdir(path: &str) -> Result { - unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) } -} - -pub fn setgid(gid: usize) -> Result { - unsafe { syscall1(SYS_SETGID, gid) } -} - -pub fn setuid(uid: usize) -> Result { - unsafe { syscall1(SYS_SETUID, uid) } -} - -pub fn unlink(path: &str) -> Result { - unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) } -} - -pub unsafe fn virttophys(virtual_address: usize) -> Result { - syscall1(SYS_VIRTTOPHYS, virtual_address) -} - -pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result { - unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) } -} - -pub fn write(fd: usize, buf: &[u8]) -> Result { - unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) } -} - -pub fn sched_yield() -> Result { - unsafe { syscall0(SYS_YIELD) } -}