Add getdents syscall, and switch schemes to it.

This commit is contained in:
4lDO2
2024-09-08 22:21:55 +02:00
parent 548fd63264
commit 339271b4d7
15 changed files with 224 additions and 177 deletions
+1
View File
@@ -49,6 +49,7 @@ default = [
"serial_debug",
"self_modifying",
"x86_kvm_pv",
"syscall_debug",
]
# Activates some limited code-overwriting optimizations, based on CPU features.
+6 -6
View File
@@ -296,19 +296,19 @@ pub unsafe fn init(
let real_size = 0x100000;
let real_end = real_base + real_size;
let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let kernel_size_aligned = kernel_size.next_multiple_of(A::PAGE_SIZE);
let kernel_end = kernel_base + kernel_size_aligned;
let stack_size_aligned = ((stack_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let stack_size_aligned = stack_size.next_multiple_of(A::PAGE_SIZE);
let stack_end = stack_base + stack_size_aligned;
let env_size_aligned = ((env_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let env_size_aligned = env_size.next_multiple_of(A::PAGE_SIZE);
let env_end = env_base + env_size_aligned;
let acpi_size_aligned = ((acpi_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let acpi_size_aligned = acpi_size.next_multiple_of(A::PAGE_SIZE);
let acpi_end = acpi_base + acpi_size_aligned;
let initfs_size_aligned = ((initfs_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let initfs_size_aligned = initfs_size.next_multiple_of(A::PAGE_SIZE);
let initfs_end = initfs_base + initfs_size_aligned;
let bootloader_areas = slice::from_raw_parts(
@@ -329,7 +329,7 @@ pub unsafe fn init(
let mut base = bootloader_area.base as usize;
let mut size = bootloader_area.size as usize;
log::debug!("{:X}:{:X}", base, size);
log::info!("{:X}:{:X}", base, size);
// Page align base
let base_offset = (A::PAGE_SIZE - (base & A::PAGE_OFFSET_MASK)) & A::PAGE_OFFSET_MASK;
-2
View File
@@ -42,12 +42,10 @@
// Ensure that all must_use results are used
#![deny(unused_must_use)]
#![feature(allocator_api)]
#![feature(asm_const)] // TODO: Relax requirements of most asm invocations
#![feature(int_roundings)]
#![feature(iter_next_chunk)]
#![feature(let_chains)]
#![feature(naked_functions)]
#![feature(new_uninit)]
#![feature(sync_unsafe_cell)]
#![feature(variant_count)]
#![no_std]
+1
View File
@@ -8,6 +8,7 @@ use crate::{context, cpu_id, interrupt, syscall};
#[panic_handler]
fn rust_begin_unwind(info: &PanicInfo) -> ! {
println!("KERNEL PANIC: {}", info);
loop {}
unsafe {
interrupt::stack_trace();
+21 -8
View File
@@ -7,6 +7,10 @@ use core::{
use alloc::{boxed::Box, collections::BTreeMap};
use spin::{Mutex, Once, RwLock};
use syscall::{
dirent::{DirentBuf, DirentKind},
EIO,
};
use crate::{
acpi::{RxsdtEnum, RXSDT_ENUM},
@@ -47,8 +51,6 @@ static NEXT_FD: AtomicUsize = AtomicUsize::new(0);
static DATA: Once<Box<[u8]>> = Once::new();
const TOPLEVEL_CONTENTS: &[u8] = b"rxsdt\nkstop\n";
static KSTOP_WAITCOND: WaitCondition = WaitCondition::new();
static KSTOP_FLAG: Mutex<bool> = Mutex::new(false);
@@ -169,7 +171,7 @@ impl KernelScheme for AcpiScheme {
Ok(match handle.kind {
HandleKind::Rxsdt => DATA.get().ok_or(Error::new(EBADFD))?.len() as u64,
HandleKind::ShutdownPipe => 1,
HandleKind::TopLevel => TOPLEVEL_CONTENTS.len() as u64,
HandleKind::TopLevel => 0,
})
}
// TODO
@@ -227,7 +229,7 @@ impl KernelScheme for AcpiScheme {
return dst_buf.copy_exactly(&[0x42]).map(|()| 1);
}
HandleKind::Rxsdt => DATA.get().ok_or(Error::new(EBADFD))?,
HandleKind::TopLevel => TOPLEVEL_CONTENTS,
HandleKind::TopLevel => return Err(Error::new(EISDIR)),
};
let src_offset = core::cmp::min(offset, data.len());
@@ -237,6 +239,20 @@ impl KernelScheme for AcpiScheme {
dst_buf.copy_common_bytes_from_slice(src_buf)
}
fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result<usize> {
let Some(Handle {
kind: HandleKind::TopLevel,
..
}) = HANDLES.read().get(&id)
else {
return Err(Error::new(ENOTDIR));
};
let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?;
buf.entry(DirentKind::Regular, "rxsdt")?;
buf.entry(DirentKind::Socket, "kstop")?;
Ok(buf.finalize())
}
fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> {
let handles = HANDLES.read();
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
@@ -253,10 +269,7 @@ impl KernelScheme for AcpiScheme {
}
HandleKind::TopLevel => Stat {
st_mode: MODE_DIR,
st_size: TOPLEVEL_CONTENTS
.len()
.try_into()
.unwrap_or(u64::max_value()),
st_size: 0,
..Default::default()
},
HandleKind::ShutdownPipe => Stat {
+43 -58
View File
@@ -10,6 +10,7 @@ use core::{
use alloc::{collections::BTreeMap, string::String, vec::Vec};
use spin::{Mutex, Once, RwLock};
use syscall::dirent::{DirentBuf, DirentKind};
use crate::{
arch::interrupt::{available_irqs_iter, bsp_apic_id, is_reserved, set_reserved},
@@ -68,8 +69,8 @@ pub extern "C" fn irq_trigger(irq: u8) {
enum Handle {
Irq { ack: AtomicUsize, irq: u8 },
Avail(u8, Vec<u8>), // CPU id, data, offset
TopLevel(Vec<u8>), // data, offset
Avail(u8), // CPU id
TopLevel,
Bsp,
}
impl Handle {
@@ -175,27 +176,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
return Err(Error::new(EISDIR));
}
// list every logical CPU in the format of e.g. `cpu-1b`
let mut bytes = String::new();
use core::fmt::Write;
for cpu_id in CPUS.get().expect("IRQ scheme not initialized") {
writeln!(bytes, "cpu-{:02x}", cpu_id).unwrap();
}
if bsp_apic_id().is_some() {
writeln!(bytes, "bsp").unwrap();
}
// 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()),
InternalFlags::POSITIONED,
)
(Handle::TopLevel, InternalFlags::POSITIONED)
} else {
if path_str == "bsp" {
if bsp_apic_id().is_none() {
@@ -208,21 +189,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
let path_str = path_str[2..].trim_end_matches('/');
if path_str.is_empty() {
let mut data = String::new();
use core::fmt::Write;
for vector in available_irqs_iter(LogicalCpuId::new(cpu_id.into())) {
let irq = vector_to_irq(vector);
if Some(u32::from(cpu_id)) == bsp_apic_id() && irq < BASE_IRQ_COUNT {
continue;
}
writeln!(data, "{}", irq).unwrap();
}
(
Handle::Avail(cpu_id, data.into_bytes()),
InternalFlags::POSITIONED,
)
(Handle::Avail(cpu_id), InternalFlags::POSITIONED)
} else if path_str.starts_with('/') {
let path_str = &path_str[1..];
Self::open_ext_irq(flags, cpu_id, path_str)?
@@ -249,15 +216,39 @@ impl crate::scheme::KernelScheme for IrqScheme {
HANDLES.write().insert(fd, handle);
Ok(OpenResult::SchemeLocal(fd, int_flags))
}
fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result<usize> {
use core::fmt::Write;
fn fsize(&self, id: usize) -> Result<u64> {
let handles_guard = HANDLES.read();
let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?;
let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?;
let mut intermediate = String::new();
match *handle {
Handle::Avail(_, ref buf) | Handle::TopLevel(ref buf) => Ok(buf.len() as u64),
_ => Err(Error::new(ESPIPE)),
match *HANDLES.read().get(&id).ok_or(Error::new(EBADF))? {
Handle::TopLevel => {
// list every logical CPU in the format of e.g. `cpu-1b`
for cpu_id in CPUS.get().expect("IRQ scheme not initialized") {
intermediate.clear();
write!(&mut intermediate, "cpu-{:02x}", cpu_id).unwrap();
buf.entry(DirentKind::Directory, &intermediate)?;
}
if bsp_apic_id().is_some() {
buf.entry(DirentKind::CharDev, "bsp")?;
}
}
Handle::Avail(cpu_id) => {
for vector in available_irqs_iter(LogicalCpuId::new(cpu_id.into())) {
let irq = vector_to_irq(vector);
if Some(u32::from(cpu_id)) == bsp_apic_id() && irq < BASE_IRQ_COUNT {
continue;
}
intermediate.clear();
write!(intermediate, "{}", irq).unwrap();
buf.entry(DirentKind::CharDev, &intermediate)?;
}
}
_ => return Err(Error::new(ENOTDIR)),
}
Ok(buf.finalize())
}
fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
@@ -345,16 +336,16 @@ impl crate::scheme::KernelScheme for IrqScheme {
st_nlink: 1,
..Default::default()
},
Handle::Avail(cpu_id, ref buf) => Stat {
Handle::Avail(cpu_id) => Stat {
st_mode: MODE_DIR | 0o700,
st_size: buf.len() as u64,
st_size: 0,
st_ino: INO_AVAIL | u64::from(cpu_id) << 32,
st_nlink: 2,
..Default::default()
},
Handle::TopLevel(ref buf) => Stat {
Handle::TopLevel => Stat {
st_mode: MODE_DIR | 0o500,
st_size: buf.len() as u64,
st_size: 0,
st_ino: INO_TOPLEVEL,
st_nlink: 1,
..Default::default()
@@ -370,8 +361,8 @@ 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();
@@ -381,7 +372,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
&self,
file: usize,
buffer: UserSliceWo,
offset: u64,
_offset: u64,
_flags: u32,
_stored_flags: u32,
) -> Result<usize> {
@@ -416,13 +407,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
Err(Error::new(EBADFD))
}
}
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)
}
Handle::Avail(_) | Handle::TopLevel => Err(Error::new(EISDIR)),
}
}
}
+3
View File
@@ -451,6 +451,9 @@ pub trait KernelScheme: Send + Sync + 'static {
) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
fn fsync(&self, id: usize) -> Result<()> {
Ok(())
+30 -48
View File
@@ -5,7 +5,10 @@ use core::{
};
use hashbrown::HashMap;
use spin::RwLock;
use syscall::O_FSYNC;
use syscall::{
dirent::{DirentBuf, DirentKind},
O_FSYNC,
};
use crate::{
context::{self, file::InternalFlags, process},
@@ -24,25 +27,11 @@ use crate::{
use super::{CallerCtx, KernelScheme, KernelSchemes, OpenResult};
struct FolderInner {
data: Box<[u8]>,
}
impl FolderInner {
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)
}
}
#[derive(Clone)]
enum Handle {
Scheme(Arc<UserInner>),
File(Arc<Box<[u8]>>),
Folder(Arc<FolderInner>),
List { ens: SchemeNamespace },
}
pub struct RootScheme {
@@ -111,23 +100,10 @@ impl KernelScheme for RootScheme {
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
} else if path.is_empty() {
let scheme_ns = process::current()?.read().ens;
let mut data = Vec::new();
{
let schemes = scheme::schemes();
for (name, _scheme_id) in schemes.iter_name(scheme_ns) {
data.extend_from_slice(name.as_bytes());
data.push(b'\n');
}
}
let inner = Arc::new(FolderInner {
data: data.into_boxed_slice(),
});
let ens = process::current()?.read().ens;
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
self.handles.write().insert(id, Handle::Folder(inner));
self.handles.write().insert(id, Handle::List { ens });
Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED))
} else {
let inner = Arc::new(path.as_bytes().to_vec().into_boxed_slice());
@@ -175,7 +151,7 @@ impl KernelScheme for RootScheme {
match handle {
Handle::Scheme(_) => Err(Error::new(EBADF)),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(inner) => Ok(inner.data.len() as u64),
Handle::List { .. } => Ok(0),
}
}
@@ -189,7 +165,7 @@ impl KernelScheme for RootScheme {
match handle {
Handle::Scheme(inner) => inner.fevent(flags),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(_) => Err(Error::new(EBADF)),
Handle::List { .. } => Err(Error::new(EBADF)),
}
}
@@ -210,7 +186,7 @@ impl KernelScheme for RootScheme {
Handle::File(inner) => {
bytes_copied += buf.copy_common_bytes_from_slice(&inner)?;
}
Handle::Folder(_) => (),
Handle::List { .. } => (),
}
Ok(bytes_copied)
@@ -226,7 +202,7 @@ impl KernelScheme for RootScheme {
match handle {
Handle::Scheme(inner) => inner.fsync(),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(_) => Err(Error::new(EBADF)),
Handle::List { .. } => Err(Error::new(EBADF)),
}
}
@@ -248,7 +224,7 @@ impl KernelScheme for RootScheme {
&self,
file: usize,
buf: UserSliceWo,
offset: u64,
_offset: u64,
flags: u32,
_stored_flags: u32,
) -> Result<usize> {
@@ -261,9 +237,24 @@ impl KernelScheme for RootScheme {
match handle {
Handle::Scheme(inner) => inner.read(buf, flags),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(inner) => inner.read(buf, offset),
Handle::List { .. } => Err(Error::new(EISDIR)),
}
}
fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result<usize> {
let Handle::List { ens } = *self.handles.read().get(&id).ok_or(Error::new(EBADF))? else {
return Err(Error::new(ENOTDIR));
};
let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?;
{
let schemes = scheme::schemes();
for (name, _scheme_id) in schemes.iter_name(ens) {
buf.entry(DirentKind::Unspecified, name)?;
}
}
Ok(buf.finalize())
}
fn kwrite(
&self,
@@ -281,7 +272,7 @@ impl KernelScheme for RootScheme {
match handle {
Handle::Scheme(inner) => inner.write(buf),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(_) => Err(Error::new(EBADF)),
Handle::List { .. } => Err(Error::new(EISDIR)),
}
}
@@ -295,23 +286,14 @@ impl KernelScheme for RootScheme {
buf.copy_exactly(&match handle {
Handle::Scheme(_) => Stat {
st_mode: MODE_FILE,
st_uid: 0,
st_gid: 0,
st_size: 0,
..Default::default()
},
Handle::File(_) => Stat {
st_mode: MODE_FILE,
st_uid: 0,
st_gid: 0,
st_size: 0,
..Default::default()
},
Handle::Folder(inner) => Stat {
Handle::List { .. } => Stat {
st_mode: MODE_DIR,
st_uid: 0,
st_gid: 0,
st_size: inner.data.len() as u64,
..Default::default()
},
})?;
+57 -51
View File
@@ -1,3 +1,7 @@
use ::syscall::{
dirent::{DirentBuf, DirentKind},
EIO, EISDIR, ENOTDIR,
};
use alloc::{collections::BTreeMap, vec::Vec};
use core::{
str,
@@ -31,10 +35,9 @@ mod scheme_num;
mod syscall;
mod uname;
struct Handle {
path: &'static str,
data: Vec<u8>,
mode: u16,
enum Handle {
TopLevel,
Resource { path: &'static str, data: Vec<u8> },
}
type SysFn = fn() -> Result<Vec<u8>>;
@@ -74,23 +77,9 @@ impl KernelScheme for SysScheme {
let path = path.trim_matches('/');
if path.is_empty() {
let mut data = Vec::new();
for entry in FILES.iter() {
if !data.is_empty() {
data.push(b'\n');
}
data.extend_from_slice(entry.0.as_bytes());
}
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write().insert(
id,
Handle {
path: "",
data,
mode: MODE_DIR | 0o444,
},
);
HANDLES.write().insert(id, Handle::TopLevel);
return Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED));
} else {
//Have to iterate to get the path without allocation
@@ -100,10 +89,9 @@ impl KernelScheme for SysScheme {
let data = entry.1()?;
HANDLES.write().insert(
id,
Handle {
Handle::Resource {
path: entry.0,
data,
mode: MODE_FILE | 0o444,
},
);
return Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED));
@@ -115,32 +103,28 @@ impl KernelScheme for SysScheme {
}
fn fsize(&self, id: usize) -> Result<u64> {
let mut handles = HANDLES.write();
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
Ok(handle.data.len() as u64)
}
fn fsync(&self, _id: usize) -> Result<()> {
Ok(())
match HANDLES.read().get(&id).ok_or(Error::new(EBADF))? {
Handle::TopLevel => Ok(0),
Handle::Resource { data, .. } => Ok(data.len() as u64),
}
}
fn close(&self, id: usize) -> Result<()> {
HANDLES
.write()
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(()))
HANDLES.write().remove(&id).ok_or(Error::new(EBADF))?;
Ok(())
}
fn kfpath(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
let handles = HANDLES.read();
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let path = match handles.get(&id).ok_or(Error::new(EBADF))? {
Handle::TopLevel => "",
Handle::Resource { path, .. } => path,
};
const FIRST: &[u8] = b"sys:";
let mut bytes_read = buf.copy_common_bytes_from_slice(FIRST)?;
if let Some(remaining) = buf.advance(FIRST.len()) {
bytes_read += remaining.copy_common_bytes_from_slice(handle.path.as_bytes())?;
bytes_read += remaining.copy_common_bytes_from_slice(path.as_bytes())?;
}
Ok(bytes_read)
@@ -157,25 +141,47 @@ impl KernelScheme for SysScheme {
return Ok(0);
};
let mut handles = HANDLES.write();
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
match HANDLES.read().get(&id).ok_or(Error::new(EBADF))? {
Handle::TopLevel => return Err(Error::new(EISDIR)),
Handle::Resource { data, .. } => {
let avail_buf = data.get(pos..).unwrap_or(&[]);
let avail_buf = handle.data.get(pos..).unwrap_or(&[]);
buffer.copy_common_bytes_from_slice(avail_buf)
buffer.copy_common_bytes_from_slice(avail_buf)
}
}
}
fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result<usize> {
match HANDLES.read().get(&id).ok_or(Error::new(EBADF))? {
Handle::Resource { .. } => return Err(Error::new(ENOTDIR)),
Handle::TopLevel => {
let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?;
for (name, _) in FILES {
buf.entry(DirentKind::Regular, name)?;
}
Ok(buf.finalize())
}
}
}
fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> {
let handles = HANDLES.read();
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let stat = match HANDLES.read().get(&id).ok_or(Error::new(EBADF))? {
Handle::Resource { data, .. } => Stat {
st_mode: 0o444 | MODE_FILE,
st_uid: 0,
st_gid: 0,
st_size: data.len() as u64,
..Default::default()
},
Handle::TopLevel => Stat {
st_mode: 0o444 | MODE_DIR,
st_uid: 0,
st_gid: 0,
st_size: 0,
..Default::default()
},
};
buf.copy_exactly(&Stat {
st_mode: handle.mode,
st_uid: 0,
st_gid: 0,
st_size: handle.data.len() as u64,
..Default::default()
})?;
buf.copy_exactly(&stat)?;
Ok(())
}
+23
View File
@@ -769,6 +769,18 @@ impl UserInner {
gid: (sqe.args[3] >> 32) as u32, // offset hi
});
}
Opcode::Getdents => {
return Ok(Packet {
id: u64::from(sqe.tag) + 1,
pid: sqe.caller as usize,
a: SYS_GETDENTS,
b: sqe.args[0] as usize,
c: sqe.args[1] as usize,
d: sqe.args[2] as usize,
uid: sqe.args[3] as u32,
gid: (sqe.args[3] >> 32) as u32,
});
}
Opcode::Mremap => SYS_MREMAP,
Opcode::Msync => KSMSG_MSYNC,
@@ -1542,6 +1554,17 @@ impl KernelScheme for UserScheme {
address.release()?;
result
}
fn getdents(&self, file: usize, stat: UserSliceWo, header_size: u16) -> Result<usize> {
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
let address = inner.capture_user(stat)?;
let result = inner.call(
Opcode::Getdents,
[file, address.base(), address.len(), header_size.into()],
address.span(),
);
address.release()?;
result
}
fn kfstat(&self, file: usize, stat: UserSliceWo) -> Result<()> {
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
let address = inner.capture_user(stat)?;
+1 -1
View File
@@ -219,7 +219,7 @@ impl SyscallDebugInfo {
}
#[cfg(feature = "syscall_debug")]
pub fn debug_start([a, b, c, d, e, f]: [usize; 6]) {
let do_debug = if crate::context::current().read().name.contains("sigchld") {
let do_debug = if false && crate::context::current().read().name.contains("acpid") {
if a == SYS_CLOCK_GETTIME || a == SYS_YIELD || a == SYS_FUTEX {
false
} else if (a == SYS_WRITE || a == SYS_FSYNC) && (b == 1 || b == 2) {
+15 -1
View File
@@ -4,7 +4,9 @@
extern crate syscall;
use syscall::{RwFlags, EINVAL, SIGKILL};
use core::mem::size_of;
use syscall::{dirent::DirentHeader, RwFlags, EINVAL, SIGKILL};
pub use self::syscall::{
data, error, flag, io, number, ptrace_event, EnvRegisters, FloatRegisters, IntRegisters,
@@ -103,6 +105,18 @@ pub fn syscall(
})
}
}
SYS_GETDENTS => {
let header_size = u16::try_from(e).map_err(|_| Error::new(EINVAL))?;
if usize::from(header_size) != size_of::<DirentHeader>() {
// TODO: allow? If so, zero_out must be implemented for UserSlice
return Err(Error::new(EINVAL));
}
file_op_generic(fd, |scheme, number| {
scheme.getdents(number, UserSlice::wo(c, d)?, header_size)
})
}
SYS_FUTIMENS => file_op_generic(fd, |scheme, number| {
scheme.kfutimens(number, UserSlice::ro(c, d)?)
}),
+21
View File
@@ -1,3 +1,5 @@
use syscall::dirent::Buffer;
use crate::{
memory::PAGE_SIZE,
paging::{Page, VirtualAddress},
@@ -231,3 +233,22 @@ pub fn validate_region(address: usize, size: usize) -> Result<(Page, usize)> {
size / PAGE_SIZE,
))
}
impl Buffer<'static> for UserSliceWo {
fn empty() -> Self {
UserSliceWo::empty()
}
fn length(&self) -> usize {
self.len()
}
fn split_at(self, index: usize) -> Option<[Self; 2]> {
let (a, b) = self.split_at(index)?;
Some([a, b])
}
fn copy_from_slice_exact(self, src: &[u8]) -> Result<()> {
self.copy_exactly(src)
}
fn zero_out(self) -> Result<()> {
// TODO: Implement this. Don't need to as long as the header size is constant, for now.
Ok(())
}
}
+1 -1
Submodule syscall updated: 227f7fd487...c043410366
+1 -1
View File
@@ -10,7 +10,7 @@
"vendor": "unknown",
"linker": "rust-lld",
"linker-flavor": "gnu-lld",
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float",
"dynamic-linking": false,
"executables": true,
"relocation-model": "static",