call.rs 11.7 KB
Newer Older
Jeremy Soller's avatar
Jeremy Soller committed
1
use super::arch::*;
2
use super::data::{SigAction, Stat, StatVfs, TimeSpec};
Jeremy Soller's avatar
Jeremy Soller committed
3
4
5
use super::error::Result;
use super::number::*;

6
use core::{mem, ptr};
Jeremy Soller's avatar
Jeremy Soller committed
7

8
9
10
11
12
13
// Signal restorer
extern "C" fn restorer() -> ! {
    sigreturn().unwrap();
    unreachable!();
}

Jeremy Soller's avatar
Jeremy Soller committed
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/// Set the end of the process's heap
///
/// When `addr` is `0`, this function will return the current break.
///
/// When `addr` is nonzero, this function will attempt to set the end of the process's
/// heap to `addr` and return the new program break. The new program break should be
/// checked by the allocator, it may not be exactly `addr`, as it may be aligned to a page
/// boundary.
///
/// On error, `Err(ENOMEM)` will be returned indicating that no memory is available
pub unsafe fn brk(addr: usize) -> Result<usize> {
    syscall1(SYS_BRK, addr)
}

/// Change the process's working directory
///
/// This function will attempt to set the process's working directory to `path`, which can be
/// either a relative, scheme relative, or absolute path.
///
/// On success, `Ok(0)` will be returned. On error, one of the following errors will be returned.
///
/// # Errors
///
/// * `EACCES` - permission is denied for one of the components of `path`, or `path`
/// * `EFAULT` - `path` does not point to the process's addressible memory
39
/// * `EIO` - an I/O error occurred
Jeremy Soller's avatar
Jeremy Soller committed
40
41
/// * `ENOENT` - `path` does not exit
/// * `ENOTDIR` - `path` is not a directory
42
43
pub fn chdir<T: AsRef<[u8]>>(path: T) -> Result<usize> {
    unsafe { syscall2(SYS_CHDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
Jeremy Soller's avatar
Jeremy Soller committed
44
45
}

46
47
pub fn chmod<T: AsRef<[u8]>>(path: T, mode: usize) -> Result<usize> {
    unsafe { syscall3(SYS_CHMOD, path.as_ref().as_ptr() as usize, path.as_ref().len(), mode) }
48
49
}

Jeremy Soller's avatar
Jeremy Soller committed
50
/// Produce a fork of the current process, or a new process thread
Jeremy Soller's avatar
Jeremy Soller committed
51
52
53
54
pub unsafe fn clone(flags: usize) -> Result<usize> {
    syscall1_clobber(SYS_CLONE, flags)
}

Jeremy Soller's avatar
Jeremy Soller committed
55
/// Close a file
Jeremy Soller's avatar
Jeremy Soller committed
56
57
58
59
pub fn close(fd: usize) -> Result<usize> {
    unsafe { syscall1(SYS_CLOSE, fd) }
}

Jeremy Soller's avatar
Jeremy Soller committed
60
/// Get the current system time
Jeremy Soller's avatar
Jeremy Soller committed
61
62
63
64
pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize> {
    unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
}

Jeremy Soller's avatar
Jeremy Soller committed
65
/// Copy and transform a file descriptor
Jeremy Soller's avatar
Jeremy Soller committed
66
67
68
69
pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
    unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
70
71
/// Copy and transform a file descriptor
pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
72
    unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) }
Jeremy Soller's avatar
Jeremy Soller committed
73
74
}

Jeremy Soller's avatar
Jeremy Soller committed
75
/// Exit the current process
Jeremy Soller's avatar
Jeremy Soller committed
76
77
78
79
pub fn exit(status: usize) -> Result<usize> {
    unsafe { syscall1(SYS_EXIT, status) }
}

Jeremy Soller's avatar
Jeremy Soller committed
80
81
82
83
84
85
86
87
88
89
90
91
92
/// Change file permissions
pub fn fchmod(fd: usize, mode: u16) -> Result<usize> {
    unsafe { syscall2(SYS_FCHMOD, fd, mode as usize) }

}

/// Change file ownership
pub fn fchown(fd: usize, uid: u32, gid: u32) -> Result<usize> {
    unsafe { syscall3(SYS_FCHOWN, fd, uid as usize, gid as usize) }

}

