feat: Add multiple fds variant for call and std_fs_call

This commit is contained in:
Ibuki Omatsu
2026-05-27 13:26:37 +00:00
committed by Jacob Lorentzon
parent aa2a276910
commit 7a1409a910
4 changed files with 96 additions and 29 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "redox_syscall"
version = "0.7.5"
version = "0.8.0"
description = "A Rust library to access raw Redox system calls"
license = "MIT"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
+86 -26
View File
@@ -125,7 +125,7 @@ pub fn futimens(fd: usize, times: &[TimeSpec]) -> Result<usize> {
SYS_FUTIMENS,
fd,
times.as_ptr() as usize,
times.len() * mem::size_of::<TimeSpec>(),
mem::size_of_val(times),
)
}
}
@@ -302,49 +302,109 @@ pub fn sendfd(receiver_socket: usize, fd: usize, flags: usize, arg: u64) -> Resu
}
}
pub trait Call {
unsafe fn raw_call(
&self,
payload_ptr: *const u8,
len: usize,
flags: CallFlags,
metadata: &[u64],
) -> Result<usize>;
}
impl Call for usize {
unsafe fn raw_call(
&self,
payload_ptr: *const u8,
len: usize,
flags: CallFlags,
metadata: &[u64],
) -> Result<usize> {
unsafe {
syscall5(
SYS_CALL,
*self,
payload_ptr as usize,
len,
metadata.len() | flags.bits(),
metadata.as_ptr() as usize,
)
}
}
}
impl Call for &[usize] {
unsafe fn raw_call(
&self,
payload_ptr: *const u8,
len: usize,
flags: CallFlags,
metadata: &[u64],
) -> Result<usize> {
let combined_flags = flags | CallFlags::MULTIPLE_FDS;
unsafe {
syscall6(
SYS_CALL,
self.as_ptr() as usize,
payload_ptr as usize,
len,
metadata.len() | combined_flags.bits(),
metadata.as_ptr() as usize,
self.len() * mem::size_of::<usize>(),
)
}
}
}
/// SYS_CALL interface, read-only variant
pub fn call_ro(fd: usize, payload: &mut [u8], flags: CallFlags, metadata: &[u64]) -> Result<usize> {
let combined_flags = flags | CallFlags::READ;
pub fn call_ro<T: Call>(
fd: T,
payload: &mut [u8],
flags: CallFlags,
metadata: &[u64],
) -> Result<usize> {
unsafe {
syscall5(
SYS_CALL,
fd,
payload.as_mut_ptr() as usize,
fd.raw_call(
payload.as_mut_ptr(),
payload.len(),
metadata.len() | combined_flags.bits(),
metadata.as_ptr() as usize,
flags | CallFlags::READ,
metadata,
)
}
}
/// SYS_CALL interface, write-only variant
pub fn call_wo(fd: usize, payload: &[u8], flags: CallFlags, metadata: &[u64]) -> Result<usize> {
let combined_flags = flags | CallFlags::WRITE;
pub fn call_wo<T: Call>(
fd: T,
payload: &[u8],
flags: CallFlags,
metadata: &[u64],
) -> Result<usize> {
unsafe {
syscall5(
SYS_CALL,
fd,
payload.as_ptr() as *mut u8 as usize,
fd.raw_call(
payload.as_ptr(),
payload.len(),
metadata.len() | combined_flags.bits(),
metadata.as_ptr() as usize,
flags | CallFlags::WRITE,
metadata,
)
}
}
/// SYS_CALL interface, read-write variant
pub fn call_rw(fd: usize, payload: &mut [u8], flags: CallFlags, metadata: &[u64]) -> Result<usize> {
let combined_flags = flags | CallFlags::READ | CallFlags::WRITE;
pub fn call_rw<T: Call>(
fd: T,
payload: &mut [u8],
flags: CallFlags,
metadata: &[u64],
) -> Result<usize> {
unsafe {
syscall5(
SYS_CALL,
fd,
payload.as_mut_ptr() as usize,
fd.raw_call(
payload.as_mut_ptr(),
payload.len(),
metadata.len() | combined_flags.bits(),
metadata.as_ptr() as usize,
flags | CallFlags::READ | CallFlags::WRITE,
metadata,
)
}
}
pub fn std_fs_call(fd: usize, payload: &mut [u8], metadata: &StdFsCallMeta) -> Result<usize> {
pub fn std_fs_call<T: Call>(fd: T, payload: &mut [u8], metadata: &StdFsCallMeta) -> Result<usize> {
call_rw(fd, payload, CallFlags::STD_FS, metadata)
}
+5 -2
View File
@@ -405,6 +405,9 @@ bitflags! {
/// Call is a standard fs call, with metadata defined in `StdFsCallMeta`
const STD_FS = 1 << 16;
/// Call is taking multiple fds as an argument
const MULTIPLE_FDS = 1 << 17;
}
}
@@ -422,7 +425,7 @@ pub enum StdFsCallKind {
Futimens = 8,
// 9 reserved in fscall RFC
// Unlinkat = 10,
Realpathat = 11,
Relpathat = 11,
Lock = 12,
Unlock = 13,
GetLock = 14,
@@ -444,7 +447,7 @@ impl StdFsCallKind {
8 => Futimens,
// 9 reserved in fscall RFC
// 10 => Unlinkat,
11 => Realpathat,
11 => Relpathat,
12 => Lock,
13 => Unlock,
14 => GetLock,
+4
View File
@@ -46,6 +46,10 @@ bitflags! {
// If zero, the message is bidirectional, and the scheme is expected to pass the Ksmsg's
// tag field to the Skmsg. Some opcodes require this flag to be set.
const ONEWAY = 1;
// If this flag is set, index 0 of Sqe's args stores the IDs buffer address,
// and index 1 stores the IDs buffer length.
const MULTIPLE_IDS = 1 << 1;
}
}