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