/// Change file descriptor flags
Jeremy Soller's avatar
Jeremy Soller committed
93
94
95
96
pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
    unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
}

97
/// Replace the current process with a new executable
Jeremy Soller's avatar
Jeremy Soller committed
98
pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usize> {
99
100
101
    unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(), vars.as_ptr() as usize, vars.len()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
102
/// Map a file into memory
Jeremy Soller's avatar
Jeremy Soller committed
103
104
105
106
pub unsafe fn fmap(fd: usize, offset: usize, size: usize) -> Result<usize> {
    syscall3(SYS_FMAP, fd, offset, size)
}

Jeremy Soller's avatar
Jeremy Soller committed
107
/// Unmap a memory-mapped file
Jeremy Soller's avatar
Jeremy Soller committed
108
109
110
111
pub unsafe fn funmap(addr: usize) -> Result<usize> {
    syscall1(SYS_FUNMAP, addr)
}

Jeremy Soller's avatar
Jeremy Soller committed
112
/// Retrieve the canonical path of a file
Jeremy Soller's avatar
Jeremy Soller committed
113
114
115
116
pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> {
    unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
117
118
119
120
121
/// Rename a file
pub fn frename<T: AsRef<[u8]>>(fd: usize, path: T) -> Result<usize> {
    unsafe { syscall3(SYS_FRENAME, fd, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
122
/// Get metadata about a file
Jeremy Soller's avatar
Jeremy Soller committed
123
124
125
126
pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
    unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::<Stat>()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
127
128
129
130
131
/// Get metadata about a filesystem
pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> {
    unsafe { syscall3(SYS_FSTATVFS, fd, stat as *mut StatVfs as usize, mem::size_of::<StatVfs>()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
132
/// Sync a file descriptor to its underlying medium
Jeremy Soller's avatar
Jeremy Soller committed
133
134
135
136
pub fn fsync(fd: usize) -> Result<usize> {
    unsafe { syscall1(SYS_FSYNC, fd) }
}

Jeremy Soller's avatar
Jeremy Soller committed
137
/// Truncate or extend a file to a specified length
Jeremy Soller's avatar
Jeremy Soller committed
138
139
140
141
pub fn ftruncate(fd: usize, len: usize) -> Result<usize> {
    unsafe { syscall2(SYS_FTRUNCATE, fd, len) }
}

Jeremy Soller's avatar
Jeremy Soller committed
142
143
144
145
146
// Change modify and/or access times
pub fn futimens(fd: usize, times: &[TimeSpec]) -> Result<usize> {
    unsafe { syscall3(SYS_FUTIMENS, fd, times.as_ptr() as usize, times.len() * mem::size_of::<TimeSpec>()) }
}

147
148
149
/// Fast userspace mutex
pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32)
                    -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
150
151
152
    syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize)
}

Jeremy Soller's avatar
Jeremy Soller committed
153
/// Get the current working directory
Jeremy Soller's avatar
Jeremy Soller committed
154
155
156
157
pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
    unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
158
/// Get the effective group ID
Jeremy Soller's avatar
Jeremy Soller committed
159
160
161
162
pub fn getegid() -> Result<usize> {
    unsafe { syscall0(SYS_GETEGID) }
}

Jeremy Soller's avatar
Jeremy Soller committed
163
164
165
166
167
/// Get the effective namespace
pub fn getens() -> Result<usize> {
    unsafe { syscall0(SYS_GETENS) }
}

Jeremy Soller's avatar
Jeremy Soller committed
168
/// Get the effective user ID
Jeremy Soller's avatar
Jeremy Soller committed
169
170
171
172
pub fn geteuid() -> Result<usize> {
    unsafe { syscall0(SYS_GETEUID) }
}

Jeremy Soller's avatar
Jeremy Soller committed
173
/// Get the current group ID
Jeremy Soller's avatar
Jeremy Soller committed
174
175
176
177
pub fn getgid() -> Result<usize> {
    unsafe { syscall0(SYS_GETGID) }
}

Jeremy Soller's avatar
Jeremy Soller committed
178
179
180
181
182
/// Get the current namespace
pub fn getns() -> Result<usize> {
    unsafe { syscall0(SYS_GETNS) }
}

Jeremy Soller's avatar
Jeremy Soller committed
183
/// Get the current process ID
Jeremy Soller's avatar
Jeremy Soller committed
184
185
186
187
pub fn getpid() -> Result<usize> {
    unsafe { syscall0(SYS_GETPID) }
}

Jeremy Soller's avatar
Jeremy Soller committed
188
189
190
191
192
/// Get the process group ID
pub fn getpgid(pid: usize) -> Result<usize> {
    unsafe { syscall1(SYS_GETPGID, pid) }
}

Ian Douglas Scott's avatar
getppid    
Ian Douglas Scott committed
193
194
195
196
197
/// Get the parent process ID
pub fn getppid() -> Result<usize> {
    unsafe { syscall0(SYS_GETPPID) }
}

Jeremy Soller's avatar
Jeremy Soller committed
198
/// Get the current user ID
Jeremy Soller's avatar
Jeremy Soller committed
199
200
201
202
pub fn getuid() -> Result<usize> {
    unsafe { syscall0(SYS_GETUID) }
}

Jeremy Soller's avatar
Jeremy Soller committed
203
/// Set the I/O privilege level
204
205
206
207
208
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `EINVAL` - `level > 3`
Jeremy Soller's avatar
Jeremy Soller committed
209
210
211
212
pub unsafe fn iopl(level: usize) -> Result<usize> {
    syscall1(SYS_IOPL, level)
}

Jeremy Soller's avatar
Jeremy Soller committed
213
/// Send a signal `sig` to the process identified by `pid`
Jeremy Soller's avatar
Jeremy Soller committed
214
215
216
217
pub fn kill(pid: usize, sig: usize) -> Result<usize> {
    unsafe { syscall2(SYS_KILL, pid, sig) }
}

Jeremy Soller's avatar
Jeremy Soller committed
218
/// Create a link to a file
Jeremy Soller's avatar
Jeremy Soller committed
219
220
221
222
pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
    syscall2(SYS_LINK, old as usize, new as usize)
}

Jeremy Soller's avatar
Jeremy Soller committed
223
/// Seek to `offset` bytes in a file descriptor
Jeremy Soller's avatar
Jeremy Soller committed
224
225
226
227
pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> {
    unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) }
}

Jeremy Soller's avatar
Jeremy Soller committed
228
229
230
231
232
/// Make a new scheme namespace
pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
    unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
233
/// Sleep for the time specified in `req`
Jeremy Soller's avatar
Jeremy Soller committed
234
pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
235
236
    unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize,
                                     rem as *mut TimeSpec as usize) }
