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    let path = path.as_ref();
83    unsafe {
84        syscall3(
85            SYS_FRENAME,
86            fd,
87            path.as_ptr() as usize,
88            path.len(),
89        )
90    }
91}
92
93/// Get metadata about a file
94pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
95    unsafe {
96        syscall3(
97            SYS_FSTAT,
98            fd,
99            stat as *mut Stat as usize,
100            mem::size_of::<Stat>(),
101        )
102    }
103}
104
105/// Get metadata about a filesystem
106pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> {
107    unsafe {
108        syscall3(
109            SYS_FSTATVFS,
110            fd,
111            stat as *mut StatVfs as usize,
112            mem::size_of::<StatVfs>(),
113        )
114    }
115}
116
117/// Sync a file descriptor to its underlying medium
118pub fn fsync(fd: usize) -> Result<usize> {
119    unsafe { syscall1(SYS_FSYNC, fd) }
120}
121
122/// Truncate or extend a file to a specified length
123pub fn ftruncate(fd: usize, len: usize) -> Result<usize> {
124    unsafe { syscall2(SYS_FTRUNCATE, fd, len) }
125}
126
127// Change modify and/or access times
128pub fn futimens(fd: usize, times: &[TimeSpec]) -> Result<usize> {
129    unsafe {
130        syscall3(
131            SYS_FUTIMENS,
132            fd,
133            times.as_ptr() as usize,
134            times.len() * mem::size_of::<TimeSpec>(),
135        )
136    }
137}
138
139/// Fast userspace mutex
140pub unsafe fn futex(
141    addr: *mut i32,
142    op: usize,
143    val: i32,
144    val2: usize,
145    addr2: *mut i32,
146) -> Result<usize> {
147    syscall5(
148        SYS_FUTEX,
149        addr as usize,
150        op,
151        (val as isize) as usize,
152        val2,
153        addr2 as usize,
154    )
155}
156
157/// Get the effective group ID
158pub fn getegid() -> Result<usize> {
159    unsafe { syscall0(SYS_GETEGID) }
160}
161
162/// Get the effective namespace
163pub fn getens() -> Result<usize> {
164    unsafe { syscall0(SYS_GETENS) }
165}
166
167/// Get the effective user ID
168pub fn geteuid() -> Result<usize> {
169    unsafe { syscall0(SYS_GETEUID) }
170}
171
172/// Get the current group ID
173pub fn getgid() -> Result<usize> {
174    unsafe { syscall0(SYS_GETGID) }
175}
176
177/// Get the current namespace
178pub fn getns() -> Result<usize> {
179    unsafe { syscall0(SYS_GETNS) }
180}
181
182/// Get the current process ID
183pub fn getpid() -> Result<usize> {
184    unsafe { syscall0(SYS_GETPID) }
185}
186
187/// Get the process group ID
188pub fn getpgid(pid: usize) -> Result<usize> {
189    unsafe { syscall1(SYS_GETPGID, pid) }
190}
191
192/// Get the parent process ID
193pub fn getppid() -> Result<usize> {
194    unsafe { syscall0(SYS_GETPPID) }
195}
196
197/// Get the current user ID
198pub fn getuid() -> Result<usize> {
199    unsafe { syscall0(SYS_GETUID) }
200}
201
202/// Set the I/O privilege level
203///
204/// # Errors
205///
206/// * `EPERM` - `uid != 0`
207/// * `EINVAL` - `level > 3`
208pub unsafe fn iopl(level: usize) -> Result<usize> {
209    syscall1(SYS_IOPL, level)
210}
211
212/// Send a signal `sig` to the process identified by `pid`
213pub fn kill(pid: usize, sig: usize) -> Result<usize> {
214    unsafe { syscall2(SYS_KILL, pid, sig) }
215}
216
217/// Create a link to a file
218pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
219    syscall2(SYS_LINK, old as usize, new as usize)
220}
221
222/// Seek to `offset` bytes in a file descriptor
223pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> {
224    unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) }
225}
226
227/// Make a new scheme namespace
228pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
229    unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) }
230}
231
232/// Change mapping flags
233pub unsafe fn mprotect(addr: usize, size: usize, flags: MapFlags) -> Result<usize> {
234    syscall3(SYS_MPROTECT, addr, size, flags.bits())
235}
236
237/// Sleep for the time specified in `req`
238pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
239    unsafe {
240        syscall2(
241            SYS_NANOSLEEP,
242            req as *const TimeSpec as usize,
243            rem as *mut TimeSpec as usize,
244        )
245    }
246}
247
248/// Open a file
249pub fn open<T: AsRef<str>>(path: T, flags: usize) -> Result<usize> {
250    let path = path.as_ref();
251    unsafe {
252        syscall3(
253            SYS_OPEN,
254            path.as_ptr() as usize,
255            path.len(),
256            flags,
257        )
258    }
259}
260
261/// Open a file at a specific path
262pub fn openat<T: AsRef<str>>(fd: usize, path: T, flags: usize) -> Result<usize> {
263    let path = path.as_ref();
264    unsafe {
265        syscall4(
266            SYS_OPENAT,
267            fd,
268            path.as_ptr() as usize,
269            path.len(),
270            flags,
271        )
272    }
273}
274
275/// Read from a file descriptor into a buffer
276pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
277    unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) }
278}
279
280/// Remove a directory
281pub fn rmdir<T: AsRef<str>>(path: T) -> Result<usize> {
282    let path = path.as_ref();
283    unsafe {
284        syscall2(
285            SYS_RMDIR,
286            path.as_ptr() as usize,
287            path.len(),
288        )
289    }
290}
291
292/// Set the process group ID
293pub fn setpgid(pid: usize, pgid: usize) -> Result<usize> {
294    unsafe { syscall2(SYS_SETPGID, pid, pgid) }
295}
296
297/// Set the current process group IDs
298pub fn setregid(rgid: usize, egid: usize) -> Result<usize> {
299    unsafe { syscall2(SYS_SETREGID, rgid, egid) }
300}
301
302/// Make a new scheme namespace
303pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
304    unsafe { syscall2(SYS_SETRENS, rns, ens) }
305}
306
307/// Set the current process user IDs
308pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> {
309    unsafe { syscall2(SYS_SETREUID, ruid, euid) }
310}
311
312/// Remove a file
313pub fn unlink<T: AsRef<str>>(path: T) -> Result<usize> {
314    let path = path.as_ref();
315    unsafe {
316        syscall2(
317            SYS_UNLINK,
318            path.as_ptr() as usize,
319            path.len(),
320        )
321    }
322}
323
324/// Convert a virtual address to a physical one
325///
326/// # Errors
327///
328/// * `EPERM` - `uid != 0`
329pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
330    syscall1(SYS_VIRTTOPHYS, virtual_address)
331}
332
333/// Check if a child process has exited or received a signal
334pub fn waitpid(pid: usize, status: &mut usize, options: WaitFlags) -> Result<usize> {
335    unsafe {
336        syscall3(
337            SYS_WAITPID,
338            pid,
339            status as *mut usize as usize,
340            options.bits(),
341        )
342    }
343}
344
345/// Write a buffer to a file descriptor
346///
347/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning
348/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which
349/// were written.
350///
351/// # Errors
352///
353/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
354/// * `EBADF` - the file descriptor is not valid or is not open for writing
355/// * `EFAULT` - `buf` does not point to the process's addressible memory
356/// * `EIO` - an I/O error occurred
357/// * `ENOSPC` - the device containing the file descriptor has no room for data
358/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
359pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
360    unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) }
361}
362
363/// Yield the process's time slice to the kernel
364///
365/// This function will return Ok(0) on success
366pub fn sched_yield() -> Result<usize> {
367    unsafe { syscall0(SYS_YIELD) }
368}
369
370/// Send a file descriptor `fd`, handled by the scheme providing `receiver_socket`. `flags` is
371/// currently unused (must be zero), and `arg` is included in the scheme call.
372///
373/// The scheme can return an arbitrary value.
374pub fn sendfd(receiver_socket: usize, fd: usize, flags: usize, arg: u64) -> Result<usize> {
375    #[cfg(target_pointer_width = "32")]
376    unsafe {
377        syscall5(
378            SYS_SENDFD,
379            receiver_socket,
380            fd,
381            flags,
382            arg as u32 as usize,
383            (arg >> 32) as u32 as usize,
384        )
385    }
386
387    #[cfg(target_pointer_width = "64")]
388    unsafe {
389        syscall4(SYS_SENDFD, receiver_socket, fd, flags, arg as usize)
390    }
391}