From 317a0178b6d70bb39a66731c7968f7e7d86e6463 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 13 Apr 2026 22:11:19 +0200 Subject: [PATCH] Introduce scheme-utils crate and HandleMap type HandleMap deduplicates the id assignment for handles and unlike most existing implementations handles overflow just fine. --- Cargo.lock | 24 +++++ Cargo.toml | 1 + audiod/Cargo.toml | 1 + audiod/src/scheme.rs | 27 ++--- drivers/acpid/Cargo.toml | 1 + drivers/acpid/src/scheme.rs | 55 ++++------ drivers/audio/ac97d/Cargo.toml | 1 + drivers/audio/ac97d/src/device.rs | 25 ++--- drivers/audio/ihdad/Cargo.toml | 1 + drivers/audio/ihdad/src/hda/device.rs | 26 ++--- drivers/audio/sb16d/Cargo.toml | 1 + drivers/audio/sb16d/src/device.rs | 22 ++-- drivers/graphics/driver-graphics/Cargo.toml | 1 + drivers/graphics/driver-graphics/src/lib.rs | 34 +++--- drivers/graphics/fbcond/Cargo.toml | 1 + drivers/graphics/fbcond/src/scheme.rs | 55 ++++------ drivers/inputd/Cargo.toml | 1 + drivers/inputd/src/main.rs | 37 +++---- drivers/net/driver-network/Cargo.toml | 1 + drivers/net/driver-network/src/lib.rs | 40 +++----- drivers/pcid/Cargo.toml | 1 + drivers/pcid/src/scheme.rs | 66 ++++-------- drivers/storage/driver-block/Cargo.toml | 1 + drivers/storage/driver-block/src/lib.rs | 33 +++--- ipcd/Cargo.toml | 1 + ipcd/src/shm.rs | 71 ++++--------- logd/Cargo.toml | 1 + logd/src/scheme.rs | 54 ++++------ netstack/Cargo.toml | 1 + netstack/src/scheme/mod.rs | 2 +- netstack/src/scheme/netcfg/mod.rs | 81 +++++---------- netstack/src/scheme/socket.rs | 108 +++++--------------- ramfs/Cargo.toml | 1 + ramfs/src/scheme.rs | 45 +++----- randd/Cargo.toml | 1 + randd/src/main.rs | 51 ++------- scheme-utils/Cargo.toml | 11 ++ scheme-utils/src/lib.rs | 67 ++++++++++++ 38 files changed, 381 insertions(+), 570 deletions(-) create mode 100644 scheme-utils/Cargo.toml create mode 100644 scheme-utils/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 09233ad19f..ac92d1f8b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,7 @@ dependencies = [ "redox-scheme", "redox_event", "redox_syscall 0.7.3", + "scheme-utils", "spin", ] @@ -50,6 +51,7 @@ dependencies = [ "redox_syscall 0.7.3", "ron", "rustc-hash", + "scheme-utils", "serde", "thiserror 2.0.18", ] @@ -180,6 +182,7 @@ dependencies = [ "libredox", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", ] [[package]] @@ -562,6 +565,7 @@ dependencies = [ "partitionlib", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", ] [[package]] @@ -578,6 +582,7 @@ dependencies = [ "redox-ioctl", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", ] [[package]] @@ -588,6 +593,7 @@ dependencies = [ "libredox", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", ] [[package]] @@ -743,6 +749,7 @@ dependencies = [ "redox-scheme", "redox_event", "redox_syscall 0.7.3", + "scheme-utils", ] [[package]] @@ -1047,6 +1054,7 @@ dependencies = [ "redox-scheme", "redox_event", "redox_syscall 0.7.3", + "scheme-utils", "spin", ] @@ -1110,6 +1118,7 @@ dependencies = [ "orbclient", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", ] [[package]] @@ -1134,6 +1143,7 @@ dependencies = [ "redox-scheme", "redox_event", "redox_syscall 0.7.3", + "scheme-utils", ] [[package]] @@ -1250,6 +1260,7 @@ dependencies = [ "libredox", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", ] [[package]] @@ -1473,6 +1484,7 @@ dependencies = [ "plain", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", "serde", ] @@ -1618,6 +1630,7 @@ dependencies = [ "libredox", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", "slab", ] @@ -1706,6 +1719,7 @@ dependencies = [ "raw-cpuid", "redox-scheme", "redox_syscall 0.7.3", + "scheme-utils", "sha2", ] @@ -1815,6 +1829,7 @@ dependencies = [ "redox-scheme", "redox_event", "redox_syscall 0.7.3", + "scheme-utils", "smoltcp", ] @@ -1982,9 +1997,18 @@ dependencies = [ "redox-scheme", "redox_event", "redox_syscall 0.7.3", + "scheme-utils", "spin", ] +[[package]] +name = "scheme-utils" +version = "0.0.0" +dependencies = [ + "libredox", + "redox_syscall 0.7.3", +] + [[package]] name = "scopeguard" version = "1.2.0" diff --git a/Cargo.toml b/Cargo.toml index 5432e8ebf6..5b9b6e24fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ "ptyd", "ramfs", "randd", + "scheme-utils", "zerod", "drivers/common", diff --git a/audiod/Cargo.toml b/audiod/Cargo.toml index 820a9bd9ee..762a080b9a 100644 --- a/audiod/Cargo.toml +++ b/audiod/Cargo.toml @@ -11,6 +11,7 @@ redox_syscall = { workspace = true, features = ["std"] } libc.workspace = true libredox = { workspace = true, features = ["mkns"] } redox-scheme.workspace = true +scheme-utils = { path = "../scheme-utils" } anyhow.workspace = true ioslice = "0.6.0" diff --git a/audiod/src/scheme.rs b/audiod/src/scheme.rs index e23a7098a3..62d9b9ede2 100644 --- a/audiod/src/scheme.rs +++ b/audiod/src/scheme.rs @@ -1,5 +1,6 @@ use redox_scheme::{CallerCtx, OpenResult}; -use std::collections::{BTreeMap, VecDeque}; +use scheme_utils::HandleMap; +use std::collections::VecDeque; use std::str; use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, ENOENT, EWOULDBLOCK}; @@ -20,16 +21,14 @@ enum Handle { } pub struct AudioScheme { - next_id: usize, - handles: BTreeMap, + handles: HandleMap, volume: i32, } impl AudioScheme { pub fn new() -> Self { AudioScheme { - next_id: 0, - handles: BTreeMap::new(), + handles: HandleMap::new(), volume: 50, } } @@ -66,10 +65,7 @@ impl AudioScheme { impl SchemeSync for AudioScheme { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.next_id += 1; - self.handles.insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( &mut self, @@ -79,10 +75,7 @@ impl SchemeSync for AudioScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - if !matches!( - self.handles.get(&dirfd).ok_or(Error::new(EBADF))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } @@ -97,9 +90,7 @@ impl SchemeSync for AudioScheme { _ => return Err(Error::new(ENOENT)), }; - let id = self.next_id; - self.next_id += 1; - self.handles.insert(id, handle); + let id = self.handles.insert(handle); Ok(OpenResult::ThisScheme { number: id, flags }) } @@ -113,7 +104,7 @@ impl SchemeSync for AudioScheme { _ctx: &CallerCtx, ) -> Result { //TODO: check flags for readable - match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + match self.handles.get_mut(id)? { Handle::Audio { buffer: _ } => { //TODO: audio input? Err(Error::new(EBADF)) @@ -143,7 +134,7 @@ impl SchemeSync for AudioScheme { _ctx: &CallerCtx, ) -> Result { //TODO: check flags for writable - match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + match self.handles.get_mut(id)? { Handle::Audio { ref mut buffer } => { if buffer.len() >= HANDLE_BUFFER_SIZE { Err(Error::new(EWOULDBLOCK)) diff --git a/drivers/acpid/Cargo.toml b/drivers/acpid/Cargo.toml index 3cdc71fe0e..2d22a8f923 100644 --- a/drivers/acpid/Cargo.toml +++ b/drivers/acpid/Cargo.toml @@ -27,6 +27,7 @@ common = { path = "../common" } daemon = { path = "../../daemon" } libredox.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../../scheme-utils" } [lints] workspace = true diff --git a/drivers/acpid/src/scheme.rs b/drivers/acpid/src/scheme.rs index 62f36bd3ba..e6d4645480 100644 --- a/drivers/acpid/src/scheme.rs +++ b/drivers/acpid/src/scheme.rs @@ -7,7 +7,7 @@ use parking_lot::RwLockReadGuard; use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult, SendFdRequest, Socket}; use ron::de::SpannedError; -use std::collections::BTreeMap; +use scheme_utils::HandleMap; use std::convert::{TryFrom, TryInto}; use std::str::FromStr; use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; @@ -25,8 +25,7 @@ use crate::acpi::{AcpiContext, AmlSymbols, SdtSignature}; pub struct AcpiScheme<'acpi, 'sock> { ctx: &'acpi AcpiContext, - handles: BTreeMap>, - next_fd: usize, + handles: HandleMap>, pci_fd: Option, socket: &'sock Socket, } @@ -77,8 +76,7 @@ impl<'acpi, 'sock> AcpiScheme<'acpi, 'sock> { pub fn new(ctx: &'acpi AcpiContext, socket: &'sock Socket) -> Self { Self { ctx, - handles: BTreeMap::new(), - next_fd: 0, + handles: HandleMap::new(), pci_fd: None, socket, } @@ -161,18 +159,11 @@ fn parse_table(table: &[u8]) -> Option { impl SchemeSync for AcpiScheme<'_, '_> { fn scheme_root(&mut self) -> Result { - let fd = self.next_fd; - self.next_fd += 1; - - self.handles.insert( - fd, - Handle { - stat: false, - kind: HandleKind::SchemeRoot, - allowed_to_eval: false, - }, - ); - Ok(fd) + Ok(self.handles.insert(Handle { + stat: false, + kind: HandleKind::SchemeRoot, + allowed_to_eval: false, + })) } fn openat( &mut self, @@ -182,7 +173,7 @@ impl SchemeSync for AcpiScheme<'_, '_> { _fcntl_flags: u32, ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get(&dirfd).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(dirfd)?; let path = path.trim_start_matches('/'); @@ -265,17 +256,11 @@ impl SchemeSync for AcpiScheme<'_, '_> { return Err(Error::new(EINVAL)); } - let fd = self.next_fd; - self.next_fd += 1; - - self.handles.insert( - fd, - Handle { - stat: flag_stat, - kind, - allowed_to_eval, - }, - ); + let fd = self.handles.insert(Handle { + stat: flag_stat, + kind, + allowed_to_eval, + }); Ok(OpenResult::ThisScheme { number: fd, @@ -284,7 +269,7 @@ impl SchemeSync for AcpiScheme<'_, '_> { } fn fstat(&mut self, id: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(id)?; stat.st_size = handle .kind @@ -311,7 +296,7 @@ impl SchemeSync for AcpiScheme<'_, '_> { ) -> Result { let offset: usize = offset.try_into().map_err(|_| Error::new(EINVAL))?; - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get_mut(id)?; if handle.stat { return Err(Error::new(EBADF)); @@ -343,7 +328,7 @@ impl SchemeSync for AcpiScheme<'_, '_> { mut buf: DirentBuf<&'buf mut [u8]>, opaque_offset: u64, ) -> Result> { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EOPNOTSUPP))?; + let handle = self.handles.get_mut(id)?; match &handle.kind { HandleKind::TopLevel => { @@ -430,7 +415,7 @@ impl SchemeSync for AcpiScheme<'_, '_> { _metadata: &[u64], _ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get_mut(id)?; if !handle.allowed_to_eval { return Err(Error::new(EPERM)); } @@ -474,7 +459,7 @@ impl SchemeSync for AcpiScheme<'_, '_> { let id = sendfd_request.id(); let num_fds = sendfd_request.num_fds(); - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(id)?; if !matches!(handle.kind, HandleKind::RegisterPci) { return Err(Error::new(EACCES)); } @@ -506,6 +491,6 @@ impl SchemeSync for AcpiScheme<'_, '_> { } fn on_close(&mut self, id: usize) { - self.handles.remove(&id); + self.handles.remove(id); } } diff --git a/drivers/audio/ac97d/Cargo.toml b/drivers/audio/ac97d/Cargo.toml index 29e42171f8..97b163dbe9 100644 --- a/drivers/audio/ac97d/Cargo.toml +++ b/drivers/audio/ac97d/Cargo.toml @@ -15,6 +15,7 @@ spin.workspace = true daemon = { path = "../../../daemon" } pcid = { path = "../../pcid" } redox-scheme.workspace = true +scheme-utils = { path = "../../../scheme-utils" } [lints] workspace = true diff --git a/drivers/audio/ac97d/src/device.rs b/drivers/audio/ac97d/src/device.rs index ed075d891b..a83c9bcc48 100644 --- a/drivers/audio/ac97d/src/device.rs +++ b/drivers/audio/ac97d/src/device.rs @@ -1,12 +1,10 @@ #![allow(dead_code)] -use std::collections::BTreeMap; -use std::sync::atomic::{AtomicUsize, Ordering}; - use common::io::Pio; use redox_scheme::scheme::SchemeSync; use redox_scheme::CallerCtx; use redox_scheme::OpenResult; +use scheme_utils::HandleMap; use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, ENOENT}; use syscall::schemev2::NewFdFlags; use syscall::EWOULDBLOCK; @@ -156,8 +154,7 @@ pub struct Ac97 { bus: BusRegs, bdl: Dma<[BufferDescriptor; NUM_SUB_BUFFS]>, buf: Dma<[u8; NUM_SUB_BUFFS * SUB_BUFF_SIZE]>, - handles: Mutex>, - next_id: AtomicUsize, + handles: Mutex>, } impl Ac97 { @@ -173,8 +170,7 @@ impl Ac97 { //TODO: PhysBox::new_in_32bit_space(buf_size)? )? .assume_init(), - handles: Mutex::new(BTreeMap::new()), - next_id: AtomicUsize::new(0), + handles: Mutex::new(HandleMap::new()), }; module.init()?; @@ -264,9 +260,7 @@ impl Ac97 { impl SchemeSync for Ac97 { fn scheme_root(&mut self) -> Result { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.lock().insert(Handle::SchemeRoot)) } fn openat( &mut self, @@ -278,14 +272,13 @@ impl SchemeSync for Ac97 { ) -> Result { { let handles = self.handles.lock(); - let handle = handles.get(&dirfd).ok_or(Error::new(EBADF))?; + let handle = handles.get(dirfd)?; if !matches!(handle, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } } if ctx.uid == 0 { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, Handle::Todo); + let id = self.handles.lock().insert(Handle::Todo); Ok(OpenResult::ThisScheme { number: id, flags: NewFdFlags::empty(), @@ -305,7 +298,7 @@ impl SchemeSync for Ac97 { ) -> Result { { let mut handles = self.handles.lock(); - let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = handles.get_mut(id)?; if !matches!(handle, Handle::Todo) { return Err(Error::new(EBADF)); } @@ -335,7 +328,7 @@ impl SchemeSync for Ac97 { fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { { let mut handles = self.handles.lock(); - let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = handles.get_mut(id)?; if !matches!(handle, Handle::Todo) { return Err(Error::new(EBADF)); } @@ -351,6 +344,6 @@ impl SchemeSync for Ac97 { } fn on_close(&mut self, id: usize) { - let _ = self.handles.lock().remove(&id); + self.handles.lock().remove(id); } } diff --git a/drivers/audio/ihdad/Cargo.toml b/drivers/audio/ihdad/Cargo.toml index 43b6f6dd1f..49f8171525 100644 --- a/drivers/audio/ihdad/Cargo.toml +++ b/drivers/audio/ihdad/Cargo.toml @@ -16,6 +16,7 @@ common = { path = "../../common" } daemon = { path = "../../../daemon" } pcid = { path = "../../pcid" } redox-scheme.workspace = true +scheme-utils = { path = "../../../scheme-utils" } [lints] workspace = true diff --git a/drivers/audio/ihdad/src/hda/device.rs b/drivers/audio/ihdad/src/hda/device.rs index 3973914a73..1b595ca564 100755 --- a/drivers/audio/ihdad/src/hda/device.rs +++ b/drivers/audio/ihdad/src/hda/device.rs @@ -1,10 +1,8 @@ #![allow(dead_code)] -use std::collections::BTreeMap; use std::collections::HashMap; use std::fmt::Write; use std::str; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::task::Poll; use std::thread; use std::time::Duration; @@ -15,6 +13,7 @@ use common::timeout::Timeout; use redox_scheme::scheme::SchemeSync; use redox_scheme::CallerCtx; use redox_scheme::OpenResult; +use scheme_utils::HandleMap; use syscall::error::{Error, Result, EACCES, EBADF, EIO, ENODEV, EWOULDBLOCK}; use spin::Mutex; @@ -150,8 +149,7 @@ pub struct IntelHDA { buffs: Vec>, int_counter: usize, - handles: Mutex>, - next_id: AtomicUsize, + handles: Mutex>, } impl IntelHDA { @@ -203,8 +201,7 @@ impl IntelHDA { buffs: Vec::>::new(), int_counter: 0, - handles: Mutex::new(BTreeMap::new()), - next_id: AtomicUsize::new(0), + handles: Mutex::new(HandleMap::new()), }; module.init()?; @@ -986,9 +983,7 @@ impl Drop for IntelHDA { impl SchemeSync for IntelHDA { fn scheme_root(&mut self) -> Result { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.lock().insert(Handle::SchemeRoot)) } fn openat( &mut self, @@ -1000,7 +995,7 @@ impl SchemeSync for IntelHDA { ) -> Result { { let handles = self.handles.lock(); - let handle = handles.get(&dirfd).ok_or(Error::new(EBADF))?; + let handle = handles.get(dirfd)?; if !matches!(handle, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } @@ -1026,8 +1021,7 @@ impl SchemeSync for IntelHDA { "codec" => Handle::StrBuf(self.dump_codec(0).into_bytes()), _ => Handle::Todo, }; - let id = self.next_id.fetch_add(1, Ordering::Relaxed); - self.handles.lock().insert(id, handle); + let id = self.handles.lock().insert(handle); // TODO: always positioned? Ok(OpenResult::ThisScheme { @@ -1045,7 +1039,7 @@ impl SchemeSync for IntelHDA { _ctx: &CallerCtx, ) -> Result { let handles = self.handles.lock(); - let Some(Handle::StrBuf(strbuf)) = handles.get(&id) else { + let Handle::StrBuf(strbuf) = handles.get(id)? else { return Err(Error::new(EBADF)); }; @@ -1068,7 +1062,7 @@ impl SchemeSync for IntelHDA { ) -> Result { let index = { let mut handles = self.handles.lock(); - match handles.get_mut(&id).ok_or(Error::new(EBADF))? { + match handles.get_mut(id)? { Handle::Todo => 0, _ => return Err(Error::new(EBADF)), } @@ -1084,7 +1078,7 @@ impl SchemeSync for IntelHDA { fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { let mut handles = self.handles.lock(); - let _handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let _handle = handles.get_mut(id)?; let mut i = 0; let scheme_path = b"/scheme/audiohw"; @@ -1096,6 +1090,6 @@ impl SchemeSync for IntelHDA { } fn on_close(&mut self, id: usize) { - let _ = self.handles.lock().remove(&id); + self.handles.lock().remove(id); } } diff --git a/drivers/audio/sb16d/Cargo.toml b/drivers/audio/sb16d/Cargo.toml index 33f822fec4..a54c7287a8 100644 --- a/drivers/audio/sb16d/Cargo.toml +++ b/drivers/audio/sb16d/Cargo.toml @@ -14,6 +14,7 @@ redox_event.workspace = true redox_syscall.workspace = true spin.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../../../scheme-utils" } [lints] workspace = true diff --git a/drivers/audio/sb16d/src/device.rs b/drivers/audio/sb16d/src/device.rs index 8017b91501..54055c69d9 100644 --- a/drivers/audio/sb16d/src/device.rs +++ b/drivers/audio/sb16d/src/device.rs @@ -1,7 +1,5 @@ #![allow(dead_code)] -use std::collections::BTreeMap; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::{thread, time}; use common::io::{Io, Pio, ReadOnly, WriteOnly}; @@ -9,6 +7,7 @@ use common::io::{Io, Pio, ReadOnly, WriteOnly}; use redox_scheme::scheme::SchemeSync; use redox_scheme::CallerCtx; use redox_scheme::OpenResult; +use scheme_utils::HandleMap; use syscall::error::{Error, Result, EACCES, EBADF, ENODEV}; use syscall::schemev2::NewFdFlags; @@ -24,8 +23,7 @@ enum Handle { #[allow(dead_code)] pub struct Sb16 { - handles: Mutex>, - next_id: AtomicUsize, + handles: Mutex>, pub(crate) irqs: Vec, dmas: Vec, // Regs @@ -41,8 +39,7 @@ pub struct Sb16 { impl Sb16 { pub unsafe fn new(addr: u16) -> Result { let mut module = Sb16 { - handles: Mutex::new(BTreeMap::new()), - next_id: AtomicUsize::new(0), + handles: Mutex::new(HandleMap::new()), irqs: Vec::new(), dmas: Vec::new(), // Regs @@ -187,9 +184,7 @@ impl Sb16 { impl SchemeSync for Sb16 { fn scheme_root(&mut self) -> Result { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.lock().insert(Handle::SchemeRoot)) } fn openat( &mut self, @@ -201,14 +196,13 @@ impl SchemeSync for Sb16 { ) -> Result { { let handles = self.handles.lock(); - let handle = handles.get(&dirfd).ok_or(Error::new(EBADF))?; + let handle = handles.get(dirfd)?; if !matches!(handle, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } } if ctx.uid == 0 { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, Handle::Todo); + let id = self.handles.lock().insert(Handle::Todo); Ok(OpenResult::ThisScheme { number: id, flags: NewFdFlags::empty(), @@ -232,7 +226,7 @@ impl SchemeSync for Sb16 { fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { let mut handles = self.handles.lock(); - let _handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let _handle = handles.get_mut(id)?; let mut i = 0; let scheme_path = b"/scheme/audiohw"; @@ -244,6 +238,6 @@ impl SchemeSync for Sb16 { } fn on_close(&mut self, id: usize) { - let _ = self.handles.lock().remove(&id); + self.handles.lock().remove(id); } } diff --git a/drivers/graphics/driver-graphics/Cargo.toml b/drivers/graphics/driver-graphics/Cargo.toml index 7f90a93eb6..31e02335c8 100644 --- a/drivers/graphics/driver-graphics/Cargo.toml +++ b/drivers/graphics/driver-graphics/Cargo.toml @@ -11,6 +11,7 @@ edid.workspace = true #TODO: edid is abandoned, fork it and maintain? log.workspace = true redox-ioctl.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../../../scheme-utils" } redox_syscall.workspace = true libredox.workspace = true diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index b2177e4e4a..741139c10b 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -1,6 +1,6 @@ #![feature(macro_metavar_expr)] -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; use std::fmt::Debug; use std::fs::File; use std::io::{self, Write}; @@ -18,8 +18,9 @@ use inputd::{DisplayHandle, VtEventKind}; use libredox::Fd; use redox_scheme::scheme::{register_scheme_inner, SchemeState, SchemeSync}; use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket}; +use scheme_utils::HandleMap; use syscall::schemev2::NewFdFlags; -use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP}; +use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EINVAL, ENOENT, EOPNOTSUPP}; use crate::kms::connector::{KmsConnectorDriver, KmsConnectorState}; use crate::kms::objects::{self, KmsCrtc, KmsCrtcDriver, KmsCrtcState, KmsObjectId, KmsObjects}; @@ -155,8 +156,7 @@ impl GraphicsScheme { disable_graphical_debug, socket, objects, - next_id: 0, - handles: BTreeMap::new(), + handles: HandleMap::new(), active_vt: 0, vts: HashMap::new(), }; @@ -264,8 +264,7 @@ struct GraphicsSchemeInner { disable_graphical_debug: Option, socket: Socket, objects: KmsObjects, - next_id: usize, - handles: BTreeMap>, + handles: HandleMap>, active_vt: usize, vts: HashMap>, @@ -381,10 +380,7 @@ const MAP_FAKE_OFFSET_MULTIPLIER: usize = 0x10_000_000; impl SchemeSync for GraphicsSchemeInner { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.next_id += 1; - self.handles.insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( &mut self, @@ -394,10 +390,7 @@ impl SchemeSync for GraphicsSchemeInner { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - if !matches!( - self.handles.get(&dirfd).ok_or(Error::new(EBADF))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } if path.is_empty() { @@ -423,16 +416,15 @@ impl SchemeSync for GraphicsSchemeInner { } else { return Err(Error::new(EINVAL)); }; - self.next_id += 1; - self.handles.insert(self.next_id, handle); + let id = self.handles.insert(handle); Ok(OpenResult::ThisScheme { - number: self.next_id, + number: id, flags: NewFdFlags::empty(), }) } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> syscall::Result { - let path = match self.handles.get(&id).ok_or(Error::new(EBADF))? { + let path = match self.handles.get(id)? { Handle::V2 { vt, next_id: _, @@ -461,7 +453,7 @@ impl SchemeSync for GraphicsSchemeInner { id_index(i) | (1 << 13) } - match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + match self.handles.get_mut(id)? { Handle::SchemeRoot => return Err(Error::new(EOPNOTSUPP)), Handle::V2 { vt, @@ -969,7 +961,7 @@ impl SchemeSync for GraphicsSchemeInner { _ctx: &CallerCtx, ) -> syscall::Result { // log::trace!("KSMSG MMAP {} {:?} {} {}", id, _flags, _offset, _size); - let (framebuffer, offset) = match self.handles.get(&id).ok_or(Error::new(EINVAL))? { + let (framebuffer, offset) = match self.handles.get(id)? { Handle::V2 { vt: _, next_id: _, @@ -990,6 +982,6 @@ impl SchemeSync for GraphicsSchemeInner { impl GraphicsSchemeInner { fn on_close(&mut self, id: usize) { - self.handles.remove(&id); + self.handles.remove(id); } } diff --git a/drivers/graphics/fbcond/Cargo.toml b/drivers/graphics/fbcond/Cargo.toml index a4431bba57..ea9e2d6759 100644 --- a/drivers/graphics/fbcond/Cargo.toml +++ b/drivers/graphics/fbcond/Cargo.toml @@ -12,6 +12,7 @@ ransid.workspace = true redox_event.workspace = true redox_syscall.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../../../scheme-utils" } common = { path = "../../common" } console-draw = { path = "../console-draw" } diff --git a/drivers/graphics/fbcond/src/scheme.rs b/drivers/graphics/fbcond/src/scheme.rs index 0fafdc384d..3d11e5e1ae 100644 --- a/drivers/graphics/fbcond/src/scheme.rs +++ b/drivers/graphics/fbcond/src/scheme.rs @@ -4,6 +4,7 @@ use std::os::fd::AsRawFd; use event::{EventQueue, UserData}; use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult}; +use scheme_utils::HandleMap; use syscall::schemev2::NewFdFlags; use syscall::{Error, EventFlags, Result, EACCES, EAGAIN, EBADF, ENOENT, O_NONBLOCK}; @@ -41,8 +42,7 @@ pub enum Handle { pub struct FbconScheme { pub vts: BTreeMap, - next_id: usize, - pub handles: BTreeMap, + pub handles: HandleMap, } impl FbconScheme { @@ -63,26 +63,21 @@ impl FbconScheme { FbconScheme { vts, - next_id: 0, - handles: BTreeMap::new(), + handles: HandleMap::new(), } } fn get_vt_handle_mut(&mut self, id: usize) -> Result<&mut FdHandle> { - match self.handles.get_mut(&id) { - Some(Handle::Vt(handle)) => Ok(handle), - Some(Handle::SchemeRoot) => Err(Error::new(EBADF)), - None => Err(Error::new(EBADF)), + match self.handles.get_mut(id)? { + Handle::Vt(handle) => Ok(handle), + Handle::SchemeRoot => Err(Error::new(EBADF)), } } } impl SchemeSync for FbconScheme { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.next_id += 1; - self.handles.insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( @@ -93,27 +88,18 @@ impl SchemeSync for FbconScheme { fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - if !matches!( - self.handles.get(&dirfd).ok_or(Error::new(EBADF))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } let vt_i = VtIndex(path_str.parse::().map_err(|_| Error::new(ENOENT))?); if self.vts.contains_key(&vt_i) { - let id = self.next_id; - self.next_id += 1; - - self.handles.insert( - id, - Handle::Vt(FdHandle { - vt_i, - flags: flags | fcntl_flags as usize, - events: EventFlags::empty(), - notified_read: false, - }), - ); + let id = self.handles.insert(Handle::Vt(FdHandle { + vt_i, + flags: flags | fcntl_flags as usize, + events: EventFlags::empty(), + notified_read: false, + })); Ok(OpenResult::ThisScheme { number: id, @@ -159,9 +145,7 @@ impl SchemeSync for FbconScheme { } fn fcntl(&mut self, id: usize, _cmd: usize, _arg: usize, _ctx: &CallerCtx) -> Result { - if !self.handles.get(&id).is_some() { - return Err(Error::new(EBADF)); - }; + self.handles.get(id)?; Ok(0) } @@ -173,10 +157,9 @@ impl SchemeSync for FbconScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - let handle = match self.handles.get(&id) { - Some(Handle::Vt(handle)) => Ok(handle), - Some(Handle::SchemeRoot) => Err(Error::new(EBADF)), - None => Err(Error::new(EBADF)), + let handle = match self.handles.get(id)? { + Handle::Vt(handle) => Ok(handle), + Handle::SchemeRoot => Err(Error::new(EBADF)), }?; if let Some(screen) = self.vts.get_mut(&handle.vt_i) { @@ -212,6 +195,6 @@ impl SchemeSync for FbconScheme { } fn on_close(&mut self, id: usize) { - let _ = self.handles.remove(&id); + self.handles.remove(id); } } diff --git a/drivers/inputd/Cargo.toml b/drivers/inputd/Cargo.toml index 9bcfc595f7..8c1b999040 100644 --- a/drivers/inputd/Cargo.toml +++ b/drivers/inputd/Cargo.toml @@ -15,6 +15,7 @@ libredox.workspace = true common = { path = "../common" } daemon = { path = "../../daemon" } redox-scheme.workspace = true +scheme-utils = { path = "../../scheme-utils" } [lints] workspace = true diff --git a/drivers/inputd/src/main.rs b/drivers/inputd/src/main.rs index a05bfc824c..36e942feb8 100644 --- a/drivers/inputd/src/main.rs +++ b/drivers/inputd/src/main.rs @@ -13,7 +13,7 @@ use core::mem::size_of; use std::borrow::Cow; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeSet; use std::mem::transmute; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -24,6 +24,7 @@ use redox_scheme::scheme::{SchemeState, SchemeSync}; use redox_scheme::{CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket}; use orbclient::{Event, EventOption}; +use scheme_utils::HandleMap; use syscall::schemev2::NewFdFlags; use syscall::{Error as SysError, EventFlags, EACCES, EBADF, EEXIST, EINVAL}; @@ -57,9 +58,8 @@ enum Handle { } struct InputScheme { - handles: BTreeMap, + handles: HandleMap, - next_id: AtomicUsize, next_vt_id: AtomicUsize, display: Option, @@ -76,9 +76,8 @@ struct InputScheme { impl InputScheme { fn new() -> Self { Self { - handles: BTreeMap::new(), + handles: HandleMap::new(), - next_id: AtomicUsize::new(0), next_vt_id: AtomicUsize::new(2), // VT 1 is reserved for the bootlog display: None, @@ -150,9 +149,7 @@ impl InputScheme { impl SchemeSync for InputScheme { fn scheme_root(&mut self) -> syscall::Result { - let fd = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.insert(fd, Handle::SchemeRoot); - Ok(fd) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( @@ -163,10 +160,7 @@ impl SchemeSync for InputScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> syscall::Result { - if !matches!( - self.handles.get(&dirfd).ok_or(SysError::new(EINVAL))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, Handle::SchemeRoot) { return Err(SysError::new(EACCES)); } @@ -266,8 +260,7 @@ impl SchemeSync for InputScheme { log::debug!("{path} channel has been opened"); - let fd = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.insert(fd, handle_ty); + let fd = self.handles.insert(handle_ty); Ok(OpenResult::ThisScheme { number: fd, flags: NewFdFlags::empty(), @@ -275,7 +268,7 @@ impl SchemeSync for InputScheme { } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> syscall::Result { - let handle = self.handles.get(&id).ok_or(SysError::new(EINVAL))?; + let handle = self.handles.get(id)?; if let Handle::Consumer { vt, .. } = handle { let display = self.display.as_ref().ok_or(SysError::new(EINVAL))?; @@ -298,7 +291,7 @@ impl SchemeSync for InputScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> syscall::Result { - let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?; + let handle = self.handles.get_mut(id)?; match handle { Handle::Consumer { @@ -360,7 +353,7 @@ impl SchemeSync for InputScheme { ) -> syscall::Result { self.has_new_events = true; - let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?; + let handle = self.handles.get_mut(id)?; match handle { Handle::Control => { @@ -445,7 +438,7 @@ impl SchemeSync for InputScheme { } } - let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?; + let handle = self.handles.get_mut(id)?; assert!(matches!(handle, Handle::Producer)); let buf = unsafe { @@ -485,9 +478,7 @@ impl SchemeSync for InputScheme { flags: syscall::EventFlags, _ctx: &CallerCtx, ) -> syscall::Result { - let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?; - - match handle { + match self.handles.get_mut(id)? { Handle::Consumer { ref mut events, ref mut notified, @@ -515,9 +506,7 @@ impl SchemeSync for InputScheme { } fn on_close(&mut self, id: usize) { - let handle = self.handles.remove(&id).unwrap(); - - match handle { + match self.handles.remove(id).unwrap() { Handle::Consumer { vt, .. } => { self.vts.remove(&vt); if self.active_vt == Some(vt) { diff --git a/drivers/net/driver-network/Cargo.toml b/drivers/net/driver-network/Cargo.toml index 4e8162b5eb..fc8179086f 100644 --- a/drivers/net/driver-network/Cargo.toml +++ b/drivers/net/driver-network/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" libredox.workspace = true daemon = { path = "../../../daemon" } redox-scheme.workspace = true +scheme-utils = { path = "../../../scheme-utils" } redox_syscall = { workspace = true, features = ["std"] } [lints] diff --git a/drivers/net/driver-network/src/lib.rs b/drivers/net/driver-network/src/lib.rs index 894ecadd29..d536a04fd3 100644 --- a/drivers/net/driver-network/src/lib.rs +++ b/drivers/net/driver-network/src/lib.rs @@ -1,4 +1,3 @@ -use std::collections::BTreeMap; use std::{cmp, io}; use libredox::flag::O_NONBLOCK; @@ -7,6 +6,7 @@ use redox_scheme::{ scheme::{IntoTag, Op, SchemeResponse, SchemeState, SchemeSync}, CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket, }; +use scheme_utils::HandleMap; use syscall::schemev2::NewFdFlags; use syscall::{ Error, EventFlags, Result, Stat, EACCES, EAGAIN, EBADF, EINTR, EINVAL, EWOULDBLOCK, MODE_FILE, @@ -208,8 +208,7 @@ impl NetworkScheme { struct NetworkSchemeInner { adapter: T, scheme_name: String, - next_id: usize, - handles: BTreeMap, + handles: HandleMap, } enum Handle { @@ -223,18 +222,14 @@ impl NetworkSchemeInner { Self { adapter, scheme_name, - next_id: 0, - handles: BTreeMap::new(), + handles: HandleMap::new(), } } } impl SchemeSync for NetworkSchemeInner { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.next_id += 1; - self.handles.insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( @@ -245,10 +240,7 @@ impl SchemeSync for NetworkSchemeInner { _fcntl_flags: u32, ctx: &CallerCtx, ) -> Result { - if !matches!( - self.handles.get(&fd).ok_or(Error::new(EINVAL))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(fd)?, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } if ctx.uid != 0 { @@ -261,12 +253,8 @@ impl SchemeSync for NetworkSchemeInner { _ => return Err(Error::new(EINVAL)), }; - self.next_id += 1; - self.handles.insert(self.next_id, handle); - Ok(OpenResult::ThisScheme { - number: self.next_id, - flags, - }) + let id = self.handles.insert(handle); + Ok(OpenResult::ThisScheme { number: id, flags }) } fn read( @@ -277,7 +265,7 @@ impl SchemeSync for NetworkSchemeInner { fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get_mut(id)?; match *handle { Handle::Data => {} @@ -310,7 +298,7 @@ impl SchemeSync for NetworkSchemeInner { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(id)?; match handle { Handle::Data => {} @@ -322,12 +310,12 @@ impl SchemeSync for NetworkSchemeInner { } fn fevent(&mut self, id: usize, _flags: EventFlags, _ctx: &CallerCtx) -> Result { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let _handle = self.handles.get(id)?; Ok(EventFlags::empty()) } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(id)?; const PREFIX: &[u8] = b"/scheme/"; let len = cmp::min(PREFIX.len(), buf.len()); @@ -362,7 +350,7 @@ impl SchemeSync for NetworkSchemeInner { } fn fstat(&mut self, id: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(id)?; match handle { Handle::Data { .. } => { @@ -379,11 +367,11 @@ impl SchemeSync for NetworkSchemeInner { } fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let _handle = self.handles.get(id)?; Ok(()) } fn on_close(&mut self, id: usize) { - self.handles.remove(&id); + self.handles.remove(id); } } diff --git a/drivers/pcid/Cargo.toml b/drivers/pcid/Cargo.toml index cfa4125830..6969531136 100644 --- a/drivers/pcid/Cargo.toml +++ b/drivers/pcid/Cargo.toml @@ -21,6 +21,7 @@ pci_types = "0.10.1" pico-args = { workspace = true, features = ["combined-flags"] } plain.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../../scheme-utils" } redox_syscall.workspace = true serde.workspace = true diff --git a/drivers/pcid/src/scheme.rs b/drivers/pcid/src/scheme.rs index ce55b33f9a..c2caf804f9 100644 --- a/drivers/pcid/src/scheme.rs +++ b/drivers/pcid/src/scheme.rs @@ -3,6 +3,7 @@ use std::collections::{BTreeMap, VecDeque}; use pci_types::{ConfigRegionAccess, PciAddress}; use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult}; +use scheme_utils::HandleMap; use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, EIO, EISDIR, ENOENT, ENOTDIR}; use syscall::flag::{MODE_CHR, MODE_DIR, O_DIRECTORY, O_STAT}; @@ -12,8 +13,7 @@ use syscall::ENOLCK; use crate::cfg_access::Pcie; pub struct PciScheme { - handles: BTreeMap, - next_id: usize, + handles: HandleMap, pub pcie: Pcie, pub tree: BTreeMap, } @@ -53,34 +53,19 @@ const DEVICE_CONTENTS: &[&str] = &["channel"]; impl PciScheme { pub fn access(&mut self) -> usize { - let id = self.next_id; - self.next_id += 1; - - self.handles.insert( - id, - HandleWrapper { - inner: Handle::Access, - stat: false, - }, - ); - - id + self.handles.insert(HandleWrapper { + inner: Handle::Access, + stat: false, + }) } } impl SchemeSync for PciScheme { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.next_id += 1; - - self.handles.insert( - id, - HandleWrapper { - inner: Handle::SchemeRoot, - stat: false, - }, - ); - Ok(id) + Ok(self.handles.insert(HandleWrapper { + inner: Handle::SchemeRoot, + stat: false, + })) } fn openat( &mut self, @@ -90,7 +75,7 @@ impl SchemeSync for PciScheme { _fcntl_flags: u32, ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get(&dirfd).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(dirfd)?; if !handle.inner.is_scheme_root() { return Err(Error::new(EACCES)); } @@ -132,23 +117,17 @@ impl SchemeSync for PciScheme { return Err(Error::new(EACCES)); } - let id = self.next_id; - self.next_id += 1; - - self.handles.insert( - id, - HandleWrapper { - inner: handle, - stat, - }, - ); + let id = self.handles.insert(HandleWrapper { + inner: handle, + stat, + }); Ok(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED, }) } fn fstat(&mut self, id: usize, stat: &mut syscall::Stat, _ctx: &CallerCtx) -> Result<()> { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get_mut(id)?; let (len, mode) = match handle.inner { Handle::TopLevel { ref entries } => (entries.len(), MODE_DIR | 0o755), @@ -168,7 +147,7 @@ impl SchemeSync for PciScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get_mut(id)?; if handle.stat { return Err(Error::new(EBADF)); @@ -195,7 +174,7 @@ impl SchemeSync for PciScheme { return Ok(buf); }; - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get_mut(id)?; if handle.stat { return Err(Error::new(EBADF)); @@ -237,7 +216,7 @@ impl SchemeSync for PciScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get_mut(id)?; if handle.stat { return Err(Error::new(EBADF)); @@ -259,7 +238,7 @@ impl SchemeSync for PciScheme { metadata: &[u64], _ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get_mut(id)?; if handle.stat { return Err(Error::new(EBADF)); @@ -329,7 +308,7 @@ impl SchemeSync for PciScheme { impl PciScheme { pub fn on_close(&mut self, id: usize) { - match self.handles.remove(&id) { + match self.handles.remove(id) { Some(HandleWrapper { inner: Handle::Channel { addr, .. }, .. @@ -347,8 +326,7 @@ impl PciScheme { impl PciScheme { pub fn new(pcie: Pcie) -> Self { Self { - handles: BTreeMap::new(), - next_id: 0, + handles: HandleMap::new(), pcie, tree: BTreeMap::new(), } diff --git a/drivers/storage/driver-block/Cargo.toml b/drivers/storage/driver-block/Cargo.toml index b358ee8c33..ec34dd9cdc 100644 --- a/drivers/storage/driver-block/Cargo.toml +++ b/drivers/storage/driver-block/Cargo.toml @@ -17,6 +17,7 @@ futures = { version = "0.3.28", features = ["executor"] } redox_syscall = { workspace = true, features = ["std"] } redox-scheme.workspace = true +scheme-utils = { path = "../../../scheme-utils" } [lints] workspace = true diff --git a/drivers/storage/driver-block/src/lib.rs b/drivers/storage/driver-block/src/lib.rs index 3d872e7987..51bb0e72d1 100644 --- a/drivers/storage/driver-block/src/lib.rs +++ b/drivers/storage/driver-block/src/lib.rs @@ -13,6 +13,7 @@ use libredox::Fd; use partitionlib::{LogicalBlockSize, PartitionTable}; use redox_scheme::scheme::{register_scheme_inner, SchemeAsync, SchemeState}; use redox_scheme::{CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket}; +use scheme_utils::HandleMap; use syscall::dirent::DirentBuf; use syscall::schemev2::NewFdFlags; use syscall::{ @@ -276,8 +277,7 @@ impl DiskScheme { .into_iter() .map(|(k, disk)| (k, DiskWrapper::new(disk, executor))) .collect(), - next_id: 0, - handles: BTreeMap::new(), + handles: HandleMap::new(), }; let cap_id = inner.scheme_root().expect("failed to get this scheme root"); @@ -361,8 +361,7 @@ struct DiskSchemeInner { scheme_name: String, socket: Socket, disks: BTreeMap>, - handles: BTreeMap, - next_id: usize, + handles: HandleMap, } pub trait ExecutorTrait { @@ -432,10 +431,7 @@ impl DiskSchemeInner { impl SchemeAsync for DiskSchemeInner { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.next_id += 1; - self.handles.insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } async fn openat( &mut self, @@ -445,10 +441,7 @@ impl SchemeAsync for DiskSchemeInner { _fcntl_flags: u32, ctx: &CallerCtx, ) -> Result { - if !matches!( - self.handles.get(&dirfd).ok_or(Error::new(EBADF))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } @@ -515,9 +508,7 @@ impl SchemeAsync for DiskSchemeInner { return Err(Error::new(ENOENT)); } }; - let id = self.next_id; - self.next_id += 1; - self.handles.insert(id, handle); + let id = self.handles.insert(handle); Ok(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED, @@ -534,7 +525,7 @@ impl SchemeAsync for DiskSchemeInner { } async fn fstat(&mut self, id: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { - match *self.handles.get(&id).ok_or(Error::new(EBADF))? { + match *self.handles.get(id)? { Handle::List(ref data) => { stat.st_mode = MODE_DIR; stat.st_size = data.len() as u64; @@ -568,7 +559,7 @@ impl SchemeAsync for DiskSchemeInner { } async fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(id)?; let mut i = 0; @@ -622,7 +613,7 @@ impl SchemeAsync for DiskSchemeInner { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + match *self.handles.get_mut(id)? { Handle::List(ref handle) => { let src = usize::try_from(offset) .ok() @@ -654,7 +645,7 @@ impl SchemeAsync for DiskSchemeInner { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + match *self.handles.get_mut(id)? { Handle::List(_) => Err(Error::new(EBADF)), Handle::Disk(number) => { let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?; @@ -671,7 +662,7 @@ impl SchemeAsync for DiskSchemeInner { } async fn fsize(&mut self, id: usize, _ctx: &CallerCtx) -> Result { - Ok(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + Ok(match *self.handles.get_mut(id)? { Handle::List(ref handle) => handle.len() as u64, Handle::Disk(number) => { let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?; @@ -696,6 +687,6 @@ impl SchemeAsync for DiskSchemeInner { impl DiskSchemeInner { pub fn on_close(&mut self, id: usize) { - let _ = self.handles.remove(&id); + let _ = self.handles.remove(id); } } diff --git a/ipcd/Cargo.toml b/ipcd/Cargo.toml index 570e52739d..d7d8717b3d 100644 --- a/ipcd/Cargo.toml +++ b/ipcd/Cargo.toml @@ -9,6 +9,7 @@ libredox = { workspace = true, features = ["call"]} daemon = { path = "../daemon" } redox_syscall.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../scheme-utils" } redox_event.workspace = true anyhow.workspace = true libc.workspace = true diff --git a/ipcd/src/shm.rs b/ipcd/src/shm.rs index 499d72b56c..61d5ea5659 100644 --- a/ipcd/src/shm.rs +++ b/ipcd/src/shm.rs @@ -1,4 +1,5 @@ use redox_scheme::{scheme::SchemeSync, CallerCtx, OpenResult}; +use scheme_utils::HandleMap; use std::{ cmp, collections::{hash_map::Entry, HashMap}, @@ -14,10 +15,10 @@ enum Handle { SchemeRoot, } impl Handle { - fn as_shm(&self) -> Option<&Rc> { + fn as_shm(&self) -> Result<&Rc, Error> { match self { - Self::Shm(path) => Some(path), - Self::SchemeRoot => None, + Self::Shm(path) => Ok(path), + Self::SchemeRoot => Err(Error::new(EBADF)), } } } @@ -32,26 +33,20 @@ pub struct ShmHandle { } pub struct ShmScheme { maps: HashMap, ShmHandle>, - handles: HashMap, - next_id: usize, + handles: HandleMap, } impl ShmScheme { pub fn new() -> Self { Self { maps: HashMap::new(), - handles: HashMap::new(), - next_id: 0, + handles: HandleMap::new(), } } } impl SchemeSync for ShmScheme { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } //FIXME: Handle O_RDONLY/O_WRONLY/O_RDWR fn openat( @@ -62,7 +57,7 @@ impl SchemeSync for ShmScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get(&dirfd).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(dirfd)?; if !matches!(handle, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } @@ -87,10 +82,8 @@ impl SchemeSync for ShmScheme { } }; entry.refs += 1; - self.handles.insert(self.next_id, Handle::Shm(path)); + let id = self.handles.insert(Handle::Shm(path)); - let id = self.next_id; - self.next_id += 1; Ok(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED, @@ -106,18 +99,14 @@ impl SchemeSync for ShmScheme { } // Write path - let path = self - .handles - .get(&id) - .and_then(Handle::as_shm) - .ok_or(Error::new(EBADF))?; + let path = self.handles.get(id).and_then(Handle::as_shm)?; let len = cmp::min(path.len(), buf.len() - PREFIX.len()); buf[PREFIX.len()..][..len].copy_from_slice(&path.as_bytes()[..len]); Ok(PREFIX.len() + len) } fn on_close(&mut self, id: usize) { - let Handle::Shm(path) = self.handles.remove(&id).unwrap() else { + let Handle::Shm(path) = self.handles.remove(id).unwrap() else { return; }; let mut entry = match self.maps.entry(path) { @@ -131,7 +120,7 @@ impl SchemeSync for ShmScheme { } } fn unlinkat(&mut self, dirfd: usize, path: &str, flags: usize, _ctx: &CallerCtx) -> Result<()> { - let handle = self.handles.get(&dirfd).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(dirfd)?; if !matches!(handle, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } @@ -152,11 +141,7 @@ impl SchemeSync for ShmScheme { Ok(()) } fn fstat(&mut self, id: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { - let path = self - .handles - .get(&id) - .and_then(Handle::as_shm) - .ok_or(Error::new(EBADF))?; + let path = self.handles.get(id).and_then(Handle::as_shm)?; let size = self .maps .get(path) @@ -174,11 +159,7 @@ impl SchemeSync for ShmScheme { Ok(()) } fn fsize(&mut self, id: usize, _ctx: &CallerCtx) -> Result { - let path = self - .handles - .get(&id) - .and_then(Handle::as_shm) - .ok_or(Error::new(EBADF))?; + let path = self.handles.get(id).and_then(Handle::as_shm)?; let size = self .maps .get(path) @@ -189,11 +170,7 @@ impl SchemeSync for ShmScheme { Ok(size as u64) } fn ftruncate(&mut self, id: usize, len: u64, _ctx: &CallerCtx) -> Result<()> { - let path = self - .handles - .get(&id) - .and_then(Handle::as_shm) - .ok_or(Error::new(EBADF))?; + let path = self.handles.get(id).and_then(Handle::as_shm)?; self.maps .get_mut(path) .expect("handle pointing to nothing") @@ -208,11 +185,7 @@ impl SchemeSync for ShmScheme { _flags: MapFlags, _ctx: &CallerCtx, ) -> Result { - let path = self - .handles - .get(&id) - .and_then(Handle::as_shm) - .ok_or(Error::new(EBADF))?; + let path = self.handles.get(id).and_then(Handle::as_shm)?; self.maps .get_mut(path) .expect("handle pointing to nothing") @@ -227,11 +200,7 @@ impl SchemeSync for ShmScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - let path = self - .handles - .get(&id) - .and_then(Handle::as_shm) - .ok_or(Error::new(EBADF))?; + let path = self.handles.get(id).and_then(Handle::as_shm)?; self.maps .get_mut(path) .expect("handle pointing to nothing") @@ -246,11 +215,7 @@ impl SchemeSync for ShmScheme { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - let path = self - .handles - .get(&id) - .and_then(Handle::as_shm) - .ok_or(Error::new(EBADF))?; + let path = self.handles.get(id).and_then(Handle::as_shm)?; self.maps .get_mut(path) .expect("handle pointing to nothing") diff --git a/logd/Cargo.toml b/logd/Cargo.toml index e542c06d86..85e617e6ff 100644 --- a/logd/Cargo.toml +++ b/logd/Cargo.toml @@ -10,6 +10,7 @@ redox_syscall.workspace = true daemon = { path = "../daemon" } libredox.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../scheme-utils" } [lints] workspace = true diff --git a/logd/src/scheme.rs b/logd/src/scheme.rs index 196e223178..fe7ae85420 100644 --- a/logd/src/scheme.rs +++ b/logd/src/scheme.rs @@ -7,6 +7,7 @@ use std::sync::mpsc::{self, Sender}; use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult, SendFdRequest, Socket}; +use scheme_utils::HandleMap; use syscall::error::*; use syscall::schemev2::NewFdFlags; @@ -20,11 +21,10 @@ pub enum LogHandle { } pub struct LogScheme<'sock> { - next_id: usize, socket: &'sock Socket, kernel_debug: File, output_tx: Sender, - handles: BTreeMap, + handles: HandleMap, } enum OutputCmd { @@ -88,11 +88,10 @@ impl<'sock> LogScheme<'sock> { }); LogScheme { - next_id: 0, socket, kernel_debug, output_tx, - handles: BTreeMap::new(), + handles: HandleMap::new(), } } @@ -133,10 +132,7 @@ impl<'sock> LogScheme<'sock> { impl<'sock> SchemeSync for LogScheme<'sock> { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.next_id += 1; - self.handles.insert(id, LogHandle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(LogHandle::SchemeRoot)) } fn openat( &mut self, @@ -146,27 +142,18 @@ impl<'sock> SchemeSync for LogScheme<'sock> { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> Result { - if !matches!( - self.handles.get(&dirfd).ok_or(Error::new(EBADF))?, - LogHandle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, LogHandle::SchemeRoot) { return Err(Error::new(EACCES)); } - let id = self.next_id; - self.next_id += 1; - - if path == "add_sink" { - self.handles.insert(id, LogHandle::AddSink); + let id = if path == "add_sink" { + self.handles.insert(LogHandle::AddSink) } else { - self.handles.insert( - id, - LogHandle::Log { - context: path.to_string().into_boxed_str(), - bufs: BTreeMap::new(), - }, - ); - } + self.handles.insert(LogHandle::Log { + context: path.to_string().into_boxed_str(), + bufs: BTreeMap::new(), + }) + }; Ok(OpenResult::ThisScheme { number: id, @@ -182,7 +169,7 @@ impl<'sock> SchemeSync for LogScheme<'sock> { _flags: u32, _ctx: &CallerCtx, ) -> Result { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let _handle = self.handles.get(id)?; // TODO @@ -197,7 +184,7 @@ impl<'sock> SchemeSync for LogScheme<'sock> { _flags: u32, ctx: &CallerCtx, ) -> Result { - let (context, bufs) = match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + let (context, bufs) = match self.handles.get_mut(id)? { LogHandle::Log { context, bufs } => (context, bufs), LogHandle::SchemeRoot | LogHandle::AddSink => return Err(Error::new(EBADF)), }; @@ -218,10 +205,7 @@ impl<'sock> SchemeSync for LogScheme<'sock> { fn on_sendfd(&mut self, sendfd_request: &SendFdRequest) -> Result { let id = sendfd_request.id(); - if !matches!( - self.handles.get(&id).ok_or(Error::new(EBADF))?, - LogHandle::AddSink - ) { + if !matches!(self.handles.get(id)?, LogHandle::AddSink) { return Err(Error::new(EBADF)); } @@ -239,13 +223,13 @@ impl<'sock> SchemeSync for LogScheme<'sock> { } fn fcntl(&mut self, id: usize, _cmd: usize, _arg: usize, _ctx: &CallerCtx) -> Result { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let _handle = self.handles.get(id)?; Ok(0) } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(id)?; let scheme_path = b"/scheme/log/"; @@ -271,7 +255,7 @@ impl<'sock> SchemeSync for LogScheme<'sock> { } fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let _handle = self.handles.get(id)?; //TODO: flush remaining data? @@ -279,6 +263,6 @@ impl<'sock> SchemeSync for LogScheme<'sock> { } fn on_close(&mut self, id: usize) { - self.handles.remove(&id); + self.handles.remove(id); } } diff --git a/netstack/Cargo.toml b/netstack/Cargo.toml index cdb53fb667..589eddc315 100644 --- a/netstack/Cargo.toml +++ b/netstack/Cargo.toml @@ -16,6 +16,7 @@ redox-log.workspace = true libredox = { workspace = true, features = ["mkns"] } anyhow.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../scheme-utils" } [dependencies.log] workspace = true diff --git a/netstack/src/scheme/mod.rs b/netstack/src/scheme/mod.rs index 476daf2d34..baaf360ee5 100644 --- a/netstack/src/scheme/mod.rs +++ b/netstack/src/scheme/mod.rs @@ -457,7 +457,7 @@ where let scheme = &mut self.scheme; let state = &mut self.state; - for (&fd, handle) in &mut scheme.handles { + for (&fd, handle) in scheme.handles.iter_mut() { let Handle::File(file) = handle else { continue; }; diff --git a/netstack/src/scheme/netcfg/mod.rs b/netstack/src/scheme/netcfg/mod.rs index 150df71e72..978be20037 100644 --- a/netstack/src/scheme/netcfg/mod.rs +++ b/netstack/src/scheme/netcfg/mod.rs @@ -6,6 +6,7 @@ use redox_scheme::{ scheme::{register_scheme_inner, SchemeState, SchemeSync}, CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket, }; +use scheme_utils::HandleMap; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address}; use std::cell::RefCell; use std::collections::BTreeMap; @@ -343,8 +344,7 @@ impl NetCfgScheme { })); let mut inner = NetCfgSchemeInner { scheme_file, - next_fd: 1, - handles: BTreeMap::new(), + handles: HandleMap::new(), root_node: mk_root_node( iface, Rc::clone(¬ifier), @@ -426,8 +426,7 @@ enum Handle { struct NetCfgSchemeInner { scheme_file: Socket, - next_fd: usize, - handles: BTreeMap, + handles: HandleMap, root_node: CfgNodeRef, notifier: NotifierRef, } @@ -443,10 +442,7 @@ impl NetCfgSchemeInner { impl SchemeSync for NetCfgSchemeInner { fn scheme_root(&mut self) -> SyscallResult { - let id = self.next_fd; - self.next_fd += 1; - self.handles.insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( @@ -458,10 +454,7 @@ impl SchemeSync for NetCfgSchemeInner { ctx: &CallerCtx, ) -> SyscallResult { { - let handle = self - .handles - .get(&dirfd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get(dirfd)?; if !matches!(handle, Handle::SchemeRoot) { return Err(SyscallError::new(syscall::EACCES)); @@ -481,28 +474,23 @@ impl SchemeSync for NetCfgSchemeInner { } let current_node = current_node.borrow(); let read_buf = Vec::from(current_node.read()); - let fd = self.next_fd; + let fd = self.handles.insert(Handle::File(NetCfgFile { + path: path.to_owned(), + is_dir: current_node.is_dir(), + is_writable: current_node.is_writable(), + is_readable: current_node.is_readable(), + node_writer: if current_node.is_writable() { + current_node.new_writer() + } else { + None + }, + uid: ctx.uid, + pos: 0, + read_buf, + write_buf: vec![], + done: false, + })); trace!("open {} {}", fd, path); - self.next_fd += 1; - self.handles.insert( - fd, - Handle::File(NetCfgFile { - path: path.to_owned(), - is_dir: current_node.is_dir(), - is_writable: current_node.is_writable(), - is_readable: current_node.is_readable(), - node_writer: if current_node.is_writable() { - current_node.new_writer() - } else { - None - }, - uid: ctx.uid, - pos: 0, - read_buf, - write_buf: vec![], - done: false, - }), - ); Ok(OpenResult::ThisScheme { number: fd, flags: NewFdFlags::empty(), @@ -511,7 +499,7 @@ impl SchemeSync for NetCfgSchemeInner { fn on_close(&mut self, fd: usize) { trace!("close {}", fd); - if let Some(handle) = self.handles.remove(&fd) { + if let Some(handle) = self.handles.remove(fd) { match handle { Handle::SchemeRoot => { // SchemeRoot closed, nothing specific to clean up @@ -534,10 +522,7 @@ impl SchemeSync for NetCfgSchemeInner { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> SyscallResult { - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; let file = match handle { Handle::File(file) => file, @@ -575,10 +560,7 @@ impl SchemeSync for NetCfgSchemeInner { _fcntl_flags: u32, _ctx: &CallerCtx, ) -> SyscallResult { - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; let file = match handle { Handle::File(file) => file, @@ -595,10 +577,7 @@ impl SchemeSync for NetCfgSchemeInner { } fn fstat(&mut self, fd: usize, stat: &mut Stat, _ctx: &CallerCtx) -> SyscallResult<()> { - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; match handle { Handle::SchemeRoot => return Err(SyscallError::new(syscall::EBADF)), @@ -625,10 +604,7 @@ impl SchemeSync for NetCfgSchemeInner { events: SyscallEventFlags, _ctx: &CallerCtx, ) -> SyscallResult { - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; match handle { Handle::SchemeRoot => return Err(SyscallError::new(syscall::EBADF)), @@ -644,10 +620,7 @@ impl SchemeSync for NetCfgSchemeInner { } fn fsync(&mut self, fd: usize, _ctx: &CallerCtx) -> SyscallResult<()> { - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; let file = match handle { Handle::File(file) => file, diff --git a/netstack/src/scheme/socket.rs b/netstack/src/scheme/socket.rs index b3b5fcd51c..fc8e558b51 100644 --- a/netstack/src/scheme/socket.rs +++ b/netstack/src/scheme/socket.rs @@ -15,6 +15,7 @@ use redox_scheme::{ scheme::{register_scheme_inner, Op, SchemeSync}, CallerCtx, OpenResult, Socket, }; +use scheme_utils::HandleMap; use syscall::data::TimeSpec; use syscall::flag::{EVENT_READ, EVENT_WRITE}; use syscall::schemev2::NewFdFlags; @@ -274,8 +275,7 @@ pub struct SocketScheme where SocketT: SchemeSocket + AnySocket<'static>, { - next_fd: usize, - pub handles: BTreeMap>, + pub handles: HandleMap>, ref_counts: BTreeMap, context: Context, pub socket_set: Rc>, @@ -296,8 +296,7 @@ where scheme_file: Socket, ) -> SyscallResult> { let mut scheme = SocketScheme { - next_fd: 1, - handles: BTreeMap::new(), + handles: HandleMap::new(), ref_counts: BTreeMap::new(), socket_set, scheme_data: SocketT::new_scheme_data(), @@ -313,10 +312,7 @@ where pub fn handle_block(&mut self, op: &Op) -> SyscallResult> { let fd = op.file_id().expect("op is not fd based request"); let (read_timeout, write_timeout) = { - let handle = self - .handles - .get(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get(fd)?; if let Handle::File(SchemeFile::Socket(ref scheme_file)) = *handle { Ok((scheme_file.read_timeout, scheme_file.write_timeout)) @@ -351,10 +347,7 @@ where setting: Setting, buf: &mut [u8], ) -> SyscallResult { - let file = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let file = self.handles.get_mut(fd)?; let file = match *file { Handle::File(SchemeFile::Socket(ref mut file)) => file, @@ -400,10 +393,7 @@ where setting: Setting, buf: &[u8], ) -> SyscallResult { - let file = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let file = self.handles.get_mut(fd)?; let file = match *file { Handle::File(SchemeFile::Socket(ref mut file)) => file, _ => return Err(SyscallError::new(syscall::EBADF)), @@ -469,10 +459,7 @@ where Ok(0) } SocketCall::GetSockOpt => { - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; match *handle { Handle::File(ref mut file) => { @@ -506,10 +493,7 @@ where // SocketCall::Unbind => self.handle_unbind(id), // SocketCall::GetToken => self.handle_get_token(id, payload), SocketCall::GetPeerName => { - let file = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let file = self.handles.get_mut(fd)?; let file = match *file { Handle::File(ref mut f) => f, @@ -522,10 +506,7 @@ where } SocketCall::RecvMsg => { let flags = metadata[1] as usize; - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; match *handle { Handle::File(ref mut file) => { @@ -542,11 +523,7 @@ where SocketCall::Shutdown => { let how = metadata[1] as usize; - match self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))? - { + match self.handles.get_mut(fd)? { Handle::File(file) => { let mut socket_set = self.socket_set.borrow_mut(); let socket = socket_set.get_mut::(file.socket_handle()); @@ -590,10 +567,7 @@ where write_enabled, }; - let id = self.next_fd; - self.next_fd += 1; - - self.handles.insert(id, Handle::Null(null)); + let id = self.handles.insert(Handle::Null(null)); Ok(OpenResult::ThisScheme { number: id, @@ -621,11 +595,8 @@ where data, }); - let id = self.next_fd; - self.next_fd += 1; - self.ref_counts.insert(socket_handle, 1); - self.handles.insert(id, Handle::File(file)); + let id = self.handles.insert(Handle::File(file)); Ok(OpenResult::ThisScheme { number: id, @@ -640,10 +611,7 @@ where SocketT: SchemeSocket + AnySocket<'static>, { fn scheme_root(&mut self) -> SyscallResult { - let id = self.next_fd; - self.next_fd += 1; - self.handles.insert(id, Handle::SchemeRoot); - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( @@ -654,12 +622,7 @@ where _fcntl_flags: u32, ctx: &CallerCtx, ) -> SyscallResult { - let handle = self - .handles - .get(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; - - match handle { + match self.handles.get(fd)? { Handle::SchemeRoot => self.open_inner(path, flags, ctx.uid, ctx.gid, true, true), _ => Err(SyscallError::new(syscall::EACCES)), } @@ -676,9 +639,7 @@ where } fn on_close(&mut self, fd: usize) { - let handle = if let Some(handle) = self.handles.remove(&fd) { - handle - } else { + let Some(handle) = self.handles.remove(fd) else { return; }; @@ -738,10 +699,7 @@ where _ctx: &CallerCtx, ) -> SyscallResult { let (fd, setting) = { - let file = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let file = self.handles.get_mut(fd)?; match *file { Handle::File(SchemeFile::Setting(ref setting_handle)) => { @@ -773,10 +731,7 @@ where _ctx: &CallerCtx, ) -> SyscallResult { let (fd, setting) = { - let file = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let file = self.handles.get_mut(fd)?; match *file { Handle::File(SchemeFile::Setting(ref setting_handle)) => { (setting_handle.fd, setting_handle.setting) @@ -804,10 +759,7 @@ where let path = str::from_utf8(buf).or_else(|_| Err(SyscallError::new(syscall::EINVAL)))?; let new_file = { - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; let file = match *handle { Handle::SchemeRoot => return Err(SyscallError::new(syscall::EBADF)), @@ -888,9 +840,7 @@ where new_handle }; - let id = self.next_fd; - self.handles.insert(id, Handle::File(new_file)); - self.next_fd += 1; + let id = self.handles.insert(Handle::File(new_file)); Ok(OpenResult::ThisScheme { number: id, @@ -904,10 +854,7 @@ where events: SyscallEventFlags, _ctx: &CallerCtx, ) -> SyscallResult { - let file = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let file = self.handles.get_mut(fd)?; let file = match *file { Handle::File(ref mut f) => f, @@ -929,10 +876,7 @@ where fn fsync(&mut self, fd: usize, _ctx: &CallerCtx) -> SyscallResult<()> { { - let _file = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let _file = self.handles.get_mut(fd)?; } Ok(()) // TODO Implement fsyncing @@ -940,10 +884,7 @@ where } fn fpath(&mut self, fd: usize, buf: &mut [u8], _ctx: &CallerCtx) -> SyscallResult { - let file = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let file = self.handles.get_mut(fd)?; let file = match *file { Handle::File(ref mut f) => f, @@ -963,10 +904,7 @@ where arg: usize, _ctx: &CallerCtx, ) -> SyscallResult { - let handle = self - .handles - .get_mut(&fd) - .ok_or_else(|| SyscallError::new(syscall::EBADF))?; + let handle = self.handles.get_mut(fd)?; match *handle { Handle::File(SchemeFile::Socket(ref mut socket_file)) => match cmd { diff --git a/ramfs/Cargo.toml b/ramfs/Cargo.toml index 197a939fc6..85a3ff9000 100644 --- a/ramfs/Cargo.toml +++ b/ramfs/Cargo.toml @@ -12,6 +12,7 @@ description = "RAM filesystem, which is useful for early logging" daemon = { path = "../daemon" } redox_syscall.workspace = true redox-scheme.workspace = true +scheme-utils = { path = "../scheme-utils" } libredox = { workspace = true, features = ["call"] } indexmap = "2.5.0" slab.workspace = true diff --git a/ramfs/src/scheme.rs b/ramfs/src/scheme.rs index d7dd530a63..36390995ac 100644 --- a/ramfs/src/scheme.rs +++ b/ramfs/src/scheme.rs @@ -1,10 +1,10 @@ -use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; use std::io::{Cursor, Seek}; use std::iter; use std::os::unix::io::AsRawFd; use std::{mem, str}; +use scheme_utils::HandleMap; use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; use syscall::error::{ EACCES, EBADF, EBADFD, EEXIST, EINVAL, EIO, EISDIR, ENOMEM, ENOSYS, ENOTDIR, ENOTEMPTY, @@ -33,8 +33,7 @@ enum Handle { pub struct Scheme { scheme_name: String, filesystem: Filesystem, - handles: HashMap, - next_id: usize, + handles: HandleMap, proc_creds_capability: libredox::Fd, } impl Scheme { @@ -43,8 +42,7 @@ impl Scheme { Ok(Self { scheme_name, filesystem: Filesystem::new()?, - handles: HashMap::new(), - next_id: 0, + handles: HandleMap::new(), proc_creds_capability: { libredox::Fd::open( "/scheme/proc/proc-creds-capability", @@ -168,10 +166,7 @@ impl Scheme { impl SchemeSync for Scheme { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.handles.insert(id, Handle::SchemeRoot); - self.next_id += 1; - Ok(id) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( &mut self, @@ -181,10 +176,7 @@ impl SchemeSync for Scheme { fcntl_flags: u32, ctx: &CallerCtx, ) -> Result { - if !matches!( - self.handles.get(&dirfd).ok_or(Error::new(EBADF))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } @@ -274,9 +266,7 @@ impl SchemeSync for Scheme { self.open_existing(path, flags | fcntl_flags as usize, ctx.uid, ctx.gid)? .0 }; - let new_id = self.next_id; - self.handles.insert(new_id, Handle::Inode(inode)); - self.next_id += 1; + let new_id = self.handles.insert(Handle::Inode(inode)); Ok(OpenResult::ThisScheme { number: new_id, flags: NewFdFlags::POSITIONED, @@ -284,10 +274,7 @@ impl SchemeSync for Scheme { } fn unlinkat(&mut self, dirfd: usize, path: &str, flags: usize, ctx: &CallerCtx) -> Result<()> { { - if !matches!( - self.handles.get(&dirfd).ok_or(Error::new(EBADF))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } } @@ -309,7 +296,7 @@ impl SchemeSync for Scheme { let Ok(offset) = usize::try_from(offset) else { return Ok(0); }; - let inode = match self.handles.get(&fd).ok_or(Error::new(EBADFD))? { + let inode = match self.handles.get(fd)? { Handle::Inode(inode) => inode, Handle::SchemeRoot => return Err(Error::new(EISDIR)), }; @@ -345,7 +332,7 @@ impl SchemeSync for Scheme { let Ok(offset) = usize::try_from(opaque_offset) else { return Ok(buf); }; - let inode = match self.handles.get(&fd).ok_or(Error::new(EBADFD))? { + let inode = match self.handles.get(fd)? { Handle::Inode(inode) => inode, Handle::SchemeRoot => return Err(Error::new(EISDIR)), }; @@ -380,7 +367,7 @@ impl SchemeSync for Scheme { let Ok(offset) = usize::try_from(offset) else { return Ok(0); }; - let inode = match self.handles.get(&fd).ok_or(Error::new(EBADFD))? { + let inode = match self.handles.get(fd)? { Handle::Inode(inode) => inode, Handle::SchemeRoot => return Err(Error::new(EISDIR)), }; @@ -410,7 +397,7 @@ impl SchemeSync for Scheme { } } fn fchmod(&mut self, fd: usize, mode: u16, _ctx: &CallerCtx) -> Result<()> { - let inode = match self.handles.get(&fd).ok_or(Error::new(EBADFD))? { + let inode = match self.handles.get(fd)? { Handle::Inode(inode) => inode, Handle::SchemeRoot => return Err(Error::new(EISDIR)), }; @@ -474,7 +461,7 @@ impl SchemeSync for Scheme { Err(Error::new(ENOSYS)) } fn fpath(&mut self, fd: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let mut current_inode = match *self.handles.get(&fd).ok_or(Error::new(EBADFD))? { + let mut current_inode = match *self.handles.get(fd)? { Handle::Inode(inode) => inode, Handle::SchemeRoot => return Err(Error::new(EISDIR)), }; @@ -523,7 +510,7 @@ impl SchemeSync for Scheme { Err(Error::new(ENOSYS)) } fn fstat(&mut self, fd: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { - let inode = match *self.handles.get(&fd).ok_or(Error::new(EBADFD))? { + let inode = match *self.handles.get(fd)? { Handle::Inode(inode) => inode, Handle::SchemeRoot => return Err(Error::new(EISDIR)), }; @@ -601,7 +588,7 @@ impl SchemeSync for Scheme { Ok(()) } fn ftruncate(&mut self, fd: usize, size: u64, _ctx: &CallerCtx) -> Result<()> { - let inode = match self.handles.get(&fd).ok_or(Error::new(EBADFD))? { + let inode = match self.handles.get(fd)? { Handle::Inode(inode) => inode, Handle::SchemeRoot => return Err(Error::new(EISDIR)), }; @@ -630,7 +617,7 @@ impl SchemeSync for Scheme { Ok(()) } fn futimens(&mut self, fd: usize, times: &[TimeSpec], _ctx: &CallerCtx) -> Result<()> { - let inode = match self.handles.get(&fd).ok_or(Error::new(EBADFD))? { + let inode = match self.handles.get(fd)? { Handle::Inode(inode) => inode, Handle::SchemeRoot => return Err(Error::new(EISDIR)), }; @@ -693,7 +680,7 @@ impl SchemeSync for Scheme { } impl Scheme { pub fn on_close(&mut self, fd: usize) { - let Some(Handle::Inode(inode)) = self.handles.remove(&fd) else { + let Some(Handle::Inode(inode)) = self.handles.remove(fd) else { return; }; let Some(inode_info) = self.filesystem.files.get_mut(&inode) else { diff --git a/randd/Cargo.toml b/randd/Cargo.toml index 09d69d32c2..6ff2d7e6e1 100644 --- a/randd/Cargo.toml +++ b/randd/Cargo.toml @@ -12,6 +12,7 @@ redox_syscall.workspace = true libredox.workspace = true sha2 = "0.8" redox-scheme.workspace = true +scheme-utils = { path = "../scheme-utils" } [target.'cfg(target_arch = "x86_64")'.dependencies] raw-cpuid = "11.0.1" diff --git a/randd/src/main.rs b/randd/src/main.rs index 4ffb68d502..19fc77d52b 100644 --- a/randd/src/main.rs +++ b/randd/src/main.rs @@ -17,6 +17,7 @@ use redox_scheme::{ scheme::{SchemeState, SchemeSync}, CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket, }; +use scheme_utils::HandleMap; use syscall::data::Stat; use syscall::flag::{EventFlags, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_WRONLY}; use syscall::schemev2::NewFdFlags; @@ -25,8 +26,6 @@ use syscall::{Error, Result, EACCES, EBADF, EEXIST, ENOENT, EPERM, MODE_CHR}; // Create an RNG Seed to create initial seed from the rdrand intel instruction use rand_core::SeedableRng; use sha2::{Digest, Sha256}; -use std::collections::BTreeMap; -use std::num::Wrapping; // This Daemon implements a Cryptographically Secure Random Number Generator // that does not block on read - i.e. it is equivalent to linux /dev/urandom @@ -148,11 +147,7 @@ struct RandScheme { // https://docs.rs/rand/0.5.0/rand/prng/chacha/struct.ChaChaRng.html // Allows 2^64 streams of random numbers, which we will equate with file numbers prng_stat: Stat, - handles: BTreeMap, - // calls the system RNG (us) for entropy to protect against HashDOS attacks. - // Trying to create a HashMap causes a system crash. - // - next_id: Wrapping, + handles: HandleMap, } impl RandScheme { @@ -166,15 +161,14 @@ impl RandScheme { st_uid: 0, ..Default::default() }, - handles: BTreeMap::new(), - next_id: Wrapping(0), + handles: HandleMap::new(), } } /// Gets the open file info for a file descriptor if it is open - error otherwise. fn get_fd(&self, fd: usize) -> Result<&OpenFileInfo> { // Check we've got a valid file descriptor - let handle = self.handles.get(&fd).ok_or(Error::new(EBADF))?; + let handle = self.handles.get(fd)?; handle.as_file().ok_or(Error::new(EBADF)) } /// Checks to see if the op (MODE_READ, MODE_WRITE) can be performed on the open file @@ -212,7 +206,6 @@ impl RandScheme { return Err(Error::new(EEXIST)); } - let id = self.next_id; let open_file_info = OpenFileInfo { o_flags: flags, file_stat: self.prng_stat, @@ -231,20 +224,10 @@ impl RandScheme { return Err(Error::new(EPERM)); } - self.handles.insert(id.0, Handle::File(open_file_info)); - - // If we've looped round there's a small chance that the file descriptor still exists, so loop till we get one that doesn't - self.next_id += Wrapping(1); - loop { - if !self.handles.contains_key(&self.next_id.0) { - break; - } else { - self.next_id += Wrapping(1); - } - } + let id = self.handles.insert(Handle::File(open_file_info)); Ok(OpenResult::ThisScheme { - number: id.0, + number: id, flags: NewFdFlags::empty(), }) } @@ -354,20 +337,7 @@ fn test_scheme_perms() { impl SchemeSync for RandScheme { fn scheme_root(&mut self) -> Result { - let id = self.next_id; - self.handles.insert(id.0, Handle::SchemeRoot); - - // Get the next file descriptor - self.next_id += Wrapping(1); - // If we've looped round there's a small chance that the file descriptor still exists, so loop till we get one that doesn't - loop { - if !self.handles.contains_key(&self.next_id.0) { - break; - } else { - self.next_id += Wrapping(1); - } - } - Ok(id.0) + Ok(self.handles.insert(Handle::SchemeRoot)) } fn openat( @@ -378,10 +348,7 @@ impl SchemeSync for RandScheme { _fcntl_flags: u32, ctx: &CallerCtx, ) -> Result { - if !matches!( - self.handles.get(&dirfd).ok_or(Error::new(EBADF))?, - Handle::SchemeRoot - ) { + if !matches!(self.handles.get(dirfd)?, Handle::SchemeRoot) { return Err(Error::new(EACCES)); } @@ -489,7 +456,7 @@ impl SchemeSync for RandScheme { fn on_close(&mut self, file: usize) { // just remove the file descriptor from the open descriptors - let _ = self.handles.remove(&file); + self.handles.remove(file); } } diff --git a/scheme-utils/Cargo.toml b/scheme-utils/Cargo.toml new file mode 100644 index 0000000000..72719c52ff --- /dev/null +++ b/scheme-utils/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "scheme-utils" +version = "0.0.0" +edition = "2024" + +[dependencies] +libredox.workspace = true +redox_syscall.workspace = true + +[lints] +workspace = true diff --git a/scheme-utils/src/lib.rs b/scheme-utils/src/lib.rs new file mode 100644 index 0000000000..db07fcd7dc --- /dev/null +++ b/scheme-utils/src/lib.rs @@ -0,0 +1,67 @@ +use std::collections::{BTreeMap, btree_map}; +use std::num::Wrapping; + +use syscall::{EBADF, Error, Result}; + +pub struct HandleMap { + handles: BTreeMap, + next_id: Wrapping, +} + +impl HandleMap { + pub const fn new() -> Self { + HandleMap { + handles: BTreeMap::new(), + next_id: Wrapping(1), + } + } + + pub fn insert(&mut self, handle: T) -> usize { + let id = self.next_id; + + // If we've looped round there's a small chance that the file descriptor still exists, so loop till we get one that doesn't + self.next_id += Wrapping(1); + loop { + if !self.handles.contains_key(&self.next_id.0) { + break; + } else { + self.next_id += Wrapping(1); + } + } + + self.handles.insert(id.0, handle); + id.0 + } + + pub fn remove(&mut self, id: usize) -> Option { + self.handles.remove(&id) + } + + pub fn get(&self, id: usize) -> Result<&T> { + self.handles.get(&id).ok_or(Error::new(EBADF)) + } + + pub fn get_mut(&mut self, id: usize) -> Result<&mut T> { + self.handles.get_mut(&id).ok_or(Error::new(EBADF)) + } + + pub fn iter(&self) -> btree_map::Iter<'_, usize, T> { + self.handles.iter() + } + + pub fn iter_mut(&mut self) -> btree_map::IterMut<'_, usize, T> { + self.handles.iter_mut() + } + + pub fn keys(&self) -> btree_map::Keys<'_, usize, T> { + self.handles.keys() + } + + pub fn values(&self) -> btree_map::Values<'_, usize, T> { + self.handles.values() + } + + pub fn values_mut(&mut self) -> btree_map::ValuesMut<'_, usize, T> { + self.handles.values_mut() + } +}