Jeremy Soller's avatar
Jeremy Soller committed
237
238
}

Jeremy Soller's avatar
Jeremy Soller committed
239
/// Open a file
240
241
pub fn open<T: AsRef<[u8]>>(path: T, flags: usize) -> Result<usize> {
    unsafe { syscall3(SYS_OPEN, path.as_ref().as_ptr() as usize, path.as_ref().len(), flags) }
Jeremy Soller's avatar
Jeremy Soller committed
242
243
}

Jeremy Soller's avatar
Jeremy Soller committed
244
/// Allocate pages, linearly in physical memory
245
246
247
248
249
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `ENOMEM` - the system has run out of available memory
Jeremy Soller's avatar
Jeremy Soller committed
250
251
252
253
pub unsafe fn physalloc(size: usize) -> Result<usize> {
    syscall1(SYS_PHYSALLOC, size)
}

Jeremy Soller's avatar
Jeremy Soller committed
254
/// Free physically allocated pages
255
256
257
258
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
Jeremy Soller's avatar
Jeremy Soller committed
259
260
261
262
pub unsafe fn physfree(physical_address: usize, size: usize) -> Result<usize> {
    syscall2(SYS_PHYSFREE, physical_address, size)
}

Jeremy Soller's avatar
Jeremy Soller committed
263
/// Map physical memory to virtual memory
264
265
266
267
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
Jeremy Soller's avatar
Jeremy Soller committed
268
269
270
271
pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
    syscall3(SYS_PHYSMAP, physical_address, size, flags)
}

Jeremy Soller's avatar
Jeremy Soller committed
272
/// Unmap previously mapped physical memory
273
274
275
276
277
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `EFAULT` - `virtual_address` has not been mapped
Jeremy Soller's avatar
Jeremy Soller committed
278
279
280
281
pub unsafe fn physunmap(virtual_address: usize) -> Result<usize> {
    syscall1(SYS_PHYSUNMAP, virtual_address)
}

