]>
Commit | Line | Data |
---|---|---|
32a655c1 SL |
1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | use super::arch::*; | |
12 | use super::data::{Stat, StatVfs, TimeSpec}; | |
13 | use super::error::Result; | |
14 | use super::number::*; | |
15 | ||
16 | use core::mem; | |
17 | ||
18 | /// Set the end of the process's heap | |
19 | /// | |
20 | /// When `addr` is `0`, this function will return the current break. | |
21 | /// | |
22 | /// When `addr` is nonzero, this function will attempt to set the end of the process's | |
23 | /// heap to `addr` and return the new program break. The new program break should be | |
24 | /// checked by the allocator, it may not be exactly `addr`, as it may be aligned to a page | |
25 | /// boundary. | |
26 | /// | |
27 | /// On error, `Err(ENOMEM)` will be returned indicating that no memory is available | |
28 | pub unsafe fn brk(addr: usize) -> Result<usize> { | |
29 | syscall1(SYS_BRK, addr) | |
30 | } | |
31 | ||
32 | /// Change the process's working directory | |
33 | /// | |
34 | /// This function will attempt to set the process's working directory to `path`, which can be | |
35 | /// either a relative, scheme relative, or absolute path. | |
36 | /// | |
37 | /// On success, `Ok(0)` will be returned. On error, one of the following errors will be returned. | |
38 | /// | |
39 | /// # Errors | |
40 | /// | |
41 | /// * `EACCES` - permission is denied for one of the components of `path`, or `path` | |
42 | /// * `EFAULT` - `path` does not point to the process's addressible memory | |
43 | /// * `EIO` - an I/O error occured | |
44 | /// * `ENOENT` - `path` does not exit | |
45 | /// * `ENOTDIR` - `path` is not a directory | |
46 | pub fn chdir(path: &str) -> Result<usize> { | |
47 | unsafe { syscall2(SYS_CHDIR, path.as_ptr() as usize, path.len()) } | |
48 | } | |
49 | ||
50 | pub fn chmod(path: &str, mode: usize) -> Result<usize> { | |
51 | unsafe { syscall3(SYS_CHMOD, path.as_ptr() as usize, path.len(), mode) } | |
52 | } | |
53 | ||
54 | /// Produce a fork of the current process, or a new process thread | |
55 | pub unsafe fn clone(flags: usize) -> Result<usize> { | |
56 | syscall1_clobber(SYS_CLONE, flags) | |
57 | } | |
58 | ||
59 | /// Close a file | |
60 | pub fn close(fd: usize) -> Result<usize> { | |
61 | unsafe { syscall1(SYS_CLOSE, fd) } | |
62 | } | |
63 | ||
64 | /// Get the current system time | |
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 | |
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 | ||
cc61c64b XL |
74 | /// Copy and transform a file descriptor |
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 | ||
32a655c1 SL |
79 | /// Replace the current process with a new executable |
80 | pub fn execve(path: &str, args: &[[usize; 2]]) -> Result<usize> { | |
81 | unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(), | |
82 | args.as_ptr() as usize, args.len()) } | |
83 | } | |
84 | ||
85 | /// Exit the current process | |
86 | pub fn exit(status: usize) -> Result<usize> { | |
87 | unsafe { syscall1(SYS_EXIT, status) } | |
88 | } | |
89 | ||
90 | /// Register a file for event-based I/O | |
91 | pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> { | |
92 | unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) } | |
93 | } | |
94 | ||
95 | /// Register a file for event-based I/O | |
96 | pub fn fevent(fd: usize, flags: usize) -> Result<usize> { | |
97 | unsafe { syscall2(SYS_FEVENT, fd, flags) } | |
98 | } | |
99 | ||
100 | /// Map a file into memory | |
101 | pub unsafe fn fmap(fd: usize, offset: usize, size: usize) -> Result<usize> { | |
102 | syscall3(SYS_FMAP, fd, offset, size) | |
103 | } | |
104 | ||
105 | /// Unmap a memory-mapped file | |
106 | pub unsafe fn funmap(addr: usize) -> Result<usize> { | |
107 | syscall1(SYS_FUNMAP, addr) | |
108 | } | |
109 | ||
110 | /// Retrieve the canonical path of a file | |
111 | pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> { | |
112 | unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) } | |
113 | } | |
114 | ||
115 | /// Get metadata about a file | |
116 | pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> { | |
117 | unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::<Stat>()) } | |
118 | } | |
119 | ||
120 | /// Get metadata about a filesystem | |
121 | pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> { | |
122 | unsafe { syscall3(SYS_FSTATVFS, fd, stat as *mut StatVfs as usize, mem::size_of::<StatVfs>()) } | |
123 | } | |
124 | ||
125 | /// Sync a file descriptor to its underlying medium | |
126 | pub fn fsync(fd: usize) -> Result<usize> { | |
127 | unsafe { syscall1(SYS_FSYNC, fd) } | |
128 | } | |
129 | ||
130 | /// Truncate or extend a file to a specified length | |
131 | pub fn ftruncate(fd: usize, len: usize) -> Result<usize> { | |
132 | unsafe { syscall2(SYS_FTRUNCATE, fd, len) } | |
133 | } | |
134 | ||
135 | /// Fast userspace mutex | |
136 | pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) | |
137 | -> Result<usize> { | |
138 | syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize) | |
139 | } | |
140 | ||
141 | /// Get the current working directory | |
142 | pub fn getcwd(buf: &mut [u8]) -> Result<usize> { | |
143 | unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) } | |
144 | } | |
145 | ||
146 | /// Get the effective group ID | |
147 | pub fn getegid() -> Result<usize> { | |
148 | unsafe { syscall0(SYS_GETEGID) } | |
149 | } | |
150 | ||
151 | /// Get the effective namespace | |
152 | pub fn getens() -> Result<usize> { | |
153 | unsafe { syscall0(SYS_GETENS) } | |
154 | } | |
155 | ||
156 | /// Get the effective user ID | |
157 | pub fn geteuid() -> Result<usize> { | |
158 | unsafe { syscall0(SYS_GETEUID) } | |
159 | } | |
160 | ||
161 | /// Get the current group ID | |
162 | pub fn getgid() -> Result<usize> { | |
163 | unsafe { syscall0(SYS_GETGID) } | |
164 | } | |
165 | ||
166 | /// Get the current namespace | |
167 | pub fn getns() -> Result<usize> { | |
168 | unsafe { syscall0(SYS_GETNS) } | |
169 | } | |
170 | ||
171 | /// Get the current process ID | |
172 | pub fn getpid() -> Result<usize> { | |
173 | unsafe { syscall0(SYS_GETPID) } | |
174 | } | |
175 | ||
176 | /// Get the current user ID | |
177 | pub fn getuid() -> Result<usize> { | |
178 | unsafe { syscall0(SYS_GETUID) } | |
179 | } | |
180 | ||
181 | /// Set the I/O privilege level | |
182 | pub unsafe fn iopl(level: usize) -> Result<usize> { | |
183 | syscall1(SYS_IOPL, level) | |
184 | } | |
185 | ||
186 | /// Send a signal `sig` to the process identified by `pid` | |
187 | pub fn kill(pid: usize, sig: usize) -> Result<usize> { | |
188 | unsafe { syscall2(SYS_KILL, pid, sig) } | |
189 | } | |
190 | ||
191 | /// Create a link to a file | |
192 | pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> { | |
193 | syscall2(SYS_LINK, old as usize, new as usize) | |
194 | } | |
195 | ||
196 | /// Seek to `offset` bytes in a file descriptor | |
197 | pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> { | |
198 | unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) } | |
199 | } | |
200 | ||
201 | /// Make a new scheme namespace | |
202 | pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> { | |
203 | unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) } | |
204 | } | |
205 | ||
206 | /// Sleep for the time specified in `req` | |
207 | pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> { | |
208 | unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize, | |
209 | rem as *mut TimeSpec as usize) } | |
210 | } | |
211 | ||
212 | /// Open a file | |
213 | pub fn open(path: &str, flags: usize) -> Result<usize> { | |
214 | unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) } | |
215 | } | |
216 | ||
217 | /// Allocate pages, linearly in physical memory | |
218 | pub unsafe fn physalloc(size: usize) -> Result<usize> { | |
219 | syscall1(SYS_PHYSALLOC, size) | |
220 | } | |
221 | ||
222 | /// Free physically allocated pages | |
223 | pub unsafe fn physfree(physical_address: usize, size: usize) -> Result<usize> { | |
224 | syscall2(SYS_PHYSFREE, physical_address, size) | |
225 | } | |
226 | ||
227 | /// Map physical memory to virtual memory | |
228 | pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> { | |
229 | syscall3(SYS_PHYSMAP, physical_address, size, flags) | |
230 | } | |
231 | ||
232 | /// Unmap previously mapped physical memory | |
233 | pub unsafe fn physunmap(virtual_address: usize) -> Result<usize> { | |
234 | syscall1(SYS_PHYSUNMAP, virtual_address) | |
235 | } | |
236 | ||
237 | /// Create a pair of file descriptors referencing the read and write ends of a pipe | |
238 | pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize> { | |
239 | unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) } | |
240 | } | |
241 | ||
242 | /// Read from a file descriptor into a buffer | |
243 | pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> { | |
244 | unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) } | |
245 | } | |
246 | ||
247 | /// Remove a directory | |
248 | pub fn rmdir(path: &str) -> Result<usize> { | |
249 | unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) } | |
250 | } | |
251 | ||
252 | /// Set the current process group IDs | |
253 | pub fn setregid(rgid: usize, egid: usize) -> Result<usize> { | |
254 | unsafe { syscall2(SYS_SETREGID, rgid, egid) } | |
255 | } | |
256 | ||
257 | /// Make a new scheme namespace | |
258 | pub fn setrens(rns: usize, ens: usize) -> Result<usize> { | |
259 | unsafe { syscall2(SYS_SETRENS, rns, ens) } | |
260 | } | |
261 | ||
262 | /// Set the current process user IDs | |
263 | pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> { | |
264 | unsafe { syscall2(SYS_SETREUID, ruid, euid) } | |
265 | } | |
266 | ||
267 | /// Remove a file | |
268 | pub fn unlink(path: &str) -> Result<usize> { | |
269 | unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) } | |
270 | } | |
271 | ||
272 | /// Convert a virtual address to a physical one | |
273 | pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> { | |
274 | syscall1(SYS_VIRTTOPHYS, virtual_address) | |
275 | } | |
276 | ||
277 | /// Check if a child process has exited or received a signal | |
278 | pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result<usize> { | |
279 | unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) } | |
280 | } | |
281 | ||
282 | /// Write a buffer to a file descriptor | |
283 | /// | |
284 | /// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning | |
285 | /// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which | |
286 | /// were written. | |
287 | /// | |
288 | /// # Errors | |
289 | /// | |
290 | /// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block | |
291 | /// * `EBADF` - the file descriptor is not valid or is not open for writing | |
292 | /// * `EFAULT` - `buf` does not point to the process's addressible memory | |
293 | /// * `EIO` - an I/O error occured | |
294 | /// * `ENOSPC` - the device containing the file descriptor has no room for data | |
295 | /// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed | |
296 | pub fn write(fd: usize, buf: &[u8]) -> Result<usize> { | |
297 | unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) } | |
298 | } | |
299 | ||
300 | /// Yield the process's time slice to the kernel | |
301 | /// | |
302 | /// This function will return Ok(0) on success | |
303 | pub fn sched_yield() -> Result<usize> { | |
304 | unsafe { syscall0(SYS_YIELD) } | |
305 | } |