diff --git a/drivers/audio/ac97d/src/device.rs b/drivers/audio/ac97d/src/device.rs index 66d732ef3a..a9217dbab6 100644 --- a/drivers/audio/ac97d/src/device.rs +++ b/drivers/audio/ac97d/src/device.rs @@ -2,7 +2,7 @@ use common::io::Pio; use redox_scheme::scheme::SchemeSync; use redox_scheme::CallerCtx; use redox_scheme::OpenResult; -use scheme_utils::HandleMap; +use scheme_utils::{FpathWriter, HandleMap}; use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, ENOENT}; use syscall::schemev2::NewFdFlags; use syscall::EWOULDBLOCK; @@ -323,22 +323,8 @@ 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)?; - if !matches!(handle, Handle::Todo) { - return Err(Error::new(EBADF)); - } - } - - let mut i = 0; - let scheme_path = b"/scheme/audiohw"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - Ok(i) + fn fpath(&mut self, _id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { + FpathWriter::with(buf, "audiohw", |_| Ok(())) } fn on_close(&mut self, id: usize) { diff --git a/drivers/audio/ihdad/src/hda/device.rs b/drivers/audio/ihdad/src/hda/device.rs index 1b595ca564..78e8f0a281 100755 --- a/drivers/audio/ihdad/src/hda/device.rs +++ b/drivers/audio/ihdad/src/hda/device.rs @@ -13,7 +13,7 @@ use common::timeout::Timeout; use redox_scheme::scheme::SchemeSync; use redox_scheme::CallerCtx; use redox_scheme::OpenResult; -use scheme_utils::HandleMap; +use scheme_utils::{FpathWriter, HandleMap}; use syscall::error::{Error, Result, EACCES, EBADF, EIO, ENODEV, EWOULDBLOCK}; use spin::Mutex; @@ -1076,17 +1076,8 @@ 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)?; - - let mut i = 0; - let scheme_path = b"/scheme/audiohw"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - Ok(i) + fn fpath(&mut self, _id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { + FpathWriter::with(buf, "audiohw", |_| Ok(())) } fn on_close(&mut self, id: usize) { diff --git a/drivers/audio/sb16d/src/device.rs b/drivers/audio/sb16d/src/device.rs index 289522cff6..5667ce764a 100644 --- a/drivers/audio/sb16d/src/device.rs +++ b/drivers/audio/sb16d/src/device.rs @@ -5,7 +5,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 scheme_utils::{FpathWriter, HandleMap}; use syscall::error::{Error, Result, EACCES, EBADF, ENODEV}; use syscall::schemev2::NewFdFlags; @@ -222,17 +222,8 @@ impl SchemeSync for Sb16 { Err(Error::new(EBADF)) } - fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let mut handles = self.handles.lock(); - let _handle = handles.get_mut(id)?; - - let mut i = 0; - let scheme_path = b"/scheme/audiohw"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - Ok(i) + fn fpath(&mut self, _id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { + FpathWriter::with(buf, "audiohw", |_| Ok(())) } fn on_close(&mut self, id: usize) { diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 3bca38db1f..eab0be9c3e 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -18,7 +18,7 @@ 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 scheme_utils::{FpathWriter, HandleMap}; use syscall::schemev2::NewFdFlags; use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EINVAL, ENOENT, EOPNOTSUPP}; @@ -424,16 +424,17 @@ impl SchemeSync for GraphicsSchemeInner { } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> syscall::Result { - let path = match self.handles.get(id)? { - Handle::V2 { - vt, - next_id: _, - buffers: _, - } => format!("/scheme/{}/v2/{vt}", self.scheme_name), - Handle::SchemeRoot => return Err(Error::new(EOPNOTSUPP)), - }; - buf[..path.len()].copy_from_slice(path.as_bytes()); - Ok(path.len()) + FpathWriter::with(buf, &self.scheme_name, |w| { + match self.handles.get(id)? { + Handle::V2 { + vt, + next_id: _, + buffers: _, + } => write!(w, "v2/{vt}").unwrap(), + Handle::SchemeRoot => return Err(Error::new(EOPNOTSUPP)), + }; + Ok(()) + }) } fn call( diff --git a/drivers/graphics/fbbootlogd/src/scheme.rs b/drivers/graphics/fbbootlogd/src/scheme.rs index 65bc6630b5..812c4a5bc3 100644 --- a/drivers/graphics/fbbootlogd/src/scheme.rs +++ b/drivers/graphics/fbbootlogd/src/scheme.rs @@ -9,6 +9,7 @@ use inputd::ConsumerHandle; use orbclient::{Event, EventOption}; use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult}; +use scheme_utils::FpathWriter; use syscall::schemev2::NewFdFlags; use syscall::{Error, Result, EACCES, EBADF, EINVAL, ENOENT}; @@ -196,15 +197,7 @@ impl SchemeSync for FbbootlogScheme { } fn fpath(&mut self, _id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let path = b"fbbootlog:"; - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) + FpathWriter::with_legacy(buf, "fbbootlog", |_| Ok(())) } fn fsync(&mut self, _id: usize, _ctx: &CallerCtx) -> Result<()> { diff --git a/drivers/graphics/fbcond/src/scheme.rs b/drivers/graphics/fbcond/src/scheme.rs index 3d11e5e1ae..1bee134e29 100644 --- a/drivers/graphics/fbcond/src/scheme.rs +++ b/drivers/graphics/fbcond/src/scheme.rs @@ -4,7 +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 scheme_utils::{FpathWriter, HandleMap}; use syscall::schemev2::NewFdFlags; use syscall::{Error, EventFlags, Result, EACCES, EAGAIN, EBADF, ENOENT, O_NONBLOCK}; @@ -125,18 +125,11 @@ impl SchemeSync for FbconScheme { } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let handle = self.get_vt_handle_mut(id)?; - - let path_str = format!("fbcon:{}", handle.vt_i.0); - let path = path_str.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) + FpathWriter::with_legacy(buf, "fbcon", |w| { + let handle = self.get_vt_handle_mut(id)?; + write!(w, "{}", handle.vt_i.0).unwrap(); + Ok(()) + }) } fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { diff --git a/drivers/inputd/src/main.rs b/drivers/inputd/src/main.rs index f884203243..07aa943eee 100644 --- a/drivers/inputd/src/main.rs +++ b/drivers/inputd/src/main.rs @@ -25,7 +25,7 @@ use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult, Response, SignalBehavior, Socket}; use orbclient::{Event, EventOption}; -use scheme_utils::{Blocking, HandleMap}; +use scheme_utils::{Blocking, FpathWriter, HandleMap}; use syscall::schemev2::NewFdFlags; use syscall::{Error as SysError, EventFlags, EACCES, EBADF, EEXIST, EINVAL}; @@ -269,19 +269,17 @@ impl SchemeSync for InputScheme { } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> syscall::Result { - let handle = self.handles.get(id)?; + let display = self.display.as_ref().ok_or(SysError::new(EINVAL))?; + FpathWriter::with(buf, display, |w| { + let handle = self.handles.get(id)?; - if let Handle::Consumer { vt, .. } = handle { - let display = self.display.as_ref().ok_or(SysError::new(EINVAL))?; - let vt = format!("/scheme/{}/{vt}", display); - - let size = core::cmp::min(vt.len(), buf.len()); - buf[..size].copy_from_slice(&vt.as_bytes()[..size]); - - Ok(size) - } else { - Err(SysError::new(EINVAL)) - } + if let Handle::Consumer { vt, .. } = handle { + write!(w, "{vt}").unwrap(); + Ok(()) + } else { + Err(SysError::new(EINVAL)) + } + }) } fn read( diff --git a/drivers/net/driver-network/src/lib.rs b/drivers/net/driver-network/src/lib.rs index d536a04fd3..39d26d851b 100644 --- a/drivers/net/driver-network/src/lib.rs +++ b/drivers/net/driver-network/src/lib.rs @@ -6,7 +6,7 @@ use redox_scheme::{ scheme::{IntoTag, Op, SchemeResponse, SchemeState, SchemeSync}, CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket, }; -use scheme_utils::HandleMap; +use scheme_utils::{FpathWriter, HandleMap}; use syscall::schemev2::NewFdFlags; use syscall::{ Error, EventFlags, Result, Stat, EACCES, EAGAIN, EBADF, EINTR, EINVAL, EWOULDBLOCK, MODE_FILE, @@ -315,38 +315,15 @@ impl SchemeSync for NetworkSchemeInner { } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let handle = self.handles.get(id)?; - - const PREFIX: &[u8] = b"/scheme/"; - let len = cmp::min(PREFIX.len(), buf.len()); - buf[..len].copy_from_slice(&PREFIX[..len]); - if len < PREFIX.len() { - return Ok(len); - } - let mut i = len; - - let scheme_name = self.scheme_name.as_bytes(); - let mut j = 0; - while i < buf.len() && j < scheme_name.len() { - buf[i] = scheme_name[j]; - i += 1; - j += 1; - } - - let path = match handle { - Handle::Data { .. } => &b""[..], - Handle::Mac { .. } => &b"mac"[..], - _ => &b""[..], - }; - - j = 0; - while i < buf.len() && j < path.len() { - buf[i] = path[j]; - i += 1; - j += 1; - } - - Ok(i) + FpathWriter::with(buf, &self.scheme_name, |w| { + let path = match self.handles.get(id)? { + Handle::Data { .. } => "", + Handle::Mac { .. } => "mac", + _ => "", + }; + write!(w, "{path}").unwrap(); + Ok(()) + }) } fn fstat(&mut self, id: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { diff --git a/drivers/storage/driver-block/src/lib.rs b/drivers/storage/driver-block/src/lib.rs index 51bb0e72d1..315aa659d1 100644 --- a/drivers/storage/driver-block/src/lib.rs +++ b/drivers/storage/driver-block/src/lib.rs @@ -13,7 +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 scheme_utils::{FpathWriter, HandleMap}; use syscall::dirent::DirentBuf; use syscall::schemev2::NewFdFlags; use syscall::{ @@ -559,50 +559,19 @@ impl SchemeAsync for DiskSchemeInner { } async fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let handle = self.handles.get(id)?; - - let mut i = 0; - - let scheme_name = self.scheme_name.as_bytes(); - let mut j = 0; - // TODO: copy_from_slice - while i < buf.len() && j < scheme_name.len() { - buf[i] = scheme_name[j]; - i += 1; - j += 1; - } - - if i < buf.len() { - buf[i] = b':'; - i += 1; - } - - match *handle { - Handle::List(_) => (), - Handle::Disk(number) => { - let number_str = format!("{}", number); - let number_bytes = number_str.as_bytes(); - j = 0; - while i < buf.len() && j < number_bytes.len() { - buf[i] = number_bytes[j]; - i += 1; - j += 1; + FpathWriter::with_legacy(buf, &self.scheme_name, |w| { + match *self.handles.get(id)? { + Handle::List(_) => (), + Handle::Disk(number) => { + write!(w, "{number}").unwrap(); } - } - Handle::Partition(disk_num, part_num) => { - let number_str = format!("{}p{}", disk_num, part_num); - let number_bytes = number_str.as_bytes(); - j = 0; - while i < buf.len() && j < number_bytes.len() { - buf[i] = number_bytes[j]; - i += 1; - j += 1; + Handle::Partition(disk_num, part_num) => { + write!(w, "{disk_num}p{part_num}").unwrap(); } + Handle::SchemeRoot => return Err(Error::new(EBADF)), } - Handle::SchemeRoot => return Err(Error::new(EBADF)), - } - - Ok(i) + Ok(()) + }) } async fn read( diff --git a/drivers/usb/xhcid/src/xhci/scheme.rs b/drivers/usb/xhcid/src/xhci/scheme.rs index b524f5d834..ca27b3fec7 100644 --- a/drivers/usb/xhcid/src/xhci/scheme.rs +++ b/drivers/usb/xhcid/src/xhci/scheme.rs @@ -26,6 +26,7 @@ use common::dma::Dma; use futures::executor::block_on; use log::{debug, error, info, trace, warn}; use redox_scheme::scheme::SchemeSync; +use scheme_utils::FpathWriter; use smallvec::SmallVec; use common::io::Io; @@ -197,7 +198,7 @@ impl Handle { /// /// # Returns /// - A [String] containing the scheme path that the handle is associated with. - pub(crate) fn to_scheme(&self) -> String { + pub(crate) fn to_path(&self) -> String { match self { Handle::TopLevel(_) => String::from(""), Handle::Port(port_num, _) => { @@ -2212,22 +2213,12 @@ impl SchemeSync for &Xhci { Ok(()) } - fn fpath(&mut self, fd: usize, buffer: &mut [u8], _ctx: &CallerCtx) -> Result { - let mut cursor = io::Cursor::new(buffer); - - let guard = self.handles.get(&fd).ok_or(Error::new(EBADF))?; - let scheme = (&*guard).to_scheme(); - - write!(cursor, "{}", scheme.as_str()).expect( - format!( - "Failed to convert the file descriptor with value {} to the associated file path", - fd - ) - .as_str(), - ); - - let src_len = usize::try_from(cursor.seek(io::SeekFrom::End(0)).unwrap()).unwrap(); - Ok(src_len) + fn fpath(&mut self, fd: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { + FpathWriter::with(buf, "xhci", |w| { + let handle = self.handles.get(&fd).ok_or(Error::new(EBADF))?; + write!(w, "{}", handle.to_path()).unwrap(); + Ok(()) + }) } fn read( diff --git a/ipcd/src/chan.rs b/ipcd/src/chan.rs index f4a94e2444..ec19751283 100644 --- a/ipcd/src/chan.rs +++ b/ipcd/src/chan.rs @@ -1,4 +1,5 @@ use redox_scheme::{scheme::SchemeSync, CallerCtx, OpenResult, Response, SignalBehavior, Socket}; +use scheme_utils::FpathWriter; use std::{ cmp, collections::{HashMap, VecDeque}, @@ -330,24 +331,15 @@ impl<'sock> SchemeSync for ChanScheme<'sock> { } } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - // Write scheme name - const PREFIX: &[u8] = b"chan:"; - let len = cmp::min(PREFIX.len(), buf.len()); - buf[..len].copy_from_slice(&PREFIX[..len]); - if len < PREFIX.len() { - return Ok(len); - } + FpathWriter::with_legacy(buf, "chan", |w| { + let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + if let Extra::SchemeRoot = handle.extra { + return Ok(()); + } + w.push_str(handle.path.as_ref().ok_or(Error::new(EBADF))?); - // Write path - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - if let Extra::SchemeRoot = handle.extra { - return Ok(len); - } - let path = handle.path.as_ref().ok_or(Error::new(EBADF))?; - 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) + Ok(()) + }) } fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { self.handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(())) diff --git a/ipcd/src/shm.rs b/ipcd/src/shm.rs index 61d5ea5659..2ea6964e05 100644 --- a/ipcd/src/shm.rs +++ b/ipcd/src/shm.rs @@ -1,5 +1,5 @@ use redox_scheme::{scheme::SchemeSync, CallerCtx, OpenResult}; -use scheme_utils::HandleMap; +use scheme_utils::{FpathWriter, HandleMap}; use std::{ cmp, collections::{hash_map::Entry, HashMap}, @@ -90,20 +90,10 @@ impl SchemeSync for ShmScheme { }) } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - // Write scheme name - const PREFIX: &[u8] = b"/scheme/shm/"; - let len = cmp::min(PREFIX.len(), buf.len()); - buf[..len].copy_from_slice(&PREFIX[..len]); - if len < PREFIX.len() { - return Ok(len); - } - - // Write path - 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) + FpathWriter::with(buf, "shm", |w| { + w.push_str(self.handles.get(id).and_then(Handle::as_shm)?); + Ok(()) + }) } fn on_close(&mut self, id: usize) { let Handle::Shm(path) = self.handles.remove(id).unwrap() else { diff --git a/ipcd/src/uds/dgram.rs b/ipcd/src/uds/dgram.rs index d68cbbc8ee..85c8d53b61 100644 --- a/ipcd/src/uds/dgram.rs +++ b/ipcd/src/uds/dgram.rs @@ -13,6 +13,7 @@ use redox_scheme::{ scheme::SchemeSync, CallerCtx, OpenResult, RecvFdRequest, Response, SendFdRequest, SignalBehavior, Socket as SchemeSocket, }; +use scheme_utils::FpathWriter; use std::{ cell::RefCell, cmp, @@ -566,19 +567,10 @@ impl<'sock> UdsDgramScheme<'sock> { } fn fpath_inner(path: &String, buf: &mut [u8]) -> Result { - // Write scheme name - const PREFIX: &[u8] = b"/scheme/uds_dgram/"; - let len = cmp::min(PREFIX.len(), buf.len()); - buf[..len].copy_from_slice(&PREFIX[..len]); - if len < PREFIX.len() { - return Ok(len); - } - - // Write path - 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) + FpathWriter::with(buf, "uds_dgram", |w| { + w.push_str(path); + Ok(()) + }) } fn read_inner(&mut self, id: usize, buf: &mut [u8], flags: u32) -> Result { diff --git a/ipcd/src/uds/stream.rs b/ipcd/src/uds/stream.rs index c258a1c0e4..81c846fda0 100644 --- a/ipcd/src/uds/stream.rs +++ b/ipcd/src/uds/stream.rs @@ -12,6 +12,7 @@ use redox_scheme::{ scheme::SchemeSync, CallerCtx, OpenResult, RecvFdRequest, Response, SendFdRequest, SignalBehavior, Socket as SchemeSocket, }; +use scheme_utils::FpathWriter; use std::{ cell::RefCell, cmp, @@ -1228,19 +1229,10 @@ impl<'sock> UdsStreamScheme<'sock> { } fn fpath_inner(path: &String, buf: &mut [u8]) -> Result { - // Write scheme name - const PREFIX: &[u8] = b"/scheme/uds_stream/"; - let len = cmp::min(PREFIX.len(), buf.len()); - buf[..len].copy_from_slice(&PREFIX[..len]); - if len < PREFIX.len() { - return Ok(len); - } - - // Write path - 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) + FpathWriter::with(buf, "uds_stream", |w| { + w.push_str(path); + Ok(()) + }) } } diff --git a/logd/src/scheme.rs b/logd/src/scheme.rs index fe7ae85420..070de3d678 100644 --- a/logd/src/scheme.rs +++ b/logd/src/scheme.rs @@ -7,7 +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 scheme_utils::{FpathWriter, HandleMap}; use syscall::error::*; use syscall::schemev2::NewFdFlags; @@ -229,29 +229,14 @@ impl<'sock> SchemeSync for LogScheme<'sock> { } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let handle = self.handles.get(id)?; - - let scheme_path = b"/scheme/log/"; - - let mut i = 0; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - - let path_bytes = match handle { - LogHandle::Log { context, .. } => context.as_bytes(), - LogHandle::AddSink => b"add_sink", - LogHandle::SchemeRoot => return Err(Error::new(EBADF)), - }; - let mut j = 0; - while i < buf.len() && j < path_bytes.len() { - buf[i] = path_bytes[j]; - i += 1; - j += 1; - } - - Ok(i) + FpathWriter::with(buf, "log", |w| { + w.push_str(match self.handles.get(id)? { + LogHandle::Log { context, .. } => context, + LogHandle::AddSink => "add_sink", + LogHandle::SchemeRoot => return Err(Error::new(EBADF)), + }); + Ok(()) + }) } fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { diff --git a/netstack/src/scheme/icmp.rs b/netstack/src/scheme/icmp.rs index 6365e2a7da..e326c67eb5 100644 --- a/netstack/src/scheme/icmp.rs +++ b/netstack/src/scheme/icmp.rs @@ -1,3 +1,4 @@ +use scheme_utils::FpathWriter; use smoltcp::iface::SocketHandle; use smoltcp::socket::icmp::{ Endpoint as IcmpEndpoint, PacketBuffer as IcmpSocketBuffer, @@ -249,36 +250,21 @@ impl<'a> SchemeSocket for IcmpSocket<'a> { } fn fpath(&self, file: &SchemeFile, buf: &mut [u8]) -> SyscallResult { - if let SchemeFile::Socket(ref socket_file) = *file { - match socket_file.data.socket_type { - IcmpSocketType::Echo => { - let path = format!("/scheme/icmp/echo/{}", socket_file.data.ip); - let path = path.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; + FpathWriter::with(buf, "icmp", |w| { + if let SchemeFile::Socket(ref socket_file) = *file { + match socket_file.data.socket_type { + IcmpSocketType::Echo => { + write!(w, "echo/{}", socket_file.data.ip).unwrap(); } - - Ok(i) - } - IcmpSocketType::Udp => { - let path = format!("/scheme/icmp/udp/{}", socket_file.data.ip); - let path = path.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; + IcmpSocketType::Udp => { + write!(w, "udp/{}", socket_file.data.ip).unwrap(); } - - Ok(i) } + Ok(()) + } else { + Err(SyscallError::new(syscall::EBADF)) } - } else { - Err(SyscallError::new(syscall::EBADF)) - } + }) } fn handle_recvmsg( diff --git a/netstack/src/scheme/ip.rs b/netstack/src/scheme/ip.rs index 70d2bf8e91..18d0dc6d9a 100644 --- a/netstack/src/scheme/ip.rs +++ b/netstack/src/scheme/ip.rs @@ -1,3 +1,4 @@ +use scheme_utils::FpathWriter; use smoltcp::iface::SocketHandle; use smoltcp::socket::raw::{ PacketBuffer as RawSocketBuffer, PacketMetadata as RawPacketMetadata, Socket as RawSocket, @@ -137,16 +138,10 @@ impl<'a> SchemeSocket for RawSocket<'a> { } fn fpath(&self, _file: &SchemeFile, buf: &mut [u8]) -> SyscallResult { - let path = format!("/scheme/ip/{}", self.ip_protocol()); - let path = path.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) + FpathWriter::with(buf, "ip", |w| { + write!(w, "{}", self.ip_protocol()).unwrap(); + Ok(()) + }) } fn handle_recvmsg( diff --git a/netstack/src/scheme/tcp.rs b/netstack/src/scheme/tcp.rs index b5257e5553..435553829d 100644 --- a/netstack/src/scheme/tcp.rs +++ b/netstack/src/scheme/tcp.rs @@ -1,7 +1,7 @@ +use scheme_utils::FpathWriter; use smoltcp::iface::SocketHandle; use smoltcp::socket::tcp::{Socket as TcpSocket, SocketBuffer as TcpSocketBuffer}; use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; -use std::fmt::Write; use std::str; use syscall; use syscall::{Error as SyscallError, Result as SyscallResult}; @@ -273,40 +273,33 @@ impl<'a> SchemeSocket for TcpSocket<'a> { } fn fpath(&self, file: &SchemeFile, buf: &mut [u8]) -> SyscallResult { - let unspecified = "0.0.0.0:0"; - let mut path = String::from("/scheme/tcp/"); - match self.remote_endpoint() { - Some(endpoint) => write!(&mut path, "{}", endpoint).unwrap(), - None => path.push_str(unspecified), - } - path.push('/'); - match (self.local_endpoint(), file) { - (Some(endpoint), _) => write!(&mut path, "{}", endpoint).unwrap(), - ( - None, - SchemeFile::Socket(SocketFile { - data: Some(endpoint), - .. - }), - ) => { - if endpoint.is_specified() { - write!(&mut path, "{}", endpoint).unwrap() - } else { - write!(&mut path, "0.0.0.0:{}", endpoint.port).unwrap() - } + FpathWriter::with(buf, "tcp", |w| { + let unspecified = "0.0.0.0:0"; + match self.remote_endpoint() { + Some(endpoint) => write!(w, "{}", endpoint).unwrap(), + None => w.push_str(unspecified), + } + w.push_str("/"); + match (self.local_endpoint(), file) { + (Some(endpoint), _) => write!(w, "{}", endpoint).unwrap(), + ( + None, + SchemeFile::Socket(SocketFile { + data: Some(endpoint), + .. + }), + ) => { + if endpoint.is_specified() { + write!(w, "{}", endpoint).unwrap() + } else { + write!(w, "0.0.0.0:{}", endpoint.port).unwrap() + } + } + _ => w.push_str(unspecified), } - _ => path.push_str(unspecified), - } - trace!("fpath: {}", path); - let path = path.as_bytes(); - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) + Ok(()) + }) } fn handle_recvmsg( diff --git a/netstack/src/scheme/udp.rs b/netstack/src/scheme/udp.rs index 35d396a925..f336d2544a 100644 --- a/netstack/src/scheme/udp.rs +++ b/netstack/src/scheme/udp.rs @@ -1,3 +1,4 @@ +use scheme_utils::FpathWriter; use smoltcp::iface::SocketHandle; use smoltcp::socket::udp::{ PacketBuffer as UdpSocketBuffer, PacketMetadata as UdpPacketMetadata, Socket as UdpSocket, @@ -12,7 +13,6 @@ use super::{parse_endpoint, SchemeWrapper, Smolnetd, SocketSet}; use crate::port_set::PortSet; use crate::router::Router; use libredox::flag; -use std::fmt::Write; const SO_SNDBUF: usize = 7; const SO_RCVBUF: usize = 8; @@ -269,37 +269,31 @@ impl<'a> SchemeSocket for UdpSocket<'a> { } fn fpath(&self, file: &SchemeFile, buf: &mut [u8]) -> SyscallResult { - let unspecified = "0.0.0.0:0"; - let mut path = String::from("/scheme/udp/"); + FpathWriter::with(buf, "udp", |w| { + let unspecified = "0.0.0.0:0"; - // remote - match file { - SchemeFile::Socket(SocketFile { data: endpoint, .. }) => { - if endpoint.is_specified() { - write!(&mut path, "{}", endpoint).unwrap() - } else { - write!(&mut path, "0.0.0.0:{}", endpoint.port).unwrap() + // remote + match file { + SchemeFile::Socket(SocketFile { data: endpoint, .. }) => { + if endpoint.is_specified() { + write!(w, "{}", endpoint).unwrap() + } else { + write!(w, "0.0.0.0:{}", endpoint.port).unwrap() + } } + _ => w.push_str(unspecified), + } + w.push_str("/"); + // local + let endpoint = self.endpoint(); + if endpoint.is_specified() { + write!(w, "{}", endpoint).unwrap() + } else { + write!(w, "0.0.0.0:{}", endpoint.port).unwrap() } - _ => path.push_str(unspecified), - } - path.push('/'); - // local - let endpoint = self.endpoint(); - if endpoint.is_specified() { - write!(&mut path, "{}", endpoint).unwrap() - } else { - write!(&mut path, "0.0.0.0:{}", endpoint.port).unwrap() - } - let path = path.as_bytes(); - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) + Ok(()) + }) } fn handle_recvmsg( diff --git a/ptyd/src/pty.rs b/ptyd/src/pty.rs index 82c050d316..bcc46ac35a 100644 --- a/ptyd/src/pty.rs +++ b/ptyd/src/pty.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; -use std::io::{Cursor, Write}; use redox_termios::*; +use scheme_utils::FpathWriter; use syscall::error::Result; pub struct Pty { @@ -32,9 +32,10 @@ impl Pty { } pub fn path(&self, buf: &mut [u8]) -> Result { - let mut buf = Cursor::new(buf); - let _ = write!(buf, "/scheme/pty/{}", self.id); - Ok(buf.position().try_into().unwrap_or(usize::MAX)) + FpathWriter::with(buf, "pty", |w| { + write!(w, "{}", self.id).unwrap(); + Ok(()) + }) } pub fn input(&mut self, buf: &[u8]) { diff --git a/ramfs/src/scheme.rs b/ramfs/src/scheme.rs index 2b4998760f..421d814126 100644 --- a/ramfs/src/scheme.rs +++ b/ramfs/src/scheme.rs @@ -1,10 +1,8 @@ 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 scheme_utils::{FpathWriter, HandleMap}; use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; use syscall::error::{ EACCES, EBADF, EBADFD, EEXIST, EINVAL, EIO, EISDIR, ENOMEM, ENOSYS, ENOTDIR, ENOTEMPTY, @@ -461,49 +459,49 @@ 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)? { - Handle::Inode(inode) => inode, - Handle::SchemeRoot => return Err(Error::new(EISDIR)), - }; + FpathWriter::with(buf, &self.scheme_name, |w| { + let mut current_inode = match *self.handles.get(fd)? { + Handle::Inode(inode) => inode, + Handle::SchemeRoot => return Err(Error::new(EISDIR)), + }; - let mut chain = Vec::new(); + let mut chain = Vec::new(); - let mut current_info = self - .filesystem - .files - .get(¤t_inode) - .ok_or(Error::new(EBADFD))?; - - while current_inode != Filesystem::ROOT_INODE { - let parent_info = self + let mut current_info = self .filesystem .files - .get(¤t_info.parent.0) + .get(¤t_inode) .ok_or(Error::new(EBADFD))?; - let FileData::Directory(ref dir) = parent_info.data else { - return Err(Error::new(EBADFD)); - }; - // TODO: error handling? - let (name, _) = dir - .iter() - .find(|(_name, inode)| inode.0 == current_inode) - .ok_or(Error::new(ENOENT))?; - chain.push(&**name); + while current_inode != Filesystem::ROOT_INODE { + let parent_info = self + .filesystem + .files + .get(¤t_info.parent.0) + .ok_or(Error::new(EBADFD))?; - current_inode = current_info.parent.0; - current_info = parent_info; - } + let FileData::Directory(ref dir) = parent_info.data else { + return Err(Error::new(EBADFD)); + }; + // TODO: error handling? + let (name, _) = dir + .iter() + .find(|(_name, inode)| inode.0 == current_inode) + .ok_or(Error::new(ENOENT))?; + chain.push(&**name); - let mut cursor = Cursor::new(buf); - for component in - iter::once(self.scheme_name.trim_start_matches('/')).chain(chain.iter().copied().rev()) - { - use std::io::Write; + current_inode = current_info.parent.0; + current_info = parent_info; + } - write!(cursor, "/{component}").unwrap(); - } - Ok(cursor.stream_position().unwrap() as usize) + for (i, component) in chain.iter().copied().rev().enumerate() { + if i != 0 { + w.push_str("/"); + } + w.push_str(component); + } + Ok(()) + }) } fn frename(&mut self, _inode: usize, _path: &str, _ctx: &CallerCtx) -> Result { // TODO diff --git a/randd/src/main.rs b/randd/src/main.rs index 6e249dc986..d68dd732d1 100644 --- a/randd/src/main.rs +++ b/randd/src/main.rs @@ -12,7 +12,7 @@ pub const MODE_READ: u16 = 0o4; use raw_cpuid::CpuId; use redox_scheme::{scheme::SchemeSync, CallerCtx, OpenResult, Socket}; -use scheme_utils::{Blocking, HandleMap}; +use scheme_utils::{Blocking, FpathWriter, HandleMap}; use syscall::data::Stat; use syscall::flag::{EventFlags, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_WRONLY}; use syscall::schemev2::NewFdFlags; @@ -431,13 +431,7 @@ impl SchemeSync for RandScheme { Ok(EventFlags::EVENT_READ) } fn fpath(&mut self, _file: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let mut i = 0; - let scheme_path = b"rand"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - Ok(i) + FpathWriter::with(buf, "rand", |_| Ok(())) } fn fstat(&mut self, file: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { diff --git a/scheme-utils/src/lib.rs b/scheme-utils/src/lib.rs index c81555a2ed..b262939c6b 100644 --- a/scheme-utils/src/lib.rs +++ b/scheme-utils/src/lib.rs @@ -1,6 +1,7 @@ #![feature(never_type)] use std::collections::{BTreeMap, btree_map}; +use std::fmt; use std::num::Wrapping; use syscall::{EBADF, Error, Result}; @@ -73,3 +74,49 @@ impl HandleMap { self.handles.values_mut() } } + +pub struct FpathWriter<'a> { + buf: &'a mut [u8], + written: usize, +} + +impl<'a> FpathWriter<'a> { + pub fn with( + buf: &'a mut [u8], + scheme_name: &str, + f: impl FnOnce(&mut Self) -> Result<()>, + ) -> Result { + let mut w = FpathWriter { buf, written: 0 }; + write!(w, "/scheme/{scheme_name}/").unwrap(); + f(&mut w)?; + Ok(w.written) + } + + pub fn with_legacy( + buf: &'a mut [u8], + scheme_name: &str, + f: impl FnOnce(&mut Self) -> Result<()>, + ) -> Result { + let mut w = FpathWriter { buf, written: 0 }; + write!(w, "{scheme_name}:").unwrap(); + f(&mut w)?; + Ok(w.written) + } + + pub fn push_str(&mut self, s: &str) { + let count = core::cmp::min(s.len(), self.buf.len() - self.written); + self.buf[self.written..self.written + count].copy_from_slice(&s.as_bytes()[..count]); + self.written += count; + } + + pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { + std::fmt::write(self, args) + } +} + +impl fmt::Write for FpathWriter<'_> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.push_str(s); + Ok(()) + } +} diff --git a/zerod/src/scheme.rs b/zerod/src/scheme.rs index a180d6377f..3e988461e1 100644 --- a/zerod/src/scheme.rs +++ b/zerod/src/scheme.rs @@ -1,5 +1,6 @@ use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult}; +use scheme_utils::FpathWriter; use syscall::{error::*, schemev2::NewFdFlags, MODE_CHR}; use crate::Ty; @@ -67,12 +68,7 @@ impl SchemeSync for ZeroScheme { } fn fpath(&mut self, _id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let scheme_path = b"zero:"; - let size = std::cmp::min(buf.len(), scheme_path.len()); - - buf[..size].copy_from_slice(&scheme_path[..size]); - - Ok(size) + FpathWriter::with(buf, "zero", |_| Ok(())) } fn fsync(&mut self, _id: usize, _ctx: &CallerCtx) -> Result<()> {