diff --git a/src/scheme/sys/iostat.rs b/src/scheme/sys/iostat.rs index a976ff2972..306b5db8b4 100644 --- a/src/scheme/sys/iostat.rs +++ b/src/scheme/sys/iostat.rs @@ -1,9 +1,22 @@ -use crate::{context, scheme, syscall::error::Result}; -use alloc::{string::String, vec::Vec}; -use core::fmt::Write; +use crate::{ + context::{ + self, + memory::{Grant, PageSpan}, + }, + paging::PAGE_SIZE, + scheme, + syscall::{ + error::Result, + flag::MapFlags, + usercopy::{UserSlice, UserSliceRw}, + }, +}; +use alloc::{string::String, sync::Arc, vec::Vec}; +use core::{fmt::Write, num::NonZeroUsize, str}; -pub fn resource() -> Result> { +fn inner(fpath_user: UserSliceRw) -> Result> { let mut string = String::new(); + let mut fpath_kernel = [0; PAGE_SIZE]; { let mut rows = Vec::new(); @@ -31,39 +44,72 @@ pub fn resource() -> Result> { let description = file.description.read(); - let _scheme = { + let _ = write!( + string, + " {:>4}: {:>8} {:>8} {:>08X}: ", + fd, + description.scheme.get(), + description.number, + description.flags + ); + + let scheme = { let schemes = scheme::schemes(); match schemes.get(description.scheme) { Some(scheme) => scheme.clone(), None => { - let _ = writeln!( - string, - " {:>4}: {:>8} {:>8} {:>08X}: no scheme", - fd, - description.scheme.get(), - description.number, - description.flags - ); + let _ = writeln!(string, "no scheme",); continue; } } }; - /* - let mut fpath = [0; 4096]; - match scheme.fpath(description.number, &mut fpath) { + match scheme.kfpath(description.number, fpath_user.reinterpret_unchecked()) { Ok(path_len) => { - let fname = str::from_utf8(&fpath[..path_len]).unwrap_or("?"); - let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, description.scheme.get(), description.number, description.flags, fname); - }, + fpath_user.copy_to_slice(&mut fpath_kernel)?; + let fname = str::from_utf8(&fpath_kernel[..path_len]).unwrap_or("?"); + let _ = writeln!(string, "{}", fname); + } Err(err) => { - let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, description.scheme.get(), description.number, description.flags, err); + let _ = writeln!(string, "{}", err); } } - */ } } } Ok(string.into_bytes()) } + +pub fn resource() -> Result> { + let page_count = NonZeroUsize::new(1).unwrap(); + let fpath_page = { + let addr_space = Arc::clone(context::current().read().addr_space()?); + addr_space.acquire_write().mmap( + &addr_space, + None, + page_count, + MapFlags::PROT_READ | MapFlags::PROT_WRITE, + &mut Vec::new(), + |page, flags, mapper, flusher| { + let shared = false; + Ok(Grant::zeroed( + PageSpan::new(page, page_count.get()), + flags, + mapper, + flusher, + shared, + )?) + }, + )? + }; + + let res = UserSlice::rw(fpath_page.start_address().data(), PAGE_SIZE).and_then(inner); + + { + let addr_space = Arc::clone(context::current().read().addr_space()?); + addr_space.munmap(PageSpan::new(fpath_page, page_count.get()), false)?; + } + + res +}