syscall/
call.rs

1use super::{
2    arch::*,
3    data::{Map, Stat, StatVfs, TimeSpec},
4    error::Result,
5    flag::*,
6    number::*,
7};
8
9use core::mem;
10
11/// Close a file
12pub fn close(fd: usize) -> Result<usize> {
13    unsafe { syscall1(SYS_CLOSE, fd) }
14}
15
16/// Get the current system time
17pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize> {
18    unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
19}
20
21/// Copy and transform a file descriptor
22pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
23    unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) }
24}
25
26/// Copy and transform a file descriptor
27pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> {
28    unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) }
29}
30
31/// Exit the current process
32pub fn exit(status: usize) -> Result<usize> {
33    unsafe { syscall1(SYS_EXIT, status) }
34}
35
36/// Change file permissions
37pub fn fchmod(fd: usize, mode: u16) -> Result<usize> {
38    unsafe { syscall2(SYS_FCHMOD, fd, mode as usize) }
39}
40
41/// Change file ownership
42pub fn fchown(fd: usize, uid: u32, gid: u32) -> Result<usize> {
43    unsafe { syscall3(SYS_FCHOWN, fd, uid as usize, gid as usize) }
44}
45
46/// Change file descriptor flags
47pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
48    unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
49}
50
51/// Map a file into memory, but with the ability to set the address to map into, either as a hint
52/// or as a requirement of the map.
53///
54/// # Errors
55/// `EACCES` - the file descriptor was not open for reading
56/// `EBADF` - if the file descriptor was invalid
57/// `ENODEV` - mmapping was not supported
58/// `EINVAL` - invalid combination of flags
59/// `EEXIST` - if [`MapFlags::MAP_FIXED`] was set, and the address specified was already in use.
60///
61pub unsafe fn fmap(fd: usize, map: &Map) -> Result<usize> {
62    syscall3(
63        SYS_FMAP,
64        fd,
65        map as *const Map as usize,
66        mem::size_of::<Map>(),
67    )
68}
69
70/// Unmap whole (or partial) continous memory-mapped files
71pub unsafe fn funmap(addr: usize, len: usize) -> Result<usize> {
72    syscall2(SYS_FUNMAP, addr, len)
73}
74
75/// Retrieve the canonical path of a file
76pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> {
77    unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) }
78}
79
80/// Rename a file
81pub fn frename<T: AsRef<str>>(fd: usize, path: T) -> Result<usize> {
82    unsafe {
83        syscall3(
84            SYS_FRENAME,
85            fd,
86            path.as_ref().as_ptr() as usize,
87            path.as_ref().len(),
88        )
89    }
90}
91
92/// Get metadata about a file
93pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
94    unsafe {
95        syscall3(
96            SYS_FSTAT,
97            fd,
98            stat as *mut Stat as usize,
99            mem::size_of::<Stat>(),
100        )
101    }
102}
103
104/// Get metadata about a filesystem
105pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> {
106    unsafe {
107        syscall3(
108            SYS_FSTATVFS,
109            fd,
110            stat as *mut StatVfs as usize,
111            mem::size_of::<StatVfs>(),
112        )
113    }
114}
115
116/// Sync a file descriptor to its underlying medium
117pub fn fsync(fd: usize) -> Result<usize> {
118    unsafe { syscall1(SYS_FSYNC, fd) }
119}
120
121/// Truncate or extend a file to a specified length
122pub fn ftruncate(fd: usize, len: usize) -> Result<usize> {
123    unsafe { syscall2(SYS_FTRUNCATE, fd, len) }
124}
125
126// Change modify and/or access times
127pub fn futimens(fd: usize, times: &[TimeSpec]) -> Result<usize> {
128    unsafe {
129        syscall3(
130            SYS_FUTIMENS,
131            fd,
132            times.as_ptr() as usize,
133            times.len() * mem::size_of::<TimeSpec>(),
134        )
135    }
136}
137
138/// Fast userspace mutex
139pub unsafe fn futex(
140    addr: *mut i32,
141    op: usize,
142    val: i32,
143    val2: usize,
144    addr2: *mut i32,
145) -> Result<usize> {
146    syscall5(
147        SYS_FUTEX,
148        addr as usize,
149        op,
150        (val as isize) as usize,
151        val2,
152        addr2 as usize,
153    )
154}
155
156/// Get the effective group ID
157pub fn getegid() -> Result<usize> {
158    unsafe { syscall0(SYS_GETEGID) }
159}
160
161/// Get the effective namespace
162pub fn getens() -> Result<usize> {
163    unsafe { syscall0(SYS_GETENS) }
164}
165
166/// Get the effective user ID
167pub fn geteuid() -> Result<usize> {
168    unsafe { syscall0(SYS_GETEUID) }
169}
170
171/// Get the current group ID
172pub fn getgid() -> Result<usize> {
173    unsafe { syscall0(SYS_GETGID) }
174}
175
176/// Get the current namespace
177pub fn getns() -> Result<usize> {
178    unsafe { syscall0(SYS_GETNS) }
179}
180
181/// Get the current process ID
182pub fn getpid() -> Result<usize> {
183    unsafe { syscall0(SYS_GETPID) }
184}
185
186/// Get the process group ID
187pub fn getpgid(pid: usize) -> Result<usize> {
188    unsafe { syscall1(SYS_GETPGID, pid) }
189}
190
191/// Get the parent process ID
192pub fn getppid() -> Result<usize> {
193    unsafe { syscall0(SYS_GETPPID) }
194}
195
196/// Get the current user ID
197pub fn getuid() -> Result<usize> {
198    unsafe { syscall0(SYS_GETUID) }
199}
200
201/// Set the I/O privilege level
202///
203/// # Errors
204///
205/// * `EPERM` - `uid != 0`
206/// * `EINVAL` - `level > 3`
207pub unsafe fn iopl(level: usize) -> Result<usize> {
208    syscall1(SYS_IOPL, level)
209}
210
211/// Send a signal `sig` to the process identified by `pid`
212pub fn kill(pid: usize, sig: usize) -> Result<usize> {
213    unsafe { syscall2(SYS_KILL, pid, sig) }
214}
215
216/// Create a link to a file
217pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
218    syscall2(SYS_LINK, old as usize, new as usize)
219}
220
221/// Seek to `offset` bytes in a file descriptor
222pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> {
223    unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) }
224}
225
226/// Make a new scheme namespace
227pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
228    unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) }
229}
230
231/// Change mapping flags
232pub unsafe fn mprotect(addr: usize, size: usize, flags: MapFlags) -> Result<usize> {
233    syscall3(SYS_MPROTECT, addr, size, flags.bits())
234}
235
236/// Sleep for the time specified in `req`
237pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
238    unsafe {
239        syscall2(
240            SYS_NANOSLEEP,
241            req as *const TimeSpec as usize,
242            rem as *mut TimeSpec as usize,
243        )
244    }
245}
246
247/// Open a file
248pub fn open<T: AsRef<str>>(path: T, flags: usize) -> Result<usize> {
249    unsafe {
250        syscall3(
251            SYS_OPEN,
252            path.as_ref().as_ptr() as usize,
253            path.as_ref().len(),
254            flags,
255        )
256    }
257}
258
259/// Read from a file descriptor into a buffer
260pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
261    unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) }
262}
263
264/// Remove a directory
265pub fn rmdir<T: AsRef<str>>(path: T) -> Result<usize> {
266    unsafe {
267        syscall2(
268            SYS_RMDIR,
269            path.as_ref().as_ptr() as usize,
270            path.as_ref().len(),
271        )
272    }
273}
274
275/// Set the process group ID
276pub fn setpgid(pid: usize, pgid: usize) -> Result<usize> {
277    unsafe { syscall2(SYS_SETPGID, pid, pgid) }
278}
279
280/// Set the current process group IDs
281pub fn setregid(rgid: usize, egid: usize) -> Result<usize> {
282    unsafe { syscall2(SYS_SETREGID, rgid, egid) }
283}
284
285/// Make a new scheme namespace
286pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
287    unsafe { syscall2(SYS_SETRENS, rns, ens) }
288}
289
290/// Set the current process user IDs
291pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> {
292    unsafe { syscall2(SYS_SETREUID, ruid, euid) }
293}
294
295/// Remove a file
296pub fn unlink<T: AsRef<str>>(path: T) -> Result<usize> {
297    unsafe {
298        syscall2(
299            SYS_UNLINK,
300            path.as_ref().as_ptr() as usize,
301            path.as_ref().len(),
302        )
303    }
304}
305
306/// Convert a virtual address to a physical one
307///
308/// # Errors
309///
310/// * `EPERM` - `uid != 0`
311pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
312    syscall1(SYS_VIRTTOPHYS, virtual_address)
313}
314
315/// Check if a child process has exited or received a signal
316pub fn waitpid(pid: usize, status: &mut usize, options: WaitFlags) -> Result<usize> {
317    unsafe {
318        syscall3(
319            SYS_WAITPID,
320            pid,
321            status as *mut usize as usize,
322            options.bits(),
323        )
324    }
325}
326
327/// Write a buffer to a file descriptor
328///
329/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning
330/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which
331/// were written.
332///
333/// # Errors
334///
335/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
336/// * `EBADF` - the file descriptor is not valid or is not open for writing
337/// * `EFAULT` - `buf` does not point to the process's addressible memory
338/// * `EIO` - an I/O error occurred
339/// * `ENOSPC` - the device containing the file descriptor has no room for data
340/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
341pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
342    unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) }
343}
344
345/// Yield the process's time slice to the kernel
346///
347/// This function will return Ok(0) on success
348pub fn sched_yield() -> Result<usize> {
349    unsafe { syscall0(SYS_YIELD) }
350}
351
352/// Send a file descriptor `fd`, handled by the scheme providing `receiver_socket`. `flags` is
353/// currently unused (must be zero), and `arg` is included in the scheme call.
354///
355/// The scheme can return an arbitrary value.
356pub fn sendfd(receiver_socket: usize, fd: usize, flags: usize, arg: u64) -> Result<usize> {
357    #[cfg(target_pointer_width = "32")]
358    unsafe {
359        syscall5(
360            SYS_SENDFD,
361            receiver_socket,
362            fd,
363            flags,
364            arg as u32 as usize,
365            (arg >> 32) as u32 as usize,
366        )
367    }
368
369    #[cfg(target_pointer_width = "64")]
370    unsafe {
371        syscall4(SYS_SENDFD, receiver_socket, fd, flags, arg as usize)
372    }
373}