647 lines
19 KiB
Rust
647 lines
19 KiB
Rust
use core::{mem, slice, str};
|
|
|
|
use alloc::vec::Vec;
|
|
use ioslice::IoSlice;
|
|
use redox_path::RedoxStr;
|
|
use redox_protocols::protocol::{ProcKillTarget, SocketCall, WaitFlags};
|
|
use redox_rt::sys::{WaitpidTarget, posix_read, posix_write, std_fs_call_ro, std_fs_call_wo};
|
|
use syscall::{
|
|
EMFILE, ENAMETOOLONG, ENOSYS, EOPNOTSUPP, Error, Result, StdFsCallKind,
|
|
data::StdFsCallMeta,
|
|
dirent::{DirentHeader, DirentKind},
|
|
};
|
|
|
|
use crate::{
|
|
header::{
|
|
errno::EINVAL, fcntl::AT_FDCWD, signal::sigaction, sys_stat::UTIME_NOW, sys_uio::iovec,
|
|
time::timespec,
|
|
},
|
|
out::Out,
|
|
platform::{PalSignal, pal::Pal, types::*},
|
|
};
|
|
|
|
use super::Sys;
|
|
|
|
pub type RawResult = usize;
|
|
|
|
pub fn openat(dirfd: c_int, path: RedoxStr<'_>, oflag: c_int, mode: mode_t) -> Result<usize> {
|
|
let usize_fd = super::path::openat(
|
|
dirfd,
|
|
path,
|
|
((oflag as usize) & 0xFFFF_0000) | ((mode as usize) & 0xFFFF),
|
|
)?;
|
|
|
|
if let Err(_) = c_int::try_from(usize_fd) {
|
|
let _ = redox_rt::sys::close(usize_fd);
|
|
return Err(Error::new(EMFILE));
|
|
}
|
|
Ok(usize_fd)
|
|
}
|
|
|
|
pub fn fchmod(fd: usize, new_mode: u16) -> Result<()> {
|
|
std_fs_call_wo(
|
|
fd,
|
|
&[],
|
|
&StdFsCallMeta::new(StdFsCallKind::Fchmod, new_mode as u64, 0),
|
|
)?;
|
|
Ok(())
|
|
}
|
|
pub fn fchown(fd: usize, new_uid: u32, new_gid: u32) -> Result<()> {
|
|
/* std_fs_call
|
|
Error::mux(std_fs_call_wo(
|
|
fd,
|
|
&[],
|
|
&StdFsCallMeta::new(
|
|
StdFsCallKind::Fchmod,
|
|
(new_uid as u64) | ((new_gid as u64) << 32),
|
|
0,
|
|
),
|
|
))
|
|
*/
|
|
syscall::fchown(fd, new_uid, new_gid)?;
|
|
Ok(())
|
|
}
|
|
pub fn getdents(fd: usize, buf: &mut [u8], opaque: u64) -> Result<usize> {
|
|
//println!("GETDENTS {} into ({:p}+{})", fd, buf.as_ptr(), buf.len());
|
|
|
|
const HEADER_SIZE: usize = mem::size_of::<DirentHeader>();
|
|
|
|
// Use syscall if it exists.
|
|
match std_fs_call_ro(
|
|
fd,
|
|
buf,
|
|
&StdFsCallMeta::new(StdFsCallKind::Getdents, opaque, HEADER_SIZE as u64),
|
|
) {
|
|
Err(Error {
|
|
errno: EOPNOTSUPP | ENOSYS,
|
|
}) => (),
|
|
other => {
|
|
//println!("REAL GETDENTS {:?}", other);
|
|
return Ok(other?);
|
|
}
|
|
}
|
|
|
|
// Otherwise, for legacy schemes, assume the buffer is pre-arranged (all schemes do this in
|
|
// practice), and just read the name. If multiple names appear, pretend it didn't happen
|
|
// and just use the first entry.
|
|
|
|
let (header, name) = buf.split_at_mut(mem::size_of::<DirentHeader>());
|
|
|
|
let bytes_read = Sys::pread(fd as c_int, name, opaque as i64)? as usize;
|
|
if bytes_read == 0 {
|
|
return Ok(0);
|
|
}
|
|
|
|
let (name_len, advance) = match name[..bytes_read].iter().position(|c| *c == b'\n') {
|
|
Some(idx) => (idx, idx + 1),
|
|
|
|
// Insufficient space for NUL byte, or entire entry was not read. Indicate we need a
|
|
// larger buffer.
|
|
None if bytes_read == name.len() => return Err(Error::new(EINVAL)),
|
|
|
|
None => (bytes_read, name.len()),
|
|
};
|
|
name[name_len] = b'\0';
|
|
|
|
let record_len = u16::try_from(mem::size_of::<DirentHeader>() + name_len + 1)
|
|
.map_err(|_| Error::new(ENAMETOOLONG))?;
|
|
header.copy_from_slice(&DirentHeader {
|
|
inode: 0,
|
|
next_opaque_id: opaque + advance as u64,
|
|
record_len,
|
|
kind: DirentKind::Unspecified as u8,
|
|
});
|
|
//println!("EMULATED GETDENTS");
|
|
|
|
Ok(record_len.into())
|
|
}
|
|
pub unsafe fn fstat(fd: usize, buf: *mut crate::header::sys_stat::stat) -> Result<()> {
|
|
let mut redox_buf: syscall::Stat = Default::default();
|
|
redox_rt::sys::fstat(fd, &mut redox_buf)?;
|
|
|
|
if let Some(buf) = unsafe { buf.as_mut() } {
|
|
buf.st_dev = redox_buf.st_dev as dev_t;
|
|
buf.st_ino = redox_buf.st_ino as ino_t;
|
|
buf.st_nlink = redox_buf.st_nlink as nlink_t;
|
|
buf.st_mode = redox_buf.st_mode as mode_t;
|
|
buf.st_uid = redox_buf.st_uid as uid_t;
|
|
buf.st_gid = redox_buf.st_gid as gid_t;
|
|
// TODO st_rdev
|
|
buf.st_rdev = 0;
|
|
buf.st_size = redox_buf.st_size as off_t;
|
|
buf.st_blksize = redox_buf.st_blksize as blksize_t;
|
|
buf.st_blocks = redox_buf.st_blocks as blkcnt_t;
|
|
buf.st_atim = timespec {
|
|
tv_sec: redox_buf.st_atime as time_t,
|
|
tv_nsec: redox_buf.st_atime_nsec as c_long,
|
|
};
|
|
buf.st_mtim = timespec {
|
|
tv_sec: redox_buf.st_mtime as time_t,
|
|
tv_nsec: redox_buf.st_mtime_nsec as c_long,
|
|
};
|
|
buf.st_ctim = timespec {
|
|
tv_sec: redox_buf.st_ctime as time_t,
|
|
tv_nsec: redox_buf.st_ctime_nsec as c_long,
|
|
};
|
|
}
|
|
Ok(())
|
|
}
|
|
pub unsafe fn fstatvfs(fd: usize, buf: *mut crate::header::sys_statvfs::statvfs) -> Result<()> {
|
|
let mut kbuf: syscall::StatVfs = Default::default();
|
|
std_fs_call_ro(
|
|
fd,
|
|
&mut kbuf,
|
|
&StdFsCallMeta::new(StdFsCallKind::Fstatvfs, 0, 0),
|
|
)?;
|
|
|
|
if !buf.is_null() {
|
|
unsafe {
|
|
(*buf).f_bsize = kbuf.f_bsize as c_ulong;
|
|
(*buf).f_frsize = kbuf.f_bsize as c_ulong;
|
|
(*buf).f_blocks = kbuf.f_blocks as c_ulong;
|
|
(*buf).f_bfree = kbuf.f_bfree as c_ulong;
|
|
(*buf).f_bavail = kbuf.f_bavail as c_ulong;
|
|
//TODO
|
|
(*buf).f_files = 0;
|
|
(*buf).f_ffree = 0;
|
|
(*buf).f_favail = 0;
|
|
(*buf).f_fsid = 0;
|
|
(*buf).f_flag = 0;
|
|
(*buf).f_namemax = 0;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn fsync(fd: usize) -> Result<()> {
|
|
std_fs_call_wo(fd, &[], &StdFsCallMeta::new(StdFsCallKind::Fsync, 0, 0))?;
|
|
Ok(())
|
|
}
|
|
pub fn ftruncate(fd: usize, len: usize) -> Result<()> {
|
|
std_fs_call_wo(
|
|
fd,
|
|
&[],
|
|
&StdFsCallMeta::new(StdFsCallKind::Ftruncate, len as u64, 0),
|
|
)?;
|
|
Ok(())
|
|
}
|
|
pub unsafe fn futimens(fd: usize, times: *const timespec) -> Result<()> {
|
|
let times = if times.is_null() {
|
|
// null means set to current time using special UTIME_NOW value (tv_sec is ignored in that case)
|
|
[
|
|
syscall::TimeSpec {
|
|
tv_sec: 0,
|
|
tv_nsec: UTIME_NOW as c_int,
|
|
},
|
|
syscall::TimeSpec {
|
|
tv_sec: 0,
|
|
tv_nsec: UTIME_NOW as c_int,
|
|
},
|
|
]
|
|
} else {
|
|
unsafe { times.cast::<[timespec; 2]>().read() }.map(|ts| syscall::TimeSpec::from(&ts))
|
|
};
|
|
let redox_buf = unsafe {
|
|
slice::from_raw_parts(
|
|
times.as_ptr() as *const u8,
|
|
times.len() * mem::size_of::<syscall::TimeSpec>(),
|
|
)
|
|
};
|
|
std_fs_call_wo(
|
|
fd,
|
|
redox_buf,
|
|
&StdFsCallMeta::new(StdFsCallKind::Futimens, 0, 0),
|
|
)?;
|
|
Ok(())
|
|
}
|
|
pub fn clock_gettime(clock: usize, mut tp: Out<timespec>) -> Result<()> {
|
|
let mut redox_tp = syscall::TimeSpec::default();
|
|
syscall::clock_gettime(clock as usize, &mut redox_tp)?;
|
|
tp.write((&redox_tp).into());
|
|
Ok(())
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_open_v1(
|
|
path_base: *const u8,
|
|
path_len: usize,
|
|
flags: u32,
|
|
mode: u16,
|
|
) -> RawResult {
|
|
let path = unsafe { str::from_utf8_unchecked(slice::from_raw_parts(path_base, path_len)) };
|
|
let path = match RedoxStr::new(path) {
|
|
Some(path) => path,
|
|
None => return Error::mux(Err(Error::new(EINVAL))),
|
|
};
|
|
Error::mux(openat(AT_FDCWD, path, flags as c_int, mode as mode_t))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_openat_v1(
|
|
fd: usize,
|
|
path_base: *const u8,
|
|
path_len: usize,
|
|
flags: u32,
|
|
fcntl_flags: u32,
|
|
) -> RawResult {
|
|
// Goes straight to redox_rt, no need parsing RedoxStr
|
|
let path = unsafe { str::from_utf8_unchecked(slice::from_raw_parts(path_base, path_len)) };
|
|
Error::mux(redox_rt::sys::openat(
|
|
fd,
|
|
path,
|
|
flags as usize,
|
|
fcntl_flags as usize,
|
|
))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_dup_v1(fd: usize, buf: *const u8, len: usize) -> RawResult {
|
|
Error::mux(redox_rt::sys::dup(fd, unsafe {
|
|
core::slice::from_raw_parts(buf, len)
|
|
}))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_dup2_v1(
|
|
old_fd: usize,
|
|
new_fd: usize,
|
|
buf: *const u8,
|
|
len: usize,
|
|
) -> RawResult {
|
|
Error::mux(redox_rt::sys::dup2(old_fd, new_fd, unsafe {
|
|
core::slice::from_raw_parts(buf, len)
|
|
}))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_read_v1(fd: usize, dst_base: *mut u8, dst_len: usize) -> RawResult {
|
|
Error::mux(posix_read(fd, unsafe {
|
|
slice::from_raw_parts_mut(dst_base, dst_len)
|
|
}))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_write_v1(
|
|
fd: usize,
|
|
src_base: *const u8,
|
|
src_len: usize,
|
|
) -> RawResult {
|
|
Error::mux(posix_write(fd, unsafe {
|
|
slice::from_raw_parts(src_base, src_len)
|
|
}))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_fchmod_v1(fd: usize, new_mode: u16) -> RawResult {
|
|
Error::mux(fchmod(fd, new_mode).map(|()| 0))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_fchown_v1(fd: usize, new_uid: u32, new_gid: u32) -> RawResult {
|
|
Error::mux(fchown(fd, new_uid, new_gid).map(|()| 0))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_getdents_v0(
|
|
fd: usize,
|
|
buf: *mut u8,
|
|
buf_len: usize,
|
|
opaque: u64,
|
|
) -> RawResult {
|
|
Error::mux(
|
|
Sys::getdents(
|
|
fd as c_int,
|
|
unsafe { slice::from_raw_parts_mut(buf, buf_len) },
|
|
opaque,
|
|
)
|
|
.map_err(Into::into),
|
|
)
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_fstat_v1(
|
|
fd: usize,
|
|
stat: *mut crate::header::sys_stat::stat,
|
|
) -> RawResult {
|
|
Error::mux(unsafe { fstat(fd, stat) }.map(|()| 0))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_fstatvfs_v1(
|
|
fd: usize,
|
|
stat: *mut crate::header::sys_statvfs::statvfs,
|
|
) -> RawResult {
|
|
Error::mux(unsafe { fstatvfs(fd, stat) }.map(|()| 0))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_fsync_v1(fd: usize) -> RawResult {
|
|
Error::mux(fsync(fd).map(|()| 0))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_fdatasync_v1(fd: usize) -> RawResult {
|
|
// TODO
|
|
Error::mux(fsync(fd).map(|()| 0))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_ftruncate_v0(fd: usize, len: usize) -> RawResult {
|
|
Error::mux(ftruncate(fd, len).map(|()| 0))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_futimens_v1(fd: usize, times: *const timespec) -> RawResult {
|
|
Error::mux(unsafe { futimens(fd, times) }.map(|()| 0))
|
|
}
|
|
/* TODO: Support unlinkat
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_unlinkat_v0(
|
|
fd: usize,
|
|
path_base: *const u8,
|
|
path_len: usize,
|
|
flags: u32,
|
|
) -> RawResult {
|
|
Error::mux(std_fs_call_wo(
|
|
fd,
|
|
unsafe { slice::from_raw_parts(path_base, path_len) },
|
|
&StdFsCallMeta::new(StdFsCallKind::Unlinkat, flags as u64, 0),
|
|
))
|
|
}
|
|
*/
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_fpath_v1(fd: usize, dst_base: *mut u8, dst_len: usize) -> RawResult {
|
|
Error::mux(syscall::fpath(fd, unsafe {
|
|
core::slice::from_raw_parts_mut(dst_base, dst_len)
|
|
}))
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_close_v1(fd: usize) -> RawResult {
|
|
Error::mux(redox_rt::sys::close(fd))
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_pid_v1() -> RawResult {
|
|
redox_rt::sys::posix_getpid() as _
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_euid_v1() -> RawResult {
|
|
redox_rt::sys::posix_getresugid().euid as _
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_ruid_v1() -> RawResult {
|
|
redox_rt::sys::posix_getresugid().ruid as _
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_egid_v1() -> RawResult {
|
|
redox_rt::sys::posix_getresugid().egid as _
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_rgid_v1() -> RawResult {
|
|
redox_rt::sys::posix_getresugid().rgid as _
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_ens_v0() -> RawResult {
|
|
Error::mux(redox_rt::sys::getens())
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_ns_v0() -> RawResult {
|
|
Error::mux(redox_rt::sys::getns())
|
|
}
|
|
#[allow(improper_ctypes_definitions)]
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_proc_credentials_v1(
|
|
cap_fd: usize,
|
|
target_pid: usize,
|
|
buf: &mut [u8], // not FFI safe
|
|
) -> RawResult {
|
|
Error::mux(redox_rt::sys::get_proc_credentials(cap_fd, target_pid, buf))
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_setrens_v1(rns: usize, ens: usize) -> RawResult {
|
|
let _ = if ens == 0 {
|
|
let null_namespace: [IoSlice; 2] = [IoSlice::new(b"memory"), IoSlice::new(b"pipe")];
|
|
match redox_rt::sys::mkns(&null_namespace) {
|
|
Ok(new_ns_fd) => redox_rt::sys::setns(new_ns_fd.take()),
|
|
Err(e) => return Error::mux(Err(e)),
|
|
}
|
|
} else {
|
|
redox_rt::sys::setns(ens)
|
|
};
|
|
0
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_waitpid_v1(pid: usize, status: *mut i32, options: u32) -> RawResult {
|
|
let mut sts = 0_usize;
|
|
let res = Error::mux(redox_rt::sys::sys_waitpid(
|
|
WaitpidTarget::from_posix_arg(pid as isize),
|
|
&mut sts,
|
|
WaitFlags::from_bits_truncate(options as usize),
|
|
));
|
|
unsafe { status.write(sts as i32) };
|
|
res
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_kill_v1(pid: usize, signal: u32) -> RawResult {
|
|
Error::mux(
|
|
redox_rt::sys::posix_kill(ProcKillTarget::from_raw(pid), signal as usize).map(|()| 0),
|
|
)
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_sigaction_v1(
|
|
signal: u32,
|
|
new: *const sigaction,
|
|
old: *mut sigaction,
|
|
) -> RawResult {
|
|
Error::mux(
|
|
Sys::sigaction(signal as c_int, unsafe { new.as_ref() }, unsafe {
|
|
old.as_mut()
|
|
})
|
|
.map(|()| 0)
|
|
.map_err(Into::into),
|
|
)
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_sigprocmask_v1(
|
|
how: u32,
|
|
new: *const u64,
|
|
old: *mut u64,
|
|
) -> RawResult {
|
|
Error::mux(
|
|
Sys::sigprocmask(how as c_int, unsafe { new.as_ref() }, unsafe {
|
|
old.as_mut()
|
|
})
|
|
.map(|()| 0)
|
|
.map_err(Into::into),
|
|
)
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_mmap_v1(
|
|
addr: *mut (),
|
|
unaligned_len: usize,
|
|
prot: u32,
|
|
flags: u32,
|
|
fd: usize,
|
|
offset: u64,
|
|
) -> RawResult {
|
|
Error::mux(unsafe {
|
|
syscall::fmap(
|
|
fd,
|
|
&syscall::Map {
|
|
address: addr as usize,
|
|
offset: offset as usize,
|
|
size: unaligned_len,
|
|
flags: syscall::MapFlags::from_bits_truncate(
|
|
((prot << 16) | (flags & 0xffff)) as usize,
|
|
),
|
|
},
|
|
)
|
|
})
|
|
}
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_munmap_v1(addr: *mut (), unaligned_len: usize) -> RawResult {
|
|
Error::mux(unsafe { syscall::funmap(addr as usize, unaligned_len) })
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_clock_gettime_v1(clock: usize, ts: *mut timespec) -> RawResult {
|
|
Error::mux(clock_gettime(clock, unsafe { Out::nonnull(ts) }).map(|()| 0))
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_strerror_v1(
|
|
buf: *mut u8,
|
|
buflen: *mut usize,
|
|
error: u32,
|
|
) -> RawResult {
|
|
let dst = unsafe { core::slice::from_raw_parts_mut(buf, buflen.read()) };
|
|
|
|
Error::mux((|| {
|
|
// TODO: Merge syscall::error::STR_ERROR into crate::header::error::?
|
|
|
|
let src = syscall::error::STR_ERROR
|
|
.get(error as usize)
|
|
.ok_or(Error::new(EINVAL))?;
|
|
|
|
// This API ensures that the returned buffer is proper UTF-8. Thus, it returns both the
|
|
// copied length and the actual length.
|
|
|
|
unsafe { buflen.write(src.len()) };
|
|
|
|
let raw_len = core::cmp::min(dst.len(), src.len());
|
|
let len = match core::str::from_utf8(&src.as_bytes()[..raw_len]) {
|
|
Ok(_valid) => raw_len,
|
|
Err(error) => error.valid_up_to(),
|
|
};
|
|
|
|
dst[..len].copy_from_slice(&src.as_bytes()[..len]);
|
|
Ok(len)
|
|
})())
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_mkns_v1(
|
|
names: *const iovec,
|
|
num_names: usize,
|
|
flags: u32,
|
|
) -> RawResult {
|
|
Error::mux((|| {
|
|
if flags != 0 {
|
|
return Err(Error::new(EINVAL));
|
|
}
|
|
let raw_iovecs = unsafe { slice::from_raw_parts(names, num_names) };
|
|
let names_ioslice: Vec<IoSlice> = raw_iovecs
|
|
.iter()
|
|
.map(|iov| {
|
|
IoSlice::new(unsafe {
|
|
slice::from_raw_parts(iov.iov_base as *const u8, iov.iov_len)
|
|
})
|
|
})
|
|
.collect();
|
|
redox_rt::sys::mkns(&names_ioslice).map(|fd| fd.take())
|
|
})())
|
|
}
|
|
|
|
// ABI-UNSTABLE
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_cur_procfd_v0() -> usize {
|
|
redox_rt::current_proc_fd().as_raw_fd()
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_cur_thrfd_v0() -> usize {
|
|
redox_rt::RtTcb::current().thread_fd().as_raw_fd()
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_sys_call_v0(
|
|
fd: usize,
|
|
payload: *mut u8,
|
|
payload_len: usize,
|
|
flags: usize,
|
|
metadata: *const u64,
|
|
metadata_len: usize,
|
|
) -> RawResult {
|
|
let flags = syscall::CallFlags::from_bits_retain(flags);
|
|
let read = flags.contains(syscall::CallFlags::READ);
|
|
let write = flags.contains(syscall::CallFlags::WRITE);
|
|
let payload = unsafe { slice::from_raw_parts_mut(payload, payload_len) };
|
|
let metadata = unsafe { slice::from_raw_parts(metadata, metadata_len) };
|
|
|
|
Error::mux(match (read, write) {
|
|
(true, true) => redox_rt::sys::sys_call_rw(fd, payload, flags, metadata),
|
|
(true, false) => redox_rt::sys::sys_call_ro(fd, payload, flags, metadata),
|
|
(false, true) => redox_rt::sys::sys_call_wo(fd, payload, flags, metadata),
|
|
(false, false) => redox_rt::sys::sys_call(fd, payload, flags, metadata),
|
|
})
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_get_socket_token_v0(
|
|
fd: usize,
|
|
payload: *mut u8,
|
|
payload_len: usize,
|
|
) -> RawResult {
|
|
let metadata = [SocketCall::GetToken as u64];
|
|
Error::mux(redox_rt::sys::sys_call_ro(
|
|
fd,
|
|
unsafe { slice::from_raw_parts_mut(payload, payload_len) },
|
|
syscall::CallFlags::empty(),
|
|
&metadata,
|
|
))
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_setns_v0(fd: usize) -> RawResult {
|
|
match redox_rt::sys::setns(fd) {
|
|
Some(guard) => guard.take(),
|
|
None => usize::MAX,
|
|
}
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_register_scheme_to_ns_v0(
|
|
ns_fd: usize,
|
|
name_base: *const u8,
|
|
name_len: usize,
|
|
cap_fd: usize,
|
|
) -> RawResult {
|
|
Error::mux(
|
|
redox_rt::sys::register_scheme_to_ns(
|
|
ns_fd,
|
|
unsafe { str::from_utf8_unchecked(slice::from_raw_parts(name_base, name_len)) },
|
|
cap_fd,
|
|
)
|
|
.map(|()| 0),
|
|
)
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_relpathat_v0(
|
|
dirfd: usize,
|
|
fd: usize,
|
|
dst_base: *mut u8,
|
|
dst_len: usize,
|
|
) -> RawResult {
|
|
Error::mux(redox_rt::sys::std_fs_call_ro(
|
|
&[dirfd, fd][..],
|
|
unsafe { slice::from_raw_parts_mut(dst_base, dst_len) },
|
|
&StdFsCallMeta::new(StdFsCallKind::Relpathat, 0, 0),
|
|
))
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn redox_fcntl_v0(fd: usize, cmd: usize, arg: usize) -> RawResult {
|
|
Error::mux(redox_rt::sys::fcntl(fd, cmd, arg))
|
|
}
|