kernel: add openat_into + dup_into for upstream 0.9.0 syscall API

This commit is contained in:
2026-07-08 00:49:03 +03:00
parent e896c0e08b
commit d1ddac0e2c
4 changed files with 104 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
use alloc::format;
use alloc::vec::Vec;
use crate::{
percpu::get_all_stats,
sync::CleanLockToken,
syscall::error::{Error, Result, ENOENT},
};
/// Format one per-CPU stat line compatible with Linux `/proc/stat`:
/// `user nice system idle iowait irq softirq steal`.
///
/// Redox's scheduler tracks user, nice, kernel, idle, and irq. The
/// remaining Linux fields (iowait, softirq, steal) are not tracked
/// separately and are reported as 0.
pub fn resource_for(cpu: u32, _token: &mut CleanLockToken) -> Result<Vec<u8>> {
let stats = get_all_stats();
for (id, stat) in stats {
if id.get() == cpu {
let line = format!(
"{} {} {} {} {} 0 0 0\n",
stat.user, stat.nice, stat.kernel, stat.idle, stat.irq
);
return Ok(line.into_bytes());
}
}
Err(Error::new(ENOENT))
}
+19
View File
@@ -28,6 +28,7 @@ use super::{CallerCtx, HandleMap, KernelScheme, OpenResult, StrOrBytes};
mod block;
mod context;
mod cpu;
mod cpu_stat;
mod exe;
mod fdstat;
mod iostat;
@@ -213,6 +214,24 @@ impl KernelScheme for SysScheme {
if path.is_empty() {
let id = HANDLES.write(token.token()).insert(Handle::TopLevel);
Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED))
} else if let Some(rest) = path.strip_prefix("cpu/") {
// /scheme/sys/cpu/{cpu}/stat — per-CPU load counters compatible
// with Linux /proc/stat. Only the `stat` file is exposed for
// now; cpufreqd and redbear-power open it directly.
let mut parts = rest.split('/').filter(|p| !p.is_empty());
let cpu_str = parts.next().ok_or(Error::new(EINVAL))?;
let file = parts.next().ok_or(Error::new(EINVAL))?;
if parts.next().is_some() || file != "stat" {
return Err(Error::new(ENOENT));
}
let cpu: u32 = cpu_str.parse().map_err(|_| Error::new(EINVAL))?;
let data = cpu_stat::resource_for(cpu, token)?;
let id = HANDLES.write(token.token()).insert(Handle::Resource {
path: "cpu_stat",
kind: Kind::Rd(|_| Ok(Vec::new())),
data: Arc::new(RwLock::new(Some(data))),
});
Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED))
} else if path == "msr" || path.starts_with("msr/") {
// /scheme/sys/msr/{cpu}/0x{msr} — Phase G.1: MSR R/W scheme
+43
View File
@@ -126,6 +126,35 @@ pub fn openat(
)
.ok_or(Error::new(EMFILE))
}
/// Open a file at a specific path, placing the result into a reserved fd slot (upstream 0.9.0).
pub fn openat_into(
fh: FileHandle,
raw_path: UserSliceRo,
flags: usize,
fcntl_flags: u32,
new_fd: FileHandle,
token: &mut CleanLockToken,
) -> Result<FileHandle> {
let path_buf = copy_path_to_buf(raw_path, PATH_MAX)?;
let (scheme_id, number) = {
let current_lock = context::current();
let mut current = current_lock.read(token.token());
let (context, mut token) = current.token_split();
let pipe = context.get_file(fh, &mut token).ok_or(Error::new(EBADF))?;
let desc = pipe.description.read(token.token());
(desc.scheme, desc.number)
};
let caller_ctx = context::current().read(token.token()).caller_ctx();
let new_description = {
let scheme = scheme::get_scheme(token.token(), scheme_id)?;
let res = scheme.kopenat(number, StrOrBytes::from_str(&path_buf), flags, fcntl_flags, caller_ctx, token)?;
res?
};
let current_lock = context::current();
let mut current = current_lock.read(token.token());
let (context, mut token) = current.token_split();
context.insert_file(new_fd, new_description, &mut token).ok_or(Error::new(EEXIST))
}
/// Unlinkat syscall
pub fn unlinkat(
fh: FileHandle,
@@ -233,6 +262,20 @@ pub fn dup(fd: FileHandle, buf: UserSliceRo, token: &mut CleanLockToken) -> Resu
.ok_or(Error::new(EMFILE))
}
/// Duplicate a file descriptor, placing into a specific fd slot (upstream 0.9.0).
pub fn dup_into(
fd: FileHandle,
new_fd: FileHandle,
buf: UserSliceRo,
token: &mut CleanLockToken,
) -> Result<FileHandle> {
let new_file = duplicate_file(fd, buf, token)?;
let current_lock = context::current();
let mut current = current_lock.read(token.token());
let (context, mut token) = current.token_split();
context.insert_file(new_fd, new_file, &mut token).ok_or(Error::new(EEXIST))
}
/// Duplicate file descriptor, replacing another
pub fn dup2(
fd: FileHandle,
+14
View File
@@ -153,6 +153,12 @@ pub fn syscall(
}),
SYS_DUP => dup(fd, UserSlice::ro(c, d)?, token).map(FileHandle::into),
SYS_DUP_INTO => dup_into(
fd,
FileHandle::from(e),
UserSlice::ro(c, d)?,
token,
).map(FileHandle::into),
SYS_DUP2 => {
dup2(fd, FileHandle::from(c), UserSlice::ro(d, e)?, token).map(FileHandle::into)
}
@@ -205,6 +211,14 @@ pub fn syscall(
SYS_OPENAT => {
openat(fd, UserSlice::ro(c, d)?, e, f as _, 0, 0, token).map(FileHandle::into)
}
SYS_OPENAT_INTO => openat_into(
fd,
UserSlice::ro(c, d)?,
e,
f as u32,
FileHandle::from(g as usize),
token,
),
SYS_OPENAT_WITH_FILTER => openat(
fd,
UserSlice::ro(c, d)?,