Jeremy Soller's avatar
Jeremy Soller committed
282
/// Create a pair of file descriptors referencing the read and write ends of a pipe
Jeremy Soller's avatar
Jeremy Soller committed
283
284
285
286
pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize> {
    unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) }
}

Jeremy Soller's avatar
Jeremy Soller committed
287
/// Read from a file descriptor into a buffer
Jeremy Soller's avatar
Jeremy Soller committed
288
289
290
291
pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
    unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) }
}

Jeremy Soller's avatar
Jeremy Soller committed
292
/// Remove a directory
293
294
pub fn rmdir<T: AsRef<[u8]>>(path: T) -> Result<usize> {
    unsafe { syscall2(SYS_RMDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
Jeremy Soller's avatar
Jeremy Soller committed
295
296
}

Jeremy Soller's avatar
Jeremy Soller committed
297
298
299
300
301
/// Set the process group ID
pub fn setpgid(pid: usize, pgid: usize) -> Result<usize> {
    unsafe { syscall2(SYS_SETPGID, pid, pgid) }
}

302
303
304
/// Set the current process group IDs
pub fn setregid(rgid: usize, egid: usize) -> Result<usize> {
    unsafe { syscall2(SYS_SETREGID, rgid, egid) }
Jeremy Soller's avatar
Jeremy Soller committed
305
306
}

Jeremy Soller's avatar
Jeremy Soller committed
307
308
309
310
311
/// Make a new scheme namespace
pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
    unsafe { syscall2(SYS_SETRENS, rns, ens) }
}

312
313
314
/// Set the current process user IDs
pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> {
    unsafe { syscall2(SYS_SETREUID, ruid, euid) }
Jeremy Soller's avatar
Jeremy Soller committed
315
316
}

Jeremy Soller's avatar
Jeremy Soller committed
317
/// Set up a signal handler
318
319
320
321
322
pub fn sigaction(sig: usize, act: Option<&SigAction>, oldact: Option<&mut SigAction>) -> Result<usize> {
    unsafe { syscall4(SYS_SIGACTION, sig,
                      act.map(|x| x as *const _).unwrap_or_else(ptr::null) as usize,
                      oldact.map(|x| x as *mut _).unwrap_or_else(ptr::null_mut) as usize,
                      restorer as usize) }
323
324
325
326
327
}

// Return from signal handler
pub fn sigreturn() -> Result<usize> {
    unsafe { syscall0(SYS_SIGRETURN) }
Jeremy Soller's avatar
Jeremy Soller committed
328
329
}

Jeremy Soller's avatar
Jeremy Soller committed
330
331
332
333
334
/// Set the file mode creation mask
pub unsafe fn umask(mask: usize) -> Result<usize> {
    syscall1(SYS_UMASK, mask)
}

Jeremy Soller's avatar
Jeremy Soller committed
335
/// Remove a file
336
337
pub fn unlink<T: AsRef<[u8]>>(path: T) -> Result<usize> {
    unsafe { syscall2(SYS_UNLINK, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
Jeremy Soller's avatar
Jeremy Soller committed
338
339
}

Jeremy Soller's avatar
Jeremy Soller committed
340
/// Convert a virtual address to a physical one
341
342
343
344
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
Jeremy Soller's avatar
Jeremy Soller committed
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
    syscall1(SYS_VIRTTOPHYS, virtual_address)
}

/// Check if a child process has exited or received a signal
pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result<usize> {
    unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) }
}

/// Write a buffer to a file descriptor
///
/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning
/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which
/// were written.
///
/// # Errors
///
/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
/// * `EBADF` - the file descriptor is not valid or is not open for writing
/// * `EFAULT` - `buf` does not point to the process's addressible memory
365
/// * `EIO` - an I/O error occurred
Jeremy Soller's avatar
Jeremy Soller committed
366
367
368
369
370
371
372
373
374
375
376
377
/// * `ENOSPC` - the device containing the file descriptor has no room for data
/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
    unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) }
}

/// Yield the process's time slice to the kernel
///
/// This function will return Ok(0) on success
pub fn sched_yield() -> Result<usize> {
    unsafe { syscall0(SYS_YIELD) }
}