1 use super::arch::*;
2 use super::data::{Map, SigAction, Stat, StatVfs, TimeSpec};
3 use super::error::Result;
4 use super::flag::*;
5 use super::number::*;
6 
7 use core::{mem, ptr};
8 
9 // Signal restorer
restorer() -> !10 extern "C" fn restorer() -> ! {
11     sigreturn().unwrap();
12     unreachable!();
13 }
14 
15 /// Change the process's working directory
16 ///
17 /// This function will attempt to set the process's working directory to `path`, which can be
18 /// either a relative, scheme relative, or absolute path.
19 ///
20 /// On success, `Ok(0)` will be returned. On error, one of the following errors will be returned.
21 ///
22 /// # Errors
23 ///
24 /// * `EACCES` - permission is denied for one of the components of `path`, or `path`
25 /// * `EFAULT` - `path` does not point to the process's addressible memory
26 /// * `EIO` - an I/O error occurred
27 /// * `ENOENT` - `path` does not exit
28 /// * `ENOTDIR` - `path` is not a directory
chdir<T: AsRef<str>>(path: T) -> Result<usize>29 pub fn chdir<T: AsRef<str>>(path: T) -> Result<usize> {
30     unsafe { syscall2(SYS_CHDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
31 }
32 
33 #[deprecated(
34     since = "0.1.55",
35     note = "use fchmod instead"
36 )]
chmod<T: AsRef<str>>(path: T, mode: usize) -> Result<usize>37 pub fn chmod<T: AsRef<str>>(path: T, mode: usize) -> Result<usize> {
38     unsafe { syscall3(SYS_CHMOD, path.as_ref().as_ptr() as usize, path.as_ref().len(), mode) }
39 }
40 
41 /// Produce a fork of the current process, or a new process thread
clone(flags: CloneFlags) -> Result<usize>42 pub unsafe fn clone(flags: CloneFlags) -> Result<usize> {
43     syscall1(SYS_CLONE, flags.bits())
44 }
45 
46 /// Close a file
close(fd: usize) -> Result<usize>47 pub fn close(fd: usize) -> Result<usize> {
48     unsafe { syscall1(SYS_CLOSE, fd) }
49 }
50 
51 /// Get the current system time
clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize>52 pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize> {
53     unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
54 }
55 
56 /// Copy and transform a file descriptor
dup(fd: usize, buf: &[u8]) -> Result<usize>57 pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
58     unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) }
59 }
60 
61 /// Copy and transform a file descriptor
dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize>62 pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> {
63     unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) }
64 }
65 
66 /// Exit the current process
exit(status: usize) -> Result<usize>67 pub fn exit(status: usize) -> Result<usize> {
68     unsafe { syscall1(SYS_EXIT, status) }
69 }
70 
71 /// Change file permissions
fchmod(fd: usize, mode: u16) -> Result<usize>72 pub fn fchmod(fd: usize, mode: u16) -> Result<usize> {
73     unsafe { syscall2(SYS_FCHMOD, fd, mode as usize) }
74 
75 }
76 
77 /// Change file ownership
fchown(fd: usize, uid: u32, gid: u32) -> Result<usize>78 pub fn fchown(fd: usize, uid: u32, gid: u32) -> Result<usize> {
79     unsafe { syscall3(SYS_FCHOWN, fd, uid as usize, gid as usize) }
80 
81 }
82 
83 /// Change file descriptor flags
fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize>84 pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
85     unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
86 }
87 
88 /// Replace the current process with a new executable
fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usize>89 pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usize> {
90     unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(), vars.as_ptr() as usize, vars.len()) }
91 }
92 
93 /// Map a file into memory, but with the ability to set the address to map into, either as a hint
94 /// or as a requirement of the map.
95 ///
96 /// # Errors
97 /// `EACCES` - the file descriptor was not open for reading
98 /// `EBADF` - if the file descriptor was invalid
99 /// `ENODEV` - mmapping was not supported
100 /// `EINVAL` - invalid combination of flags
101 /// `EEXIST` - if [`MapFlags::MAP_FIXED`] was set, and the address specified was already in use.
102 ///
fmap(fd: usize, map: &Map) -> Result<usize>103 pub unsafe fn fmap(fd: usize, map: &Map) -> Result<usize> {
104     syscall3(SYS_FMAP, fd, map as *const Map as usize, mem::size_of::<Map>())
105 }
106 
107 /// Unmap whole (or partial) continous memory-mapped files
funmap(addr: usize, len: usize) -> Result<usize>108 pub unsafe fn funmap(addr: usize, len: usize) -> Result<usize> {
109     syscall2(SYS_FUNMAP, addr, len)
110 }
111 
112 /// Retrieve the canonical path of a file
fpath(fd: usize, buf: &mut [u8]) -> Result<usize>113 pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> {
114     unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) }
115 }
116 
117 /// Rename a file
frename<T: AsRef<str>>(fd: usize, path: T) -> Result<usize>118 pub fn frename<T: AsRef<str>>(fd: usize, path: T) -> Result<usize> {
119     unsafe { syscall3(SYS_FRENAME, fd, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
120 }
121 
122 /// Get metadata about a file
fstat(fd: usize, stat: &mut Stat) -> Result<usize>123 pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
124     unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::<Stat>()) }
125 }
126 
127 /// Get metadata about a filesystem
fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize>128 pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> {
129     unsafe { syscall3(SYS_FSTATVFS, fd, stat as *mut StatVfs as usize, mem::size_of::<StatVfs>()) }
130 }
131 
132 /// Sync a file descriptor to its underlying medium
fsync(fd: usize) -> Result<usize>133 pub fn fsync(fd: usize) -> Result<usize> {
134     unsafe { syscall1(SYS_FSYNC, fd) }
135 }
136 
137 /// Truncate or extend a file to a specified length
ftruncate(fd: usize, len: usize) -> Result<usize>138 pub fn ftruncate(fd: usize, len: usize) -> Result<usize> {
139     unsafe { syscall2(SYS_FTRUNCATE, fd, len) }
140 }
141 
142 // Change modify and/or access times
futimens(fd: usize, times: &[TimeSpec]) -> Result<usize>143 pub fn futimens(fd: usize, times: &[TimeSpec]) -> Result<usize> {
144     unsafe { syscall3(SYS_FUTIMENS, fd, times.as_ptr() as usize, times.len() * mem::size_of::<TimeSpec>()) }
145 }
146 
147 /// Fast userspace mutex
futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) -> Result<usize>148 pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32)
149                     -> Result<usize> {
150     syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize)
151 }
152 
153 /// Get the current working directory
getcwd(buf: &mut [u8]) -> Result<usize>154 pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
155     unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) }
156 }
157 
158 /// Get the effective group ID
getegid() -> Result<usize>159 pub fn getegid() -> Result<usize> {
160     unsafe { syscall0(SYS_GETEGID) }
161 }
162 
163 /// Get the effective namespace
getens() -> Result<usize>164 pub fn getens() -> Result<usize> {
165     unsafe { syscall0(SYS_GETENS) }
166 }
167 
168 /// Get the effective user ID
geteuid() -> Result<usize>169 pub fn geteuid() -> Result<usize> {
170     unsafe { syscall0(SYS_GETEUID) }
171 }
172 
173 /// Get the current group ID
getgid() -> Result<usize>174 pub fn getgid() -> Result<usize> {
175     unsafe { syscall0(SYS_GETGID) }
176 }
177 
178 /// Get the current namespace
getns() -> Result<usize>179 pub fn getns() -> Result<usize> {
180     unsafe { syscall0(SYS_GETNS) }
181 }
182 
183 /// Get the current process ID
getpid() -> Result<usize>184 pub fn getpid() -> Result<usize> {
185     unsafe { syscall0(SYS_GETPID) }
186 }
187 
188 /// Get the process group ID
getpgid(pid: usize) -> Result<usize>189 pub fn getpgid(pid: usize) -> Result<usize> {
190     unsafe { syscall1(SYS_GETPGID, pid) }
191 }
192 
193 /// Get the parent process ID
getppid() -> Result<usize>194 pub fn getppid() -> Result<usize> {
195     unsafe { syscall0(SYS_GETPPID) }
196 }
197 
198 /// Get the current user ID
getuid() -> Result<usize>199 pub fn getuid() -> Result<usize> {
200     unsafe { syscall0(SYS_GETUID) }
201 }
202 
203 /// Set the I/O privilege level
204 ///
205 /// # Errors
206 ///
207 /// * `EPERM` - `uid != 0`
208 /// * `EINVAL` - `level > 3`
iopl(level: usize) -> Result<usize>209 pub unsafe fn iopl(level: usize) -> Result<usize> {
210     syscall1(SYS_IOPL, level)
211 }
212 
213 /// Send a signal `sig` to the process identified by `pid`
kill(pid: usize, sig: usize) -> Result<usize>214 pub fn kill(pid: usize, sig: usize) -> Result<usize> {
215     unsafe { syscall2(SYS_KILL, pid, sig) }
216 }
217 
218 /// Create a link to a file
link(old: *const u8, new: *const u8) -> Result<usize>219 pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
220     syscall2(SYS_LINK, old as usize, new as usize)
221 }
222 
223 /// Seek to `offset` bytes in a file descriptor
lseek(fd: usize, offset: isize, whence: usize) -> Result<usize>224 pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> {
225     unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) }
226 }
227 
228 /// Make a new scheme namespace
mkns(schemes: &[[usize; 2]]) -> Result<usize>229 pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
230     unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) }
231 }
232 
233 /// Change mapping flags
mprotect(addr: usize, size: usize, flags: MapFlags) -> Result<usize>234 pub unsafe fn mprotect(addr: usize, size: usize, flags: MapFlags) -> Result<usize> {
235     syscall3(SYS_MPROTECT, addr, size, flags.bits())
236 }
237 
238 /// Sleep for the time specified in `req`
nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize>239 pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
240     unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize,
241                                      rem as *mut TimeSpec as usize) }
242 }
243 
244 /// Open a file
open<T: AsRef<str>>(path: T, flags: usize) -> Result<usize>245 pub fn open<T: AsRef<str>>(path: T, flags: usize) -> Result<usize> {
246     unsafe { syscall3(SYS_OPEN, path.as_ref().as_ptr() as usize, path.as_ref().len(), flags) }
247 }
248 
249 /// Allocate frames, linearly in physical memory.
250 ///
251 /// # Errors
252 ///
253 /// * `EPERM` - `uid != 0`
254 /// * `ENOMEM` - the system has run out of available memory
physalloc(size: usize) -> Result<usize>255 pub unsafe fn physalloc(size: usize) -> Result<usize> {
256     syscall1(SYS_PHYSALLOC, size)
257 }
258 
259 /// Allocate frames, linearly in physical memory, with an extra set of flags. If the flags contain
260 /// [`PARTIAL_ALLOC`], this will result in `physalloc3` with `min = 1`.
261 ///
262 /// Refer to the simpler [`physalloc`] and the more complex [`physalloc3`], that this convenience
263 /// function is based on.
264 ///
265 /// # Errors
266 ///
267 /// * `EPERM` - `uid != 0`
268 /// * `ENOMEM` - the system has run out of available memory
physalloc2(size: usize, flags: usize) -> Result<usize>269 pub unsafe fn physalloc2(size: usize, flags: usize) -> Result<usize> {
270     let mut ret = 1usize;
271     physalloc3(size, flags, &mut ret)
272 }
273 
274 /// Allocate frames, linearly in physical memory, with an extra set of flags. If the flags contain
275 /// [`PARTIAL_ALLOC`], the `min` parameter specifies the number of frames that have to be allocated
276 /// for this operation to succeed. The return value is the offset of the first frame, and `min` is
277 /// overwritten with the number of frames actually allocated.
278 ///
279 /// Refer to the simpler [`physalloc`] and the simpler library function [`physalloc2`].
280 ///
281 /// # Errors
282 ///
283 /// * `EPERM` - `uid != 0`
284 /// * `ENOMEM` - the system has run out of available memory
285 /// * `EINVAL` - `min = 0`
physalloc3(size: usize, flags: usize, min: &mut usize) -> Result<usize>286 pub unsafe fn physalloc3(size: usize, flags: usize, min: &mut usize) -> Result<usize> {
287     syscall3(SYS_PHYSALLOC3, size, flags, min as *mut usize as usize)
288 }
289 
290 /// Free physically allocated pages
291 ///
292 /// # Errors
293 ///
294 /// * `EPERM` - `uid != 0`
physfree(physical_address: usize, size: usize) -> Result<usize>295 pub unsafe fn physfree(physical_address: usize, size: usize) -> Result<usize> {
296     syscall2(SYS_PHYSFREE, physical_address, size)
297 }
298 
299 /// Map physical memory to virtual memory
300 ///
301 /// # Errors
302 ///
303 /// * `EPERM` - `uid != 0`
physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result<usize>304 pub unsafe fn physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result<usize> {
305     syscall3(SYS_PHYSMAP, physical_address, size, flags.bits())
306 }
307 
308 /// Unmap previously mapped physical memory
309 ///
310 /// # Errors
311 ///
312 /// * `EPERM` - `uid != 0`
313 /// * `EFAULT` - `virtual_address` has not been mapped
physunmap(virtual_address: usize) -> Result<usize>314 pub unsafe fn physunmap(virtual_address: usize) -> Result<usize> {
315     syscall1(SYS_PHYSUNMAP, virtual_address)
316 }
317 
318 /// Create a pair of file descriptors referencing the read and write ends of a pipe
pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize>319 pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize> {
320     unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) }
321 }
322 
323 /// Read from a file descriptor into a buffer
read(fd: usize, buf: &mut [u8]) -> Result<usize>324 pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
325     unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) }
326 }
327 
328 /// Remove a directory
rmdir<T: AsRef<str>>(path: T) -> Result<usize>329 pub fn rmdir<T: AsRef<str>>(path: T) -> Result<usize> {
330     unsafe { syscall2(SYS_RMDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
331 }
332 
333 /// Set the process group ID
setpgid(pid: usize, pgid: usize) -> Result<usize>334 pub fn setpgid(pid: usize, pgid: usize) -> Result<usize> {
335     unsafe { syscall2(SYS_SETPGID, pid, pgid) }
336 }
337 
338 /// Set the current process group IDs
setregid(rgid: usize, egid: usize) -> Result<usize>339 pub fn setregid(rgid: usize, egid: usize) -> Result<usize> {
340     unsafe { syscall2(SYS_SETREGID, rgid, egid) }
341 }
342 
343 /// Make a new scheme namespace
setrens(rns: usize, ens: usize) -> Result<usize>344 pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
345     unsafe { syscall2(SYS_SETRENS, rns, ens) }
346 }
347 
348 /// Set the current process user IDs
setreuid(ruid: usize, euid: usize) -> Result<usize>349 pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> {
350     unsafe { syscall2(SYS_SETREUID, ruid, euid) }
351 }
352 
353 /// Set up a signal handler
sigaction(sig: usize, act: Option<&SigAction>, oldact: Option<&mut SigAction>) -> Result<usize>354 pub fn sigaction(sig: usize, act: Option<&SigAction>, oldact: Option<&mut SigAction>) -> Result<usize> {
355     unsafe { syscall4(SYS_SIGACTION, sig,
356                       act.map(|x| x as *const _).unwrap_or_else(ptr::null) as usize,
357                       oldact.map(|x| x as *mut _).unwrap_or_else(ptr::null_mut) as usize,
358                       restorer as usize) }
359 }
360 
361 /// Get and/or set signal masks
sigprocmask(how: usize, set: Option<&[u64; 2]>, oldset: Option<&mut [u64; 2]>) -> Result<usize>362 pub fn sigprocmask(how: usize, set: Option<&[u64; 2]>, oldset: Option<&mut [u64; 2]>) -> Result<usize> {
363     unsafe { syscall3(SYS_SIGPROCMASK, how,
364                       set.map(|x| x as *const _).unwrap_or_else(ptr::null) as usize,
365                       oldset.map(|x| x as *mut _).unwrap_or_else(ptr::null_mut) as usize) }
366 }
367 
368 // Return from signal handler
sigreturn() -> Result<usize>369 pub fn sigreturn() -> Result<usize> {
370     unsafe { syscall0(SYS_SIGRETURN) }
371 }
372 
373 /// Set the file mode creation mask
umask(mask: usize) -> Result<usize>374 pub fn umask(mask: usize) -> Result<usize> {
375     unsafe { syscall1(SYS_UMASK, mask) }
376 }
377 
378 /// Remove a file
unlink<T: AsRef<str>>(path: T) -> Result<usize>379 pub fn unlink<T: AsRef<str>>(path: T) -> Result<usize> {
380     unsafe { syscall2(SYS_UNLINK, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
381 }
382 
383 /// Convert a virtual address to a physical one
384 ///
385 /// # Errors
386 ///
387 /// * `EPERM` - `uid != 0`
virttophys(virtual_address: usize) -> Result<usize>388 pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
389     syscall1(SYS_VIRTTOPHYS, virtual_address)
390 }
391 
392 /// Check if a child process has exited or received a signal
waitpid(pid: usize, status: &mut usize, options: WaitFlags) -> Result<usize>393 pub fn waitpid(pid: usize, status: &mut usize, options: WaitFlags) -> Result<usize> {
394     unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options.bits()) }
395 }
396 
397 /// Write a buffer to a file descriptor
398 ///
399 /// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning
400 /// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which
401 /// were written.
402 ///
403 /// # Errors
404 ///
405 /// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
406 /// * `EBADF` - the file descriptor is not valid or is not open for writing
407 /// * `EFAULT` - `buf` does not point to the process's addressible memory
408 /// * `EIO` - an I/O error occurred
409 /// * `ENOSPC` - the device containing the file descriptor has no room for data
410 /// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
write(fd: usize, buf: &[u8]) -> Result<usize>411 pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
412     unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) }
413 }
414 
415 /// Yield the process's time slice to the kernel
416 ///
417 /// This function will return Ok(0) on success
sched_yield() -> Result<usize>418 pub fn sched_yield() -> Result<usize> {
419     unsafe { syscall0(SYS_YIELD) }
420 }
421