Improved scheme protocol.
This commit is contained in:
committed by
Jeremy Soller
parent
e9ba024aaa
commit
bf0fc66ac1
+20
-55
@@ -9,9 +9,7 @@ use alloc::{boxed::Box, collections::BTreeMap};
|
||||
use spin::{Mutex, Once, RwLock};
|
||||
|
||||
use crate::{
|
||||
acpi::{RxsdtEnum, RXSDT_ENUM},
|
||||
event,
|
||||
sync::WaitCondition,
|
||||
acpi::{RxsdtEnum, RXSDT_ENUM}, context::file::InternalFlags, event, sync::WaitCondition
|
||||
};
|
||||
|
||||
use crate::syscall::{
|
||||
@@ -30,7 +28,6 @@ use super::{CallerCtx, GlobalSchemes, KernelScheme, OpenResult};
|
||||
pub struct AcpiScheme;
|
||||
|
||||
struct Handle {
|
||||
offset: usize,
|
||||
kind: HandleKind,
|
||||
stat: bool,
|
||||
}
|
||||
@@ -121,25 +118,25 @@ impl KernelScheme for AcpiScheme {
|
||||
if flags & O_ACCMODE != O_RDONLY && flags & O_STAT != O_STAT {
|
||||
return Err(Error::new(EROFS));
|
||||
}
|
||||
let handle_kind = match path {
|
||||
let (handle_kind, int_flags) = match path {
|
||||
"" => {
|
||||
if flags & O_DIRECTORY != O_DIRECTORY && flags & O_STAT != O_STAT {
|
||||
return Err(Error::new(EISDIR));
|
||||
}
|
||||
|
||||
HandleKind::TopLevel
|
||||
(HandleKind::TopLevel, InternalFlags::POSITIONED)
|
||||
}
|
||||
"rxsdt" => {
|
||||
if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT {
|
||||
return Err(Error::new(ENOTDIR));
|
||||
}
|
||||
HandleKind::Rxsdt
|
||||
(HandleKind::Rxsdt, InternalFlags::POSITIONED)
|
||||
}
|
||||
"kstop" => {
|
||||
if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT {
|
||||
return Err(Error::new(ENOTDIR));
|
||||
}
|
||||
HandleKind::ShutdownPipe
|
||||
(HandleKind::ShutdownPipe, InternalFlags::empty())
|
||||
}
|
||||
_ => return Err(Error::new(ENOENT)),
|
||||
};
|
||||
@@ -150,15 +147,15 @@ impl KernelScheme for AcpiScheme {
|
||||
let _ = handles_guard.insert(
|
||||
fd,
|
||||
Handle {
|
||||
offset: 0,
|
||||
kind: handle_kind,
|
||||
// TODO: Redundant
|
||||
stat: flags & O_STAT == O_STAT,
|
||||
},
|
||||
);
|
||||
|
||||
Ok(OpenResult::SchemeLocal(fd))
|
||||
Ok(OpenResult::SchemeLocal(fd, int_flags))
|
||||
}
|
||||
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<usize> {
|
||||
fn fsize(&self, id: usize) -> Result<u64> {
|
||||
let mut handles = HANDLES.write();
|
||||
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
@@ -166,39 +163,11 @@ impl KernelScheme for AcpiScheme {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
|
||||
let file_len = match handle.kind {
|
||||
HandleKind::Rxsdt => DATA.get().ok_or(Error::new(EBADFD))?.len(),
|
||||
Ok(match handle.kind {
|
||||
HandleKind::Rxsdt => DATA.get().ok_or(Error::new(EBADFD))?.len() as u64,
|
||||
HandleKind::ShutdownPipe => 1,
|
||||
HandleKind::TopLevel => TOPLEVEL_CONTENTS.len(),
|
||||
};
|
||||
|
||||
let new_offset = match whence {
|
||||
SEEK_SET => pos as usize,
|
||||
SEEK_CUR => {
|
||||
if pos < 0 {
|
||||
handle
|
||||
.offset
|
||||
.checked_sub((-pos) as usize)
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
} else {
|
||||
handle.offset.saturating_add(pos as usize)
|
||||
}
|
||||
}
|
||||
SEEK_END => {
|
||||
if pos < 0 {
|
||||
file_len
|
||||
.checked_sub((-pos) as usize)
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
} else {
|
||||
file_len
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
};
|
||||
|
||||
handle.offset = new_offset;
|
||||
|
||||
Ok(new_offset)
|
||||
HandleKind::TopLevel => TOPLEVEL_CONTENTS.len() as u64,
|
||||
})
|
||||
}
|
||||
// TODO
|
||||
fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
|
||||
@@ -217,10 +186,11 @@ impl KernelScheme for AcpiScheme {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn kwrite(&self, _id: usize, _buf: UserSliceRo) -> Result<usize> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
fn kread(&self, id: usize, dst_buf: UserSliceWo) -> Result<usize> {
|
||||
fn kreadoff(&self, id: usize, dst_buf: UserSliceWo, offset: u64, flags: u32, stored_flags: u32) -> Result<usize> {
|
||||
let Ok(offset) = usize::try_from(offset) else {
|
||||
return Ok(0);
|
||||
};
|
||||
|
||||
let mut handles = HANDLES.write();
|
||||
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
@@ -244,23 +214,18 @@ impl KernelScheme for AcpiScheme {
|
||||
}
|
||||
}
|
||||
|
||||
dst_buf.copy_exactly(&[0x42])?;
|
||||
handle.offset = 1;
|
||||
return Ok(1);
|
||||
return dst_buf.copy_exactly(&[0x42]).map(|()| 1);
|
||||
}
|
||||
HandleKind::Rxsdt => DATA.get().ok_or(Error::new(EBADFD))?,
|
||||
HandleKind::TopLevel => TOPLEVEL_CONTENTS,
|
||||
};
|
||||
|
||||
let src_offset = core::cmp::min(handle.offset, data.len());
|
||||
let src_offset = core::cmp::min(offset, data.len());
|
||||
let src_buf = data
|
||||
.get(src_offset..)
|
||||
.expect("expected data to be at least data.len() bytes long");
|
||||
|
||||
let bytes_copied = dst_buf.copy_common_bytes_from_slice(src_buf)?;
|
||||
handle.offset += bytes_copied;
|
||||
|
||||
Ok(bytes_copied)
|
||||
dst_buf.copy_common_bytes_from_slice(src_buf)
|
||||
}
|
||||
fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> {
|
||||
let handles = HANDLES.read();
|
||||
|
||||
+5
-23
@@ -19,7 +19,6 @@ static INPUT: WaitQueue<u8> = WaitQueue::new();
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Handle {
|
||||
flags: usize,
|
||||
num: usize,
|
||||
}
|
||||
|
||||
@@ -41,7 +40,7 @@ pub fn debug_notify() {
|
||||
pub struct DebugScheme;
|
||||
|
||||
impl KernelScheme for DebugScheme {
|
||||
fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result<OpenResult> {
|
||||
fn kopen(&self, path: &str, _flags: usize, ctx: CallerCtx) -> Result<OpenResult> {
|
||||
if ctx.uid != 0 {
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
@@ -61,28 +60,11 @@ impl KernelScheme for DebugScheme {
|
||||
HANDLES.write().insert(
|
||||
id,
|
||||
Handle {
|
||||
flags: flags & !O_ACCMODE,
|
||||
num,
|
||||
},
|
||||
);
|
||||
|
||||
Ok(OpenResult::SchemeLocal(id))
|
||||
}
|
||||
|
||||
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let mut handles = HANDLES.write();
|
||||
if let Some(handle) = handles.get_mut(&id) {
|
||||
match cmd {
|
||||
F_GETFL => Ok(handle.flags),
|
||||
F_SETFL => {
|
||||
handle.flags = arg & !O_ACCMODE;
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(Error::new(EINVAL)),
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
|
||||
}
|
||||
|
||||
fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
|
||||
@@ -112,7 +94,7 @@ impl KernelScheme for DebugScheme {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
fn kread(&self, id: usize, buf: UserSliceWo, flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let handle = {
|
||||
let handles = HANDLES.read();
|
||||
*handles.get(&id).ok_or(Error::new(EBADF))?
|
||||
@@ -128,12 +110,12 @@ impl KernelScheme for DebugScheme {
|
||||
|
||||
INPUT.receive_into_user(
|
||||
buf,
|
||||
handle.flags & O_NONBLOCK != O_NONBLOCK,
|
||||
flags & O_NONBLOCK as u32 == 0,
|
||||
"DebugScheme::read",
|
||||
)
|
||||
}
|
||||
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo) -> Result<usize> {
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo, _flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let handle = {
|
||||
let handles = HANDLES.read();
|
||||
*handles.get(&id).ok_or(Error::new(EBADF))?
|
||||
|
||||
+7
-21
@@ -1,13 +1,13 @@
|
||||
use alloc::sync::Arc;
|
||||
use syscall::O_NONBLOCK;
|
||||
use core::mem;
|
||||
|
||||
use crate::{
|
||||
event::{next_queue_id, queues, queues_mut, EventQueue, EventQueueId},
|
||||
syscall::{
|
||||
context::file::InternalFlags, event::{next_queue_id, queues, queues_mut, EventQueue, EventQueueId}, syscall::{
|
||||
data::Event,
|
||||
error::*,
|
||||
usercopy::{UserSliceRo, UserSliceWo},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
use super::{CallerCtx, KernelScheme, OpenResult};
|
||||
@@ -19,21 +19,7 @@ impl KernelScheme for EventScheme {
|
||||
let id = next_queue_id();
|
||||
queues_mut().insert(id, Arc::new(EventQueue::new(id)));
|
||||
|
||||
Ok(OpenResult::SchemeLocal(id.get()))
|
||||
}
|
||||
|
||||
fn fcntl(&self, id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
|
||||
let id = EventQueueId::from(id);
|
||||
|
||||
let handles = queues();
|
||||
handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(0))
|
||||
}
|
||||
|
||||
fn fsync(&self, id: usize) -> Result<()> {
|
||||
let id = EventQueueId::from(id);
|
||||
|
||||
let handles = queues();
|
||||
handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(()))
|
||||
Ok(OpenResult::SchemeLocal(id.get(), InternalFlags::empty()))
|
||||
}
|
||||
|
||||
fn close(&self, id: usize) -> Result<()> {
|
||||
@@ -43,7 +29,7 @@ impl KernelScheme for EventScheme {
|
||||
.ok_or(Error::new(EBADF))
|
||||
.and(Ok(()))
|
||||
}
|
||||
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
fn kread(&self, id: usize, buf: UserSliceWo, flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let id = EventQueueId::from(id);
|
||||
|
||||
let queue = {
|
||||
@@ -52,10 +38,10 @@ impl KernelScheme for EventScheme {
|
||||
handle.clone()
|
||||
};
|
||||
|
||||
queue.read(buf)
|
||||
queue.read(buf, flags & O_NONBLOCK as u32 == 0)
|
||||
}
|
||||
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo) -> Result<usize> {
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo, flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let id = EventQueueId::from(id);
|
||||
|
||||
let queue = {
|
||||
|
||||
+52
-60
@@ -1,3 +1,6 @@
|
||||
// TODO: Rewrite this entire scheme. Legacy x86 APIs should be abstracted by a userspace scheme,
|
||||
// this scheme should only handle raw IRQ registration and delivery to userspace.
|
||||
|
||||
use core::{
|
||||
mem, str,
|
||||
str::FromStr,
|
||||
@@ -8,7 +11,7 @@ use alloc::{collections::BTreeMap, string::String, vec::Vec};
|
||||
|
||||
use spin::{Mutex, Once, RwLock};
|
||||
|
||||
use crate::arch::interrupt::{available_irqs_iter, bsp_apic_id, is_reserved, set_reserved};
|
||||
use crate::{arch::interrupt::{available_irqs_iter, bsp_apic_id, is_reserved, set_reserved}, context::file::InternalFlags};
|
||||
|
||||
use crate::{
|
||||
cpu_set::LogicalCpuId,
|
||||
@@ -22,7 +25,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use super::{calc_seek_offset, CallerCtx, GlobalSchemes, OpenResult};
|
||||
use super::{CallerCtx, GlobalSchemes, OpenResult};
|
||||
|
||||
/// IRQ queues
|
||||
pub(super) static COUNTS: Mutex<[usize; 224]> = Mutex::new([0; 224]);
|
||||
@@ -62,8 +65,8 @@ pub extern "C" fn irq_trigger(irq: u8) {
|
||||
|
||||
enum Handle {
|
||||
Irq { ack: AtomicUsize, irq: u8 },
|
||||
Avail(u8, Vec<u8>, AtomicUsize), // CPU id, data, offset
|
||||
TopLevel(Vec<u8>, AtomicUsize), // data, offset
|
||||
Avail(u8, Vec<u8>), // CPU id, data, offset
|
||||
TopLevel(Vec<u8>), // data, offset
|
||||
Bsp,
|
||||
}
|
||||
impl Handle {
|
||||
@@ -105,7 +108,7 @@ impl IrqScheme {
|
||||
|
||||
CPUS.call_once(|| cpus);
|
||||
}
|
||||
fn open_ext_irq(flags: usize, cpu_id: u8, path_str: &str) -> Result<Handle> {
|
||||
fn open_ext_irq(flags: usize, cpu_id: u8, path_str: &str) -> Result<(Handle, InternalFlags)> {
|
||||
let irq_number = u8::from_str(path_str).or(Err(Error::new(ENOENT)))?;
|
||||
|
||||
Ok(
|
||||
@@ -114,10 +117,10 @@ impl IrqScheme {
|
||||
//
|
||||
// The only CPUs don't have the legacy IRQs in their IDTs.
|
||||
|
||||
Handle::Irq {
|
||||
(Handle::Irq {
|
||||
ack: AtomicUsize::new(0),
|
||||
irq: irq_number,
|
||||
}
|
||||
}, InternalFlags::empty())
|
||||
} else if irq_number < TOTAL_IRQ_COUNT {
|
||||
if flags & O_CREAT == 0 && flags & O_STAT == 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
@@ -132,10 +135,10 @@ impl IrqScheme {
|
||||
true,
|
||||
);
|
||||
}
|
||||
Handle::Irq {
|
||||
(Handle::Irq {
|
||||
ack: AtomicUsize::new(0),
|
||||
irq: irq_number,
|
||||
}
|
||||
}, InternalFlags::empty())
|
||||
} else {
|
||||
return Err(Error::new(ENOENT));
|
||||
},
|
||||
@@ -158,7 +161,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
|
||||
let path_str = path.trim_start_matches('/');
|
||||
|
||||
let handle: Handle = if path_str.is_empty() {
|
||||
let (handle, int_flags) = if path_str.is_empty() {
|
||||
if flags & O_DIRECTORY == 0 && flags & O_STAT == 0 {
|
||||
return Err(Error::new(EISDIR));
|
||||
}
|
||||
@@ -180,13 +183,13 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
// TODO: When signals are used for IRQs, there will probably also be a file
|
||||
// `irq:signal` that maps IRQ numbers and their source APIC IDs to signal numbers.
|
||||
|
||||
Handle::TopLevel(bytes.into_bytes(), AtomicUsize::new(0))
|
||||
(Handle::TopLevel(bytes.into_bytes()), InternalFlags::POSITIONED)
|
||||
} else {
|
||||
if path_str == "bsp" {
|
||||
if bsp_apic_id().is_none() {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
Handle::Bsp
|
||||
(Handle::Bsp, InternalFlags::empty())
|
||||
} else if path_str.starts_with("cpu-") {
|
||||
let path_str = &path_str[4..];
|
||||
let cpu_id = u8::from_str_radix(&path_str[..2], 16).or(Err(Error::new(ENOENT)))?;
|
||||
@@ -204,7 +207,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
writeln!(data, "{}", irq).unwrap();
|
||||
}
|
||||
|
||||
Handle::Avail(cpu_id, data.into_bytes(), AtomicUsize::new(0))
|
||||
(Handle::Avail(cpu_id, data.into_bytes()), InternalFlags::POSITIONED)
|
||||
} else if path_str.starts_with('/') {
|
||||
let path_str = &path_str[1..];
|
||||
Self::open_ext_irq(flags, cpu_id, path_str)?
|
||||
@@ -213,10 +216,10 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
}
|
||||
} else if let Ok(plain_irq_number) = u8::from_str(path_str) {
|
||||
if plain_irq_number < BASE_IRQ_COUNT {
|
||||
Handle::Irq {
|
||||
(Handle::Irq {
|
||||
ack: AtomicUsize::new(0),
|
||||
irq: plain_irq_number,
|
||||
}
|
||||
}, InternalFlags::empty())
|
||||
} else {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
@@ -226,20 +229,15 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
};
|
||||
let fd = NEXT_FD.fetch_add(1, Ordering::Relaxed);
|
||||
HANDLES.write().insert(fd, handle);
|
||||
Ok(OpenResult::SchemeLocal(fd))
|
||||
Ok(OpenResult::SchemeLocal(fd, int_flags))
|
||||
}
|
||||
|
||||
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<usize> {
|
||||
fn fsize(&self, id: usize) -> Result<u64> {
|
||||
let handles_guard = HANDLES.read();
|
||||
let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
match handle {
|
||||
&Handle::Avail(_, ref buf, ref offset) | &Handle::TopLevel(ref buf, ref offset) => {
|
||||
let cur_offset = offset.load(Ordering::SeqCst);
|
||||
let new_offset = calc_seek_offset(cur_offset, pos, whence, buf.len())?;
|
||||
offset.store(new_offset as usize, Ordering::SeqCst);
|
||||
Ok(new_offset as usize)
|
||||
}
|
||||
match *handle {
|
||||
Handle::Avail(_, ref buf) | Handle::TopLevel(ref buf) => Ok(buf.len() as u64),
|
||||
_ => Err(Error::new(ESPIPE)),
|
||||
}
|
||||
}
|
||||
@@ -270,7 +268,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn kwrite(&self, file: usize, buffer: UserSliceRo) -> Result<usize> {
|
||||
fn kwrite(&self, file: usize, buffer: UserSliceRo, _flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let handles_guard = HANDLES.read();
|
||||
let handle = handles_guard.get(&file).ok_or(Error::new(EBADF))?;
|
||||
|
||||
@@ -279,22 +277,20 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
irq: handle_irq,
|
||||
ack: ref handle_ack,
|
||||
} => {
|
||||
if buffer.len() >= mem::size_of::<usize>() {
|
||||
let ack = buffer.read_usize()?;
|
||||
let current = COUNTS.lock()[handle_irq as usize];
|
||||
|
||||
if ack == current {
|
||||
handle_ack.store(ack, Ordering::SeqCst);
|
||||
unsafe {
|
||||
acknowledge(handle_irq as usize);
|
||||
}
|
||||
Ok(mem::size_of::<usize>())
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
if buffer.len() < mem::size_of::<usize>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let ack = buffer.read_usize()?;
|
||||
let current = COUNTS.lock()[handle_irq as usize];
|
||||
|
||||
if ack != current {
|
||||
return Ok(0);
|
||||
}
|
||||
handle_ack.store(ack, Ordering::SeqCst);
|
||||
unsafe {
|
||||
acknowledge(handle_irq as usize);
|
||||
}
|
||||
Ok(mem::size_of::<usize>())
|
||||
}
|
||||
_ => Err(Error::new(EBADF)),
|
||||
}
|
||||
@@ -325,14 +321,14 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
st_nlink: 1,
|
||||
..Default::default()
|
||||
},
|
||||
Handle::Avail(cpu_id, ref buf, _) => Stat {
|
||||
Handle::Avail(cpu_id, ref buf) => Stat {
|
||||
st_mode: MODE_DIR | 0o700,
|
||||
st_size: buf.len() as u64,
|
||||
st_ino: INO_AVAIL | u64::from(cpu_id) << 32,
|
||||
st_nlink: 2,
|
||||
..Default::default()
|
||||
},
|
||||
Handle::TopLevel(ref buf, _) => Stat {
|
||||
Handle::TopLevel(ref buf) => Stat {
|
||||
st_mode: MODE_DIR | 0o500,
|
||||
st_size: buf.len() as u64,
|
||||
st_ino: INO_TOPLEVEL,
|
||||
@@ -350,14 +346,14 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
let scheme_path = match handle {
|
||||
Handle::Irq { irq, .. } => format!("irq:{}", irq),
|
||||
Handle::Bsp => format!("irq:bsp"),
|
||||
Handle::Avail(cpu_id, _, _) => format!("irq:cpu-{:2x}", cpu_id),
|
||||
Handle::TopLevel(_, _) => format!("irq:"),
|
||||
Handle::Avail(cpu_id, _) => format!("irq:cpu-{:2x}", cpu_id),
|
||||
Handle::TopLevel(_) => format!("irq:"),
|
||||
}
|
||||
.into_bytes();
|
||||
|
||||
buf.copy_common_bytes_from_slice(&scheme_path)
|
||||
}
|
||||
fn kread(&self, file: usize, buffer: UserSliceWo) -> Result<usize> {
|
||||
fn kreadoff(&self, file: usize, buffer: UserSliceWo, offset: u64, flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let handles_guard = HANDLES.read();
|
||||
let handle = handles_guard.get(&file).ok_or(Error::new(EBADF))?;
|
||||
|
||||
@@ -367,16 +363,15 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
irq: handle_irq,
|
||||
ack: ref handle_ack,
|
||||
} => {
|
||||
if buffer.len() >= mem::size_of::<usize>() {
|
||||
let current = COUNTS.lock()[handle_irq as usize];
|
||||
if handle_ack.load(Ordering::SeqCst) != current {
|
||||
buffer.write_usize(current)?;
|
||||
Ok(mem::size_of::<usize>())
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
if buffer.len() < mem::size_of::<usize>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let current = COUNTS.lock()[handle_irq as usize];
|
||||
if handle_ack.load(Ordering::SeqCst) != current {
|
||||
buffer.write_usize(current)?;
|
||||
Ok(mem::size_of::<usize>())
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
Handle::Bsp => {
|
||||
@@ -390,12 +385,9 @@ impl crate::scheme::KernelScheme for IrqScheme {
|
||||
Err(Error::new(EBADFD))
|
||||
}
|
||||
}
|
||||
Handle::Avail(_, ref buf, ref offset) | Handle::TopLevel(ref buf, ref offset) => {
|
||||
let cur_offset = offset.load(Ordering::SeqCst);
|
||||
let avail_buf = buf.get(cur_offset..).unwrap_or(&[]);
|
||||
let bytes_read = buffer.copy_common_bytes_from_slice(avail_buf)?;
|
||||
offset.fetch_add(bytes_read, Ordering::SeqCst);
|
||||
Ok(bytes_read)
|
||||
Handle::Avail(_, ref buf) | Handle::TopLevel(ref buf) => {
|
||||
let src = usize::try_from(offset).ok().and_then(|o| buf.get(o..)).unwrap_or(&[]);
|
||||
buffer.copy_common_bytes_from_slice(src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ use core::{
|
||||
};
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::syscall::{
|
||||
use crate::{context::file::InternalFlags, syscall::{
|
||||
data::ITimerSpec,
|
||||
error::*,
|
||||
flag::{EventFlags, CLOCK_MONOTONIC, CLOCK_REALTIME},
|
||||
usercopy::{UserSliceRo, UserSliceWo},
|
||||
};
|
||||
}};
|
||||
|
||||
use super::{CallerCtx, KernelScheme, OpenResult};
|
||||
pub struct ITimerScheme;
|
||||
@@ -32,7 +32,7 @@ impl KernelScheme for ITimerScheme {
|
||||
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
HANDLES.write().insert(id, clock);
|
||||
|
||||
Ok(OpenResult::SchemeLocal(id))
|
||||
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
|
||||
}
|
||||
|
||||
fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
|
||||
@@ -58,7 +58,7 @@ impl KernelScheme for ITimerScheme {
|
||||
.ok_or(Error::new(EBADF))
|
||||
.and(Ok(()))
|
||||
}
|
||||
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
fn kread(&self, id: usize, buf: UserSliceWo, _flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let _clock = {
|
||||
let handles = HANDLES.read();
|
||||
*handles.get(&id).ok_or(Error::new(EBADF))?
|
||||
@@ -75,7 +75,7 @@ impl KernelScheme for ITimerScheme {
|
||||
Ok(specs_read * mem::size_of::<ITimerSpec>())
|
||||
}
|
||||
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo) -> Result<usize> {
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo, _flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let _clock = {
|
||||
let handles = HANDLES.read();
|
||||
*handles.get(&id).ok_or(Error::new(EBADF))?
|
||||
|
||||
@@ -4,7 +4,7 @@ use alloc::{sync::Arc, vec::Vec};
|
||||
use rmm::PhysicalAddress;
|
||||
|
||||
use crate::{
|
||||
context::memory::{handle_notify_files, AddrSpace, Grant, PageSpan, AddrSpaceWrapper},
|
||||
context::{file::InternalFlags, memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan}},
|
||||
memory::{free_frames, used_frames, Frame, PAGE_SIZE},
|
||||
paging::VirtualAddress,
|
||||
};
|
||||
@@ -223,16 +223,10 @@ impl KernelScheme for MemoryScheme {
|
||||
|
||||
Ok(OpenResult::SchemeLocal(
|
||||
(handle_ty as usize) | ((mem_ty as usize) << 8) | (usize::from(flags.bits()) << 16),
|
||||
InternalFlags::empty(),
|
||||
))
|
||||
}
|
||||
|
||||
fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn close(&self, _id: usize) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn kfmap(
|
||||
&self,
|
||||
id: usize,
|
||||
|
||||
+24
-26
@@ -13,7 +13,7 @@ use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use syscall::{EventFlags, MunmapFlags, SendFdFlags, SEEK_CUR, SEEK_END, SEEK_SET};
|
||||
|
||||
use crate::{
|
||||
context::{file::FileDescription, memory::AddrSpaceWrapper},
|
||||
context::{file::{FileDescription, InternalFlags}, memory::AddrSpaceWrapper},
|
||||
syscall::{
|
||||
error::*,
|
||||
usercopy::{UserSliceRo, UserSliceWo},
|
||||
@@ -394,10 +394,22 @@ pub trait KernelScheme: Send + Sync + 'static {
|
||||
fn kdup(&self, old_id: usize, buf: UserSliceRo, _caller: CallerCtx) -> Result<OpenResult> {
|
||||
Err(Error::new(EOPNOTSUPP))
|
||||
}
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo) -> Result<usize> {
|
||||
fn kwriteoff(&self, id: usize, buf: UserSliceRo, offset: u64, flags: u32, stored_flags: u32) -> Result<usize> {
|
||||
if offset != u64::MAX {
|
||||
return Err(Error::new(ESPIPE));
|
||||
}
|
||||
self.kwrite(id, buf, flags, stored_flags)
|
||||
}
|
||||
fn kreadoff(&self, id: usize, buf: UserSliceWo, offset: u64, flags: u32, stored_flags: u32) -> Result<usize> {
|
||||
if offset != u64::MAX {
|
||||
return Err(Error::new(ESPIPE));
|
||||
}
|
||||
self.kread(id, buf, flags, stored_flags)
|
||||
}
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo, flags: u32, stored_flags: u32) -> Result<usize> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
fn kread(&self, id: usize, buf: UserSliceWo, flags: u32, stored_flags: u32) -> Result<usize> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
fn kfpath(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
@@ -424,14 +436,17 @@ pub trait KernelScheme: Send + Sync + 'static {
|
||||
}
|
||||
|
||||
fn fsync(&self, id: usize) -> Result<()> {
|
||||
Err(Error::new(EBADF))
|
||||
Ok(())
|
||||
}
|
||||
fn ftruncate(&self, id: usize, len: usize) -> Result<()> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<usize> {
|
||||
fn fsize(&self, id: usize) -> Result<u64> {
|
||||
Err(Error::new(ESPIPE))
|
||||
}
|
||||
fn legacy_seek(&self, id: usize, pos: isize, whence: usize) -> Option<Result<usize>> {
|
||||
None
|
||||
}
|
||||
fn fchmod(&self, id: usize, new_mode: u16) -> Result<()> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
@@ -439,13 +454,13 @@ pub trait KernelScheme: Send + Sync + 'static {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
fn fevent(&self, id: usize, flags: EventFlags) -> Result<EventFlags> {
|
||||
Err(Error::new(EBADF))
|
||||
Ok(EventFlags::empty())
|
||||
}
|
||||
fn frename(&self, id: usize, new_path: &str, caller_ctx: CallerCtx) -> Result<()> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
Err(Error::new(EBADF))
|
||||
Ok(0)
|
||||
}
|
||||
fn rmdir(&self, path: &str, ctx: CallerCtx) -> Result<()> {
|
||||
Err(Error::new(ENOENT))
|
||||
@@ -454,13 +469,13 @@ pub trait KernelScheme: Send + Sync + 'static {
|
||||
Err(Error::new(ENOENT))
|
||||
}
|
||||
fn close(&self, id: usize) -> Result<()> {
|
||||
Err(Error::new(EBADF))
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OpenResult {
|
||||
SchemeLocal(usize),
|
||||
SchemeLocal(usize, InternalFlags),
|
||||
External(Arc<RwLock<FileDescription>>),
|
||||
}
|
||||
pub struct CallerCtx {
|
||||
@@ -469,23 +484,6 @@ pub struct CallerCtx {
|
||||
pub gid: u32,
|
||||
}
|
||||
|
||||
pub fn calc_seek_offset(
|
||||
cur_pos: usize,
|
||||
rel_pos: isize,
|
||||
whence: usize,
|
||||
len: usize,
|
||||
) -> Result<usize> {
|
||||
match whence {
|
||||
SEEK_SET => usize::try_from(rel_pos).map_err(|_| Error::new(EINVAL)),
|
||||
SEEK_CUR => cur_pos
|
||||
.checked_add_signed(rel_pos)
|
||||
.ok_or(Error::new(EOVERFLOW)),
|
||||
SEEK_END => len.checked_add_signed(rel_pos).ok_or(Error::new(EOVERFLOW)),
|
||||
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum KernelSchemes {
|
||||
Root(Arc<RootScheme>),
|
||||
|
||||
+11
-44
@@ -8,16 +8,14 @@ use alloc::{
|
||||
use spin::{Mutex, RwLock};
|
||||
|
||||
use crate::{
|
||||
event,
|
||||
sync::WaitCondition,
|
||||
syscall::{
|
||||
context::file::InternalFlags, event, sync::WaitCondition, syscall::{
|
||||
data::Stat,
|
||||
error::{Error, Result, EAGAIN, EBADF, EINTR, EINVAL, ENOENT, EPIPE, ESPIPE},
|
||||
flag::{
|
||||
EventFlags, EVENT_READ, EVENT_WRITE, F_GETFL, F_SETFL, MODE_FIFO, O_ACCMODE, O_NONBLOCK,
|
||||
},
|
||||
usercopy::{UserSliceRo, UserSliceWo},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
use super::{CallerCtx, GlobalSchemes, KernelScheme, OpenResult};
|
||||
@@ -40,14 +38,12 @@ fn from_raw_id(id: usize) -> (bool, usize) {
|
||||
(id & WRITE_NOT_READ_BIT != 0, id & !WRITE_NOT_READ_BIT)
|
||||
}
|
||||
|
||||
pub fn pipe(flags: usize) -> Result<(usize, usize)> {
|
||||
pub fn pipe() -> Result<(usize, usize)> {
|
||||
let id = PIPE_NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
PIPES.write().insert(
|
||||
id,
|
||||
Arc::new(Pipe {
|
||||
read_flags: AtomicUsize::new(flags),
|
||||
write_flags: AtomicUsize::new(flags),
|
||||
queue: Mutex::new(VecDeque::new()),
|
||||
read_condition: WaitCondition::new(),
|
||||
write_condition: WaitCondition::new(),
|
||||
@@ -63,26 +59,6 @@ pub fn pipe(flags: usize) -> Result<(usize, usize)> {
|
||||
pub struct PipeScheme;
|
||||
|
||||
impl KernelScheme for PipeScheme {
|
||||
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let (is_writer_not_reader, key) = from_raw_id(id);
|
||||
let pipe = Arc::clone(PIPES.read().get(&key).ok_or(Error::new(EBADF))?);
|
||||
|
||||
let flags = if is_writer_not_reader {
|
||||
&pipe.write_flags
|
||||
} else {
|
||||
&pipe.read_flags
|
||||
};
|
||||
|
||||
match cmd {
|
||||
F_GETFL => Ok(flags.load(Ordering::SeqCst)),
|
||||
F_SETFL => {
|
||||
flags.store(arg & !O_ACCMODE, Ordering::SeqCst);
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(Error::new(EINVAL)),
|
||||
}
|
||||
}
|
||||
|
||||
fn fevent(&self, id: usize, flags: EventFlags) -> Result<EventFlags> {
|
||||
let (is_writer_not_reader, key) = from_raw_id(id);
|
||||
let pipe = Arc::clone(PIPES.read().get(&key).ok_or(Error::new(EBADF))?);
|
||||
@@ -99,10 +75,6 @@ impl KernelScheme for PipeScheme {
|
||||
Ok(ready)
|
||||
}
|
||||
|
||||
fn fsync(&self, _id: usize) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close(&self, id: usize) -> Result<()> {
|
||||
let (is_write_not_read, key) = from_raw_id(id);
|
||||
|
||||
@@ -132,9 +104,6 @@ impl KernelScheme for PipeScheme {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn seek(&self, _id: usize, _pos: isize, _whence: usize) -> Result<usize> {
|
||||
Err(Error::new(ESPIPE))
|
||||
}
|
||||
fn kdup(&self, old_id: usize, user_buf: UserSliceRo, _ctx: CallerCtx) -> Result<OpenResult> {
|
||||
let (is_writer_not_reader, key) = from_raw_id(old_id);
|
||||
|
||||
@@ -154,19 +123,19 @@ impl KernelScheme for PipeScheme {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
|
||||
Ok(OpenResult::SchemeLocal(key | WRITE_NOT_READ_BIT))
|
||||
Ok(OpenResult::SchemeLocal(key | WRITE_NOT_READ_BIT, InternalFlags::empty()))
|
||||
}
|
||||
fn kopen(&self, path: &str, flags: usize, _ctx: CallerCtx) -> Result<OpenResult> {
|
||||
fn kopen(&self, path: &str, _flags: usize, _ctx: CallerCtx) -> Result<OpenResult> {
|
||||
if !path.trim_start_matches('/').is_empty() {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
|
||||
let (read_id, _) = pipe(flags)?;
|
||||
let (read_id, _) = pipe()?;
|
||||
|
||||
Ok(OpenResult::SchemeLocal(read_id))
|
||||
Ok(OpenResult::SchemeLocal(read_id, InternalFlags::empty()))
|
||||
}
|
||||
|
||||
fn kread(&self, id: usize, user_buf: UserSliceWo) -> Result<usize> {
|
||||
fn kread(&self, id: usize, user_buf: UserSliceWo, fcntl_flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let (is_write_not_read, key) = from_raw_id(id);
|
||||
|
||||
if is_write_not_read {
|
||||
@@ -209,14 +178,14 @@ impl KernelScheme for PipeScheme {
|
||||
|
||||
if !pipe.writer_is_alive.load(Ordering::SeqCst) {
|
||||
return Ok(0);
|
||||
} else if pipe.read_flags.load(Ordering::SeqCst) & O_NONBLOCK == O_NONBLOCK {
|
||||
} else if fcntl_flags & O_NONBLOCK as u32 != 0 {
|
||||
return Err(Error::new(EAGAIN));
|
||||
} else if !pipe.read_condition.wait(vec, "PipeRead::read") {
|
||||
return Err(Error::new(EINTR));
|
||||
}
|
||||
}
|
||||
}
|
||||
fn kwrite(&self, id: usize, user_buf: UserSliceRo) -> Result<usize> {
|
||||
fn kwrite(&self, id: usize, user_buf: UserSliceRo, fcntl_flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let (is_write_not_read, key) = from_raw_id(id);
|
||||
|
||||
if !is_write_not_read {
|
||||
@@ -260,7 +229,7 @@ impl KernelScheme for PipeScheme {
|
||||
|
||||
if !pipe.reader_is_alive.load(Ordering::SeqCst) {
|
||||
return Err(Error::new(EPIPE));
|
||||
} else if pipe.write_flags.load(Ordering::SeqCst) & O_NONBLOCK == O_NONBLOCK {
|
||||
} else if fcntl_flags & O_NONBLOCK as u32 != 0 {
|
||||
return Err(Error::new(EAGAIN));
|
||||
} else if !pipe.write_condition.wait(vec, "PipeWrite::write") {
|
||||
return Err(Error::new(EINTR));
|
||||
@@ -278,8 +247,6 @@ impl KernelScheme for PipeScheme {
|
||||
}
|
||||
|
||||
pub struct Pipe {
|
||||
read_flags: AtomicUsize, // fcntl read flags
|
||||
write_flags: AtomicUsize, // fcntl write flags
|
||||
read_condition: WaitCondition, // signals whether there are available bytes to read
|
||||
write_condition: WaitCondition, // signals whether there is room for additional bytes
|
||||
queue: Mutex<VecDeque<u8>>,
|
||||
|
||||
+72
-75
@@ -1,17 +1,14 @@
|
||||
use crate::{
|
||||
arch::paging::{Page, RmmA, RmmArch, VirtualAddress},
|
||||
context::{
|
||||
self,
|
||||
file::FileDescriptor,
|
||||
memory::{handle_notify_files, Grant, PageSpan, AddrSpaceWrapper},
|
||||
Context, ContextId, Status, context::{HardBlockedReason, Altstack, SignalHandler},
|
||||
self, context::{Altstack, HardBlockedReason, SignalHandler}, file::{FileDescriptor, InternalFlags}, memory::{handle_notify_files, AddrSpaceWrapper, Grant, PageSpan}, Context, ContextId, Status
|
||||
},
|
||||
memory::PAGE_SIZE,
|
||||
ptrace,
|
||||
scheme::{self, FileHandle, KernelScheme},
|
||||
syscall::{
|
||||
self,
|
||||
data::{GrantDesc, Map, PtraceEvent, SigAction, SetSighandlerData, Stat},
|
||||
data::{GrantDesc, Map, PtraceEvent, SetSighandlerData, SigAction, Stat},
|
||||
error::*,
|
||||
flag::*,
|
||||
usercopy::{UserSliceRo, UserSliceWo},
|
||||
@@ -37,13 +34,9 @@ use spinning_top::RwSpinlock;
|
||||
|
||||
use super::{CallerCtx, GlobalSchemes, KernelSchemes, OpenResult};
|
||||
|
||||
fn read_from(dst: UserSliceWo, src: &[u8], offset: &mut usize) -> Result<usize> {
|
||||
let avail_src = src.get(*offset..).unwrap_or(&[]);
|
||||
let bytes_copied = dst.copy_common_bytes_from_slice(avail_src)?;
|
||||
*offset = offset
|
||||
.checked_add(bytes_copied)
|
||||
.ok_or(Error::new(EOVERFLOW))?;
|
||||
Ok(bytes_copied)
|
||||
fn read_from(dst: UserSliceWo, src: &[u8], offset: u64) -> Result<usize> {
|
||||
let avail_src = usize::try_from(offset).ok().and_then(|o| src.get(o..)).unwrap_or(&[]);
|
||||
dst.copy_common_bytes_from_slice(avail_src)
|
||||
}
|
||||
|
||||
fn with_context<F, T>(pid: ContextId, callback: F) -> Result<T>
|
||||
@@ -198,17 +191,16 @@ struct TraceData {
|
||||
}
|
||||
struct StaticData {
|
||||
buf: Box<[u8]>,
|
||||
offset: usize,
|
||||
}
|
||||
impl StaticData {
|
||||
fn new(buf: Box<[u8]>) -> Self {
|
||||
Self { buf, offset: 0 }
|
||||
Self { buf }
|
||||
}
|
||||
}
|
||||
enum OperationData {
|
||||
Trace(TraceData),
|
||||
Static(StaticData),
|
||||
Offset(usize),
|
||||
Offset,
|
||||
Other,
|
||||
}
|
||||
impl OperationData {
|
||||
@@ -264,10 +256,10 @@ static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
|
||||
// Using BTreeMap as hashbrown doesn't have a const constructor.
|
||||
static HANDLES: RwLock<BTreeMap<usize, Handle>> = RwLock::new(BTreeMap::new());
|
||||
|
||||
fn new_handle(handle: Handle) -> Result<usize> {
|
||||
fn new_handle((handle, fl): (Handle, InternalFlags)) -> Result<(usize, InternalFlags)> {
|
||||
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
let _ = HANDLES.write().insert(id, handle);
|
||||
Ok(id)
|
||||
Ok((id, fl))
|
||||
}
|
||||
|
||||
fn get_context(id: ContextId) -> Result<Arc<RwSpinlock<Context>>> {
|
||||
@@ -285,46 +277,46 @@ impl<const FULL: bool> ProcScheme<FULL> {
|
||||
flags: usize,
|
||||
uid: u32,
|
||||
gid: u32,
|
||||
) -> Result<usize> {
|
||||
let operation = match operation_str {
|
||||
Some("addrspace") => Operation::AddrSpace {
|
||||
) -> Result<(usize, InternalFlags)> {
|
||||
let (operation, positioned) = match operation_str {
|
||||
Some("addrspace") => (Operation::AddrSpace {
|
||||
addrspace: Arc::clone(
|
||||
get_context(pid)?
|
||||
.read()
|
||||
.addr_space()
|
||||
.map_err(|_| Error::new(ENOENT))?,
|
||||
),
|
||||
},
|
||||
Some("filetable") => Operation::Filetable {
|
||||
}, true),
|
||||
Some("filetable") => (Operation::Filetable {
|
||||
filetable: Arc::downgrade(&get_context(pid)?.read().files),
|
||||
},
|
||||
Some("current-addrspace") => Operation::CurrentAddrSpace,
|
||||
Some("current-filetable") => Operation::CurrentFiletable,
|
||||
Some("regs/float") => Operation::Regs(RegsKind::Float),
|
||||
Some("regs/int") => Operation::Regs(RegsKind::Int),
|
||||
Some("regs/env") => Operation::Regs(RegsKind::Env),
|
||||
Some("trace") => Operation::Trace,
|
||||
Some("exe") => Operation::Static("exe"),
|
||||
Some("name") => Operation::Name,
|
||||
Some("session_id") => Operation::SessionId,
|
||||
Some("sighandler") => Operation::Sighandler,
|
||||
Some("sigprocmask") => Operation::Sigprocmask,
|
||||
Some("sigignmask") => Operation::Sigignmask,
|
||||
Some("start") => Operation::Start,
|
||||
Some("uid") => Operation::Attr(Attr::Uid),
|
||||
Some("gid") => Operation::Attr(Attr::Gid),
|
||||
Some("open_via_dup") => Operation::OpenViaDup,
|
||||
}, true),
|
||||
Some("current-addrspace") => (Operation::CurrentAddrSpace, false),
|
||||
Some("current-filetable") => (Operation::CurrentFiletable, false),
|
||||
Some("regs/float") => (Operation::Regs(RegsKind::Float), false),
|
||||
Some("regs/int") => (Operation::Regs(RegsKind::Int), false),
|
||||
Some("regs/env") => (Operation::Regs(RegsKind::Env), false),
|
||||
Some("trace") => (Operation::Trace, false),
|
||||
Some("exe") => (Operation::Static("exe"), true),
|
||||
Some("name") => (Operation::Name, true),
|
||||
Some("session_id") => (Operation::SessionId, true),
|
||||
Some("sighandler") => (Operation::Sighandler, false),
|
||||
Some("sigprocmask") => (Operation::Sigprocmask, false),
|
||||
Some("sigignmask") => (Operation::Sigignmask, false),
|
||||
Some("start") => (Operation::Start, false),
|
||||
Some("uid") => (Operation::Attr(Attr::Uid), true),
|
||||
Some("gid") => (Operation::Attr(Attr::Gid), true),
|
||||
Some("open_via_dup") => (Operation::OpenViaDup, false),
|
||||
Some("sigactions") => {
|
||||
Operation::Sigactions(Arc::clone(&get_context(pid)?.read().actions))
|
||||
(Operation::Sigactions(Arc::clone(&get_context(pid)?.read().actions)), false)
|
||||
}
|
||||
Some("current-sigactions") => Operation::CurrentSigactions,
|
||||
Some("mmap-min-addr") => Operation::MmapMinAddr(Arc::clone(
|
||||
Some("current-sigactions") => (Operation::CurrentSigactions, false),
|
||||
Some("mmap-min-addr") => (Operation::MmapMinAddr(Arc::clone(
|
||||
get_context(pid)?
|
||||
.read()
|
||||
.addr_space()
|
||||
.map_err(|_| Error::new(ENOENT))?,
|
||||
)),
|
||||
Some("sched-affinity") => Operation::SchedAffinity,
|
||||
)), false),
|
||||
Some("sched-affinity") => (Operation::SchedAffinity, true),
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
};
|
||||
|
||||
@@ -341,7 +333,7 @@ impl<const FULL: bool> ProcScheme<FULL> {
|
||||
Operation::Static(_) => OperationData::Static(StaticData::new(
|
||||
target.name.clone().into_owned().into_bytes().into(),
|
||||
)),
|
||||
Operation::AddrSpace { .. } => OperationData::Offset(0),
|
||||
Operation::AddrSpace { .. } => OperationData::Offset,
|
||||
_ => OperationData::Other,
|
||||
};
|
||||
|
||||
@@ -403,14 +395,14 @@ impl<const FULL: bool> ProcScheme<FULL> {
|
||||
}
|
||||
};
|
||||
|
||||
let id = new_handle(Handle {
|
||||
let (id, int_fl) = new_handle((Handle {
|
||||
info: Info {
|
||||
flags,
|
||||
pid,
|
||||
operation: operation.clone(),
|
||||
},
|
||||
data,
|
||||
})?;
|
||||
}, if positioned { InternalFlags::POSITIONED } else { InternalFlags::empty() }))?;
|
||||
|
||||
if let Operation::Trace = operation {
|
||||
if !ptrace::try_new_session(pid, id) {
|
||||
@@ -425,7 +417,7 @@ impl<const FULL: bool> ProcScheme<FULL> {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(id)
|
||||
Ok((id, int_fl))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
@@ -599,7 +591,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
};
|
||||
|
||||
self.open_inner(pid, parts.next(), flags, ctx.uid, ctx.gid)
|
||||
.map(OpenResult::SchemeLocal)
|
||||
.map(|(r, fl)| OpenResult::SchemeLocal(r, fl))
|
||||
}
|
||||
|
||||
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
@@ -762,7 +754,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
_ => Err(Error::new(EBADF)),
|
||||
}
|
||||
}
|
||||
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
fn kreadoff(&self, id: usize, buf: UserSliceWo, offset: u64, read_flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
// Don't hold a global lock during the context switch later on
|
||||
let info = {
|
||||
let handles = HANDLES.read();
|
||||
@@ -774,12 +766,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
Operation::Static(_) => {
|
||||
let mut handles = HANDLES.write();
|
||||
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
let data = handle.data.static_data().expect("operations can't change");
|
||||
let src_buf = data.buf.get(data.offset..).unwrap_or(&[]);
|
||||
|
||||
let len = buf.copy_common_bytes_from_slice(src_buf)?;
|
||||
data.offset += len;
|
||||
Ok(len)
|
||||
read_from(buf, &handle.data.static_data().ok_or(Error::new(EBADFD))?.buf, offset)
|
||||
}
|
||||
Operation::Regs(kind) => {
|
||||
union Output {
|
||||
@@ -877,11 +864,15 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
Ok(read * mem::size_of::<PtraceEvent>())
|
||||
}
|
||||
Operation::AddrSpace { ref addrspace } => {
|
||||
let OperationData::Offset(orig_offset) =
|
||||
let OperationData::Offset =
|
||||
HANDLES.read().get(&id).ok_or(Error::new(EBADF))?.data
|
||||
else {
|
||||
return Err(Error::new(EBADFD));
|
||||
};
|
||||
let Ok(offset) = usize::try_from(offset) else {
|
||||
return Ok(0);
|
||||
};
|
||||
let grants_to_skip = offset / mem::size_of::<GrantDesc>();
|
||||
|
||||
// Output a list of grant descriptors, sufficient to allow relibc's fork()
|
||||
// implementation to fmap MAP_SHARED grants.
|
||||
@@ -891,7 +882,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
|
||||
for (dst, (grant_base, grant_info)) in dst
|
||||
.iter_mut()
|
||||
.zip(addrspace.acquire_read().grants.iter().skip(orig_offset))
|
||||
.zip(addrspace.acquire_read().grants.iter().skip(grants_to_skip))
|
||||
{
|
||||
*dst = GrantDesc {
|
||||
base: grant_base.start_address().data(),
|
||||
@@ -911,11 +902,6 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
chunk.copy_exactly(src)?;
|
||||
}
|
||||
|
||||
match HANDLES.write().get_mut(&id).ok_or(Error::new(EBADF))?.data {
|
||||
OperationData::Offset(ref mut offset) => *offset += grants_read,
|
||||
_ => return Err(Error::new(EBADFD)),
|
||||
};
|
||||
|
||||
Ok(grants_read * mem::size_of::<GrantDesc>())
|
||||
}
|
||||
Operation::Name => read_from(
|
||||
@@ -926,7 +912,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
.read()
|
||||
.name
|
||||
.as_bytes(),
|
||||
&mut 0,
|
||||
offset,
|
||||
),
|
||||
Operation::SessionId => read_from(
|
||||
buf,
|
||||
@@ -937,7 +923,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
.session_id
|
||||
.get()
|
||||
.to_ne_bytes(),
|
||||
&mut 0,
|
||||
offset,
|
||||
),
|
||||
|
||||
Operation::Sighandler => {
|
||||
@@ -985,14 +971,14 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
}
|
||||
.into_bytes();
|
||||
|
||||
read_from(buf, &src_buf, &mut 0)
|
||||
read_from(buf, &src_buf, offset)
|
||||
}
|
||||
Operation::Filetable { .. } => {
|
||||
let mut handles = HANDLES.write();
|
||||
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
let data = handle.data.static_data().expect("operations can't change");
|
||||
|
||||
read_from(buf, &data.buf, &mut data.offset)
|
||||
read_from(buf, &data.buf, offset)
|
||||
}
|
||||
Operation::MmapMinAddr(ref addrspace) => {
|
||||
buf.write_usize(addrspace.acquire_read().mmap_min)?;
|
||||
@@ -1016,7 +1002,9 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
_ => Err(Error::new(EBADF)),
|
||||
}
|
||||
}
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo) -> Result<usize> {
|
||||
fn kwriteoff(&self, id: usize, buf: UserSliceRo, _offset: u64, fcntl_flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
// TODO: offset
|
||||
|
||||
// Don't hold a global lock during the context switch later on
|
||||
let info = {
|
||||
let mut handles = HANDLES.write();
|
||||
@@ -1406,7 +1394,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
buffer.copy_exactly(&Stat {
|
||||
st_mode: MODE_FILE | 0o666,
|
||||
st_size: match handle.data {
|
||||
OperationData::Static(ref data) => (data.buf.len() - data.offset) as u64,
|
||||
OperationData::Static(ref data) => data.buf.len() as u64,
|
||||
_ => 0,
|
||||
},
|
||||
|
||||
@@ -1416,6 +1404,14 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fsize(&self, id: usize) -> Result<u64> {
|
||||
let mut handles = HANDLES.write();
|
||||
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
// TODO: operation-dependent
|
||||
Ok(handle.data.static_data().ok_or(Error::new(ESPIPE))?.buf.len() as u64)
|
||||
}
|
||||
|
||||
/// Dup is currently used to implement clone() and execve().
|
||||
fn kdup(&self, old_id: usize, raw_buf: UserSliceRo, _: CallerCtx) -> Result<OpenResult> {
|
||||
let info = {
|
||||
@@ -1425,14 +1421,14 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
handle.info.clone()
|
||||
};
|
||||
|
||||
let handle = |operation, data| Handle {
|
||||
let handle = |operation, data, positioned| (Handle {
|
||||
info: Info {
|
||||
flags: 0,
|
||||
pid: info.pid,
|
||||
operation,
|
||||
},
|
||||
data,
|
||||
};
|
||||
}, if positioned { InternalFlags::POSITIONED } else { InternalFlags::empty() });
|
||||
let mut array = [0_u8; 64];
|
||||
if raw_buf.len() > array.len() {
|
||||
return Err(Error::new(EINVAL));
|
||||
@@ -1458,7 +1454,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
uid,
|
||||
gid,
|
||||
)
|
||||
.map(OpenResult::SchemeLocal);
|
||||
.map(|(r, fl)| OpenResult::SchemeLocal(r, fl))
|
||||
}
|
||||
|
||||
Operation::Filetable { ref filetable } => {
|
||||
@@ -1477,6 +1473,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
filetable: new_filetable,
|
||||
},
|
||||
OperationData::Other,
|
||||
true,
|
||||
)
|
||||
}
|
||||
Operation::AddrSpace { ref addrspace } => {
|
||||
@@ -1524,7 +1521,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
};
|
||||
|
||||
handle(operation, OperationData::Offset(0))
|
||||
handle(operation, OperationData::Offset, true)
|
||||
}
|
||||
Operation::Sigactions(ref sigactions) => {
|
||||
let new = match buf {
|
||||
@@ -1532,11 +1529,11 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
b"copy" => Arc::new(RwLock::new(sigactions.read().clone())),
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
};
|
||||
handle(Operation::Sigactions(new), OperationData::Other)
|
||||
handle(Operation::Sigactions(new), OperationData::Other, false)
|
||||
}
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
})
|
||||
.map(OpenResult::SchemeLocal)
|
||||
.map(|(r, fl)| OpenResult::SchemeLocal(r, fl))
|
||||
}
|
||||
}
|
||||
extern "C" fn clone_handler() {
|
||||
|
||||
+20
-28
@@ -1,4 +1,5 @@
|
||||
use alloc::{boxed::Box, string::ToString, sync::Arc, vec::Vec};
|
||||
use syscall::O_FSYNC;
|
||||
use core::{
|
||||
str,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
@@ -7,7 +8,7 @@ use hashbrown::HashMap;
|
||||
use spin::{Mutex, RwLock};
|
||||
|
||||
use crate::{
|
||||
context,
|
||||
context::{self, file::InternalFlags},
|
||||
scheme::{
|
||||
self,
|
||||
user::{UserInner, UserScheme},
|
||||
@@ -21,29 +22,16 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use super::{calc_seek_offset, CallerCtx, KernelScheme, KernelSchemes, OpenResult};
|
||||
use super::{CallerCtx, KernelScheme, KernelSchemes, OpenResult};
|
||||
|
||||
struct FolderInner {
|
||||
data: Box<[u8]>,
|
||||
pos: Mutex<usize>,
|
||||
}
|
||||
|
||||
impl FolderInner {
|
||||
fn read(&self, buf: UserSliceWo) -> Result<usize> {
|
||||
let mut pos_guard = self.pos.lock();
|
||||
|
||||
let avail_buf = self.data.get(*pos_guard..).unwrap_or(&[]);
|
||||
let bytes_read = buf.copy_common_bytes_from_slice(avail_buf)?;
|
||||
*pos_guard += bytes_read;
|
||||
|
||||
Ok(bytes_read)
|
||||
}
|
||||
|
||||
fn seek(&self, pos: isize, whence: usize) -> Result<usize> {
|
||||
let mut seek = self.pos.lock();
|
||||
let new_offset = calc_seek_offset(*seek, pos, whence, self.data.len())?;
|
||||
*seek = new_offset as usize;
|
||||
Ok(new_offset)
|
||||
fn read(&self, buf: UserSliceWo, offset: u64) -> Result<usize> {
|
||||
let avail_buf = usize::try_from(offset).ok().and_then(|o| self.data.get(o..)).unwrap_or(&[]);
|
||||
buf.copy_common_bytes_from_slice(avail_buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +91,11 @@ impl KernelScheme for RootScheme {
|
||||
let inner = Arc::new(UserInner::new(
|
||||
self.scheme_id,
|
||||
scheme_id,
|
||||
|
||||
// TODO: This is a hack, but eventually the legacy interface will be
|
||||
// removed.
|
||||
flags & O_FSYNC == O_FSYNC,
|
||||
|
||||
id,
|
||||
path_box,
|
||||
flags,
|
||||
@@ -119,7 +112,7 @@ impl KernelScheme for RootScheme {
|
||||
|
||||
self.handles.write().insert(id, Handle::Scheme(inner));
|
||||
|
||||
Ok(OpenResult::SchemeLocal(id))
|
||||
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
|
||||
} else if path.is_empty() {
|
||||
let scheme_ns = {
|
||||
let contexts = context::contexts();
|
||||
@@ -139,18 +132,17 @@ impl KernelScheme for RootScheme {
|
||||
|
||||
let inner = Arc::new(FolderInner {
|
||||
data: data.into_boxed_slice(),
|
||||
pos: Mutex::new(0),
|
||||
});
|
||||
|
||||
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
|
||||
self.handles.write().insert(id, Handle::Folder(inner));
|
||||
Ok(OpenResult::SchemeLocal(id))
|
||||
Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED))
|
||||
} else {
|
||||
let inner = Arc::new(path.as_bytes().to_vec().into_boxed_slice());
|
||||
|
||||
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
|
||||
self.handles.write().insert(id, Handle::File(inner));
|
||||
Ok(OpenResult::SchemeLocal(id))
|
||||
Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +173,7 @@ impl KernelScheme for RootScheme {
|
||||
inner.unmount()
|
||||
}
|
||||
|
||||
fn seek(&self, file: usize, pos: isize, whence: usize) -> Result<usize> {
|
||||
fn fsize(&self, file: usize) -> Result<u64> {
|
||||
let handle = {
|
||||
let handles = self.handles.read();
|
||||
let handle = handles.get(&file).ok_or(Error::new(EBADF))?;
|
||||
@@ -191,7 +183,7 @@ impl KernelScheme for RootScheme {
|
||||
match handle {
|
||||
Handle::Scheme(_) => Err(Error::new(EBADF)),
|
||||
Handle::File(_) => Err(Error::new(EBADF)),
|
||||
Handle::Folder(inner) => inner.seek(pos, whence),
|
||||
Handle::Folder(inner) => Ok(inner.data.len() as u64),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +252,7 @@ impl KernelScheme for RootScheme {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn kread(&self, file: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
fn kreadoff(&self, file: usize, buf: UserSliceWo, offset: u64, flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let handle = {
|
||||
let handles = self.handles.read();
|
||||
let handle = handles.get(&file).ok_or(Error::new(EBADF))?;
|
||||
@@ -268,13 +260,13 @@ impl KernelScheme for RootScheme {
|
||||
};
|
||||
|
||||
match handle {
|
||||
Handle::Scheme(inner) => inner.read(buf),
|
||||
Handle::Scheme(inner) => inner.read(buf, flags),
|
||||
Handle::File(_) => Err(Error::new(EBADF)),
|
||||
Handle::Folder(inner) => inner.read(buf),
|
||||
Handle::Folder(inner) => inner.read(buf, offset),
|
||||
}
|
||||
}
|
||||
|
||||
fn kwrite(&self, file: usize, buf: UserSliceRo) -> Result<usize> {
|
||||
fn kwrite(&self, file: usize, buf: UserSliceRo, _flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let handle = {
|
||||
let handles = self.handles.read();
|
||||
let handle = handles.get(&file).ok_or(Error::new(EBADF))?;
|
||||
|
||||
+4
-22
@@ -25,7 +25,6 @@ static INPUT: [WaitQueue<u8>; 2] = [WaitQueue::new(), WaitQueue::new()];
|
||||
#[derive(Clone, Copy)]
|
||||
struct Handle {
|
||||
index: usize,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
// Using BTreeMap as hashbrown doesn't have a const constructor.
|
||||
@@ -46,7 +45,7 @@ pub fn serio_input(index: usize, data: u8) {
|
||||
pub struct SerioScheme;
|
||||
|
||||
impl KernelScheme for SerioScheme {
|
||||
fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result<OpenResult> {
|
||||
fn kopen(&self, path: &str, _flags: usize, ctx: CallerCtx) -> Result<OpenResult> {
|
||||
if ctx.uid != 0 {
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
@@ -61,27 +60,10 @@ impl KernelScheme for SerioScheme {
|
||||
id,
|
||||
Handle {
|
||||
index,
|
||||
flags: flags & !O_ACCMODE,
|
||||
},
|
||||
);
|
||||
|
||||
Ok(OpenResult::SchemeLocal(id))
|
||||
}
|
||||
|
||||
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let mut handles = HANDLES.write();
|
||||
if let Some(handle) = handles.get_mut(&id) {
|
||||
match cmd {
|
||||
F_GETFL => Ok(handle.flags),
|
||||
F_SETFL => {
|
||||
handle.flags = arg & !O_ACCMODE;
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(Error::new(EINVAL)),
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
|
||||
}
|
||||
|
||||
fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
|
||||
@@ -111,7 +93,7 @@ impl KernelScheme for SerioScheme {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
fn kread(&self, id: usize, buf: UserSliceWo, flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let handle = {
|
||||
let handles = HANDLES.read();
|
||||
*handles.get(&id).ok_or(Error::new(EBADF))?
|
||||
@@ -119,7 +101,7 @@ impl KernelScheme for SerioScheme {
|
||||
|
||||
INPUT[handle.index].receive_into_user(
|
||||
buf,
|
||||
handle.flags & O_NONBLOCK != O_NONBLOCK,
|
||||
flags & O_NONBLOCK as u32 == 0,
|
||||
"SerioScheme::read",
|
||||
)
|
||||
}
|
||||
|
||||
+14
-19
@@ -6,16 +6,15 @@ use core::{
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::{
|
||||
arch::interrupt,
|
||||
syscall::{
|
||||
arch::interrupt, context::file::InternalFlags, syscall::{
|
||||
data::Stat,
|
||||
error::{Error, Result, EBADF, ENOENT},
|
||||
flag::{MODE_DIR, MODE_FILE},
|
||||
usercopy::UserSliceWo,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
use super::{calc_seek_offset, CallerCtx, KernelScheme, OpenResult};
|
||||
use super::{CallerCtx, KernelScheme, OpenResult};
|
||||
|
||||
mod block;
|
||||
mod context;
|
||||
@@ -33,7 +32,6 @@ struct Handle {
|
||||
path: &'static str,
|
||||
data: Vec<u8>,
|
||||
mode: u16,
|
||||
seek: usize,
|
||||
}
|
||||
|
||||
type SysFn = fn() -> Result<Vec<u8>>;
|
||||
@@ -88,10 +86,9 @@ impl KernelScheme for SysScheme {
|
||||
path: "",
|
||||
data,
|
||||
mode: MODE_DIR | 0o444,
|
||||
seek: 0,
|
||||
},
|
||||
);
|
||||
return Ok(OpenResult::SchemeLocal(id));
|
||||
return Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED));
|
||||
} else {
|
||||
//Have to iterate to get the path without allocation
|
||||
for entry in FILES.iter() {
|
||||
@@ -104,10 +101,9 @@ impl KernelScheme for SysScheme {
|
||||
path: entry.0,
|
||||
data,
|
||||
mode: MODE_FILE | 0o444,
|
||||
seek: 0,
|
||||
},
|
||||
);
|
||||
return Ok(OpenResult::SchemeLocal(id));
|
||||
return Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,13 +111,11 @@ impl KernelScheme for SysScheme {
|
||||
Err(Error::new(ENOENT))
|
||||
}
|
||||
|
||||
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<usize> {
|
||||
fn fsize(&self, id: usize) -> Result<u64> {
|
||||
let mut handles = HANDLES.write();
|
||||
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let new_offset = calc_seek_offset(handle.seek, pos, whence, handle.data.len())?;
|
||||
handle.seek = new_offset;
|
||||
Ok(new_offset)
|
||||
Ok(handle.data.len() as u64)
|
||||
}
|
||||
|
||||
fn fsync(&self, _id: usize) -> Result<()> {
|
||||
@@ -148,16 +142,17 @@ impl KernelScheme for SysScheme {
|
||||
|
||||
Ok(bytes_read)
|
||||
}
|
||||
fn kread(&self, id: usize, buffer: UserSliceWo) -> Result<usize> {
|
||||
fn kreadoff(&self, id: usize, buffer: UserSliceWo, pos: u64, _flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let Ok(pos) = usize::try_from(pos) else {
|
||||
return Ok(0);
|
||||
};
|
||||
|
||||
let mut handles = HANDLES.write();
|
||||
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let avail_buf = handle.data.get(handle.seek..).unwrap_or(&[]);
|
||||
let avail_buf = handle.data.get(pos..).unwrap_or(&[]);
|
||||
|
||||
let byte_count = buffer.copy_common_bytes_from_slice(avail_buf)?;
|
||||
|
||||
handle.seek = handle.seek.saturating_add(byte_count);
|
||||
Ok(byte_count)
|
||||
buffer.copy_common_bytes_from_slice(avail_buf)
|
||||
}
|
||||
|
||||
fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> {
|
||||
|
||||
+4
-4
@@ -6,7 +6,7 @@ use core::{
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::{
|
||||
context::timeout,
|
||||
context::{file::InternalFlags, timeout},
|
||||
syscall::{
|
||||
data::TimeSpec,
|
||||
error::*,
|
||||
@@ -37,7 +37,7 @@ impl KernelScheme for TimeScheme {
|
||||
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
HANDLES.write().insert(id, clock);
|
||||
|
||||
Ok(OpenResult::SchemeLocal(id))
|
||||
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
|
||||
}
|
||||
|
||||
fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
|
||||
@@ -64,7 +64,7 @@ impl KernelScheme for TimeScheme {
|
||||
.ok_or(Error::new(EBADF))
|
||||
.and(Ok(()))
|
||||
}
|
||||
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
|
||||
fn kread(&self, id: usize, buf: UserSliceWo, _flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let clock = *HANDLES.read().get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let mut bytes_read = 0;
|
||||
@@ -87,7 +87,7 @@ impl KernelScheme for TimeScheme {
|
||||
Ok(bytes_read)
|
||||
}
|
||||
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo) -> Result<usize> {
|
||||
fn kwrite(&self, id: usize, buf: UserSliceRo, _flags: u32, _stored_flags: u32) -> Result<usize> {
|
||||
let clock = *HANDLES.read().get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let mut bytes_written = 0;
|
||||
|
||||
+472
-299
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user