[libos] Rewrite the getdents
This commit is contained in:
parent
48b9c077ed
commit
d2bed6c862
2
deps/sefs
vendored
2
deps/sefs
vendored
@ -1 +1 @@
|
|||||||
Subproject commit c2a1fe48b06cf9cedbad7a51d9cb846706630403
|
Subproject commit 3314355400614c799e237ed1eae5682d27ca1400
|
@ -67,7 +67,7 @@ pub trait File: Debug + Sync + Send + Any {
|
|||||||
return_op_unsupported_error!("set_len")
|
return_op_unsupported_error!("set_len")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
fn iterate_entries(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
return_op_unsupported_error!("iterate_entries")
|
return_op_unsupported_error!("iterate_entries")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ pub fn do_getdents(fd: FileDesc, buf: &mut [u8]) -> Result<usize> {
|
|||||||
getdents_common::<LinuxDirent>(fd, buf)
|
getdents_common::<LinuxDirent>(fd, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getdents_common<T: Dirent>(fd: FileDesc, buf: &mut [u8]) -> Result<usize> {
|
fn getdents_common<T: DirentSerializer>(fd: FileDesc, buf: &mut [u8]) -> Result<usize> {
|
||||||
debug!(
|
debug!(
|
||||||
"getdents: fd: {}, buf: {:?}, buf_size: {}",
|
"getdents: fd: {}, buf: {:?}, buf_size: {}",
|
||||||
fd,
|
fd,
|
||||||
@ -23,17 +23,17 @@ fn getdents_common<T: Dirent>(fd: FileDesc, buf: &mut [u8]) -> Result<usize> {
|
|||||||
return_errno!(ENOTDIR, "");
|
return_errno!(ENOTDIR, "");
|
||||||
}
|
}
|
||||||
let mut writer = DirentBufWriter::<T>::new(buf);
|
let mut writer = DirentBufWriter::<T>::new(buf);
|
||||||
let written_len = file_ref.iterate_entries(&mut writer)?;
|
let _ = file_ref.iterate_entries(&mut writer)?;
|
||||||
Ok(written_len)
|
Ok(writer.written_len())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DirentBufWriter<'a, T: Dirent> {
|
struct DirentBufWriter<'a, T: DirentSerializer> {
|
||||||
buf: &'a mut [u8],
|
buf: &'a mut [u8],
|
||||||
written_len: usize,
|
written_len: usize,
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Dirent> DirentBufWriter<'a, T> {
|
impl<'a, T: DirentSerializer> DirentBufWriter<'a, T> {
|
||||||
fn new(buf: &'a mut [u8]) -> Self {
|
fn new(buf: &'a mut [u8]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
buf,
|
buf,
|
||||||
@ -41,29 +41,38 @@ impl<'a, T: Dirent> DirentBufWriter<'a, T> {
|
|||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Dirent> DirentWriter for DirentBufWriter<'a, T> {
|
pub fn written_len(&self) -> usize {
|
||||||
fn write_entry(&mut self, name: &str, ino: u64, type_: FileType) -> rcore_fs::vfs::Result<()> {
|
|
||||||
let dirent: T = Dirent::new(name, ino, type_);
|
|
||||||
if self.buf.len() - self.written_len < dirent.rec_len() {
|
|
||||||
return Err(FsError::InvalidParam);
|
|
||||||
}
|
|
||||||
dirent
|
|
||||||
.serialize(&mut self.buf[self.written_len..], name, type_)
|
|
||||||
.map_err(|_| FsError::InvalidParam)?;
|
|
||||||
self.written_len += dirent.rec_len();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn written_len(&self) -> usize {
|
|
||||||
self.written_len
|
self.written_len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Dirent: Sync + Send {
|
impl<'a, T: DirentSerializer> DirentVisitor for DirentBufWriter<'a, T> {
|
||||||
fn new(name: &str, ino: u64, type_: FileType) -> Self;
|
fn visit_entry(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
ino: u64,
|
||||||
|
type_: FileType,
|
||||||
|
offset: usize,
|
||||||
|
) -> rcore_fs::vfs::Result<()> {
|
||||||
|
let dirent_serializer = T::new(name, ino, type_, offset);
|
||||||
|
if self.written_len >= self.buf.len() {
|
||||||
|
return Err(FsError::InvalidParam);
|
||||||
|
}
|
||||||
|
dirent_serializer
|
||||||
|
.serialize(&mut self.buf[self.written_len..], name, type_)
|
||||||
|
.map_err(|_| FsError::InvalidParam)?;
|
||||||
|
self.written_len += dirent_serializer.rec_len();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait DirentSerializer: Sync + Send {
|
||||||
|
/// Creates a new DirentSerializer.
|
||||||
|
fn new(name: &str, ino: u64, type_: FileType, offset: usize) -> Self;
|
||||||
|
/// Returns the length.
|
||||||
fn rec_len(&self) -> usize;
|
fn rec_len(&self) -> usize;
|
||||||
|
/// Tries to serialize a directory entry into buffer.
|
||||||
fn serialize(&self, buf: &mut [u8], name: &str, type_: FileType) -> Result<()>;
|
fn serialize(&self, buf: &mut [u8], name: &str, type_: FileType) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,13 +92,13 @@ struct LinuxDirent64 {
|
|||||||
pub name: [u8; 0],
|
pub name: [u8; 0],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dirent for LinuxDirent64 {
|
impl DirentSerializer for LinuxDirent64 {
|
||||||
fn new(name: &str, ino: u64, type_: FileType) -> Self {
|
fn new(name: &str, ino: u64, type_: FileType, offset: usize) -> Self {
|
||||||
let ori_len = core::mem::size_of::<Self>() + name.len() + 1;
|
let ori_len = core::mem::size_of::<Self>() + name.len() + 1;
|
||||||
let len = align_up(ori_len, 8); // align up to 8 bytes
|
let len = align_up(ori_len, 8); // align up to 8 bytes
|
||||||
Self {
|
Self {
|
||||||
ino,
|
ino,
|
||||||
offset: 0,
|
offset: offset as u64,
|
||||||
rec_len: len as u16,
|
rec_len: len as u16,
|
||||||
type_: DirentType::from_file_type(type_),
|
type_: DirentType::from_file_type(type_),
|
||||||
name: [],
|
name: [],
|
||||||
@ -101,6 +110,10 @@ impl Dirent for LinuxDirent64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize(&self, buf: &mut [u8], name: &str, _type_: FileType) -> Result<()> {
|
fn serialize(&self, buf: &mut [u8], name: &str, _type_: FileType) -> Result<()> {
|
||||||
|
if self.rec_len() > buf.len() {
|
||||||
|
return_errno!(EINVAL, "not enough buf");
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = buf.as_mut_ptr() as *mut Self;
|
let ptr = buf.as_mut_ptr() as *mut Self;
|
||||||
ptr.write(*self);
|
ptr.write(*self);
|
||||||
@ -131,14 +144,14 @@ struct LinuxDirent {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dirent for LinuxDirent {
|
impl DirentSerializer for LinuxDirent {
|
||||||
fn new(name: &str, ino: u64, type_: FileType) -> Self {
|
fn new(name: &str, ino: u64, type_: FileType, offset: usize) -> Self {
|
||||||
let ori_len =
|
let ori_len =
|
||||||
core::mem::size_of::<Self>() + name.len() + 1 + core::mem::size_of::<FileType>();
|
core::mem::size_of::<Self>() + name.len() + 1 + core::mem::size_of::<FileType>();
|
||||||
let len = align_up(ori_len, 8); // align up to 8 bytes
|
let len = align_up(ori_len, 8); // align up to 8 bytes
|
||||||
Self {
|
Self {
|
||||||
ino,
|
ino,
|
||||||
offset: 0,
|
offset: offset as u64,
|
||||||
rec_len: len as u16,
|
rec_len: len as u16,
|
||||||
name: [],
|
name: [],
|
||||||
}
|
}
|
||||||
@ -149,6 +162,10 @@ impl Dirent for LinuxDirent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize(&self, buf: &mut [u8], name: &str, type_: FileType) -> Result<()> {
|
fn serialize(&self, buf: &mut [u8], name: &str, type_: FileType) -> Result<()> {
|
||||||
|
if self.rec_len() > buf.len() {
|
||||||
|
return_errno!(EINVAL, "not enough buf");
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = buf.as_mut_ptr() as *mut Self;
|
let ptr = buf.as_mut_ptr() as *mut Self;
|
||||||
ptr.write(*self);
|
ptr.write(*self);
|
||||||
|
@ -250,32 +250,41 @@ impl INode for HNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, ctx: &mut DirentWriterContext) -> Result<usize> {
|
fn iterate_entries(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
if !self.is_dir() {
|
if !self.is_dir() {
|
||||||
return Err(FsError::NotDir);
|
return Err(FsError::NotDir);
|
||||||
}
|
}
|
||||||
let idx = ctx.pos();
|
|
||||||
for entry in try_std!(self.path.read_dir()).skip(idx) {
|
let try_iterate = |offset: &mut usize, visitor: &mut dyn DirentVisitor| -> Result<()> {
|
||||||
let entry = try_std!(entry);
|
let start_offset = *offset;
|
||||||
if let Err(e) = ctx.write_entry(
|
for (idx, entry) in try_std!(self.path.read_dir())
|
||||||
&entry
|
.enumerate()
|
||||||
.file_name()
|
.skip_while(|(idx, _)| idx < &start_offset)
|
||||||
.into_string()
|
{
|
||||||
.map_err(|_| FsError::InvalidParam)?,
|
let entry = try_std!(entry);
|
||||||
entry.ino(),
|
visitor.visit_entry(
|
||||||
entry
|
&entry
|
||||||
.file_type()
|
.file_name()
|
||||||
.map_err(|_| FsError::InvalidParam)?
|
.into_string()
|
||||||
.into_fs_filetype(),
|
.map_err(|_| FsError::InvalidParam)?,
|
||||||
) {
|
entry.ino() as u64,
|
||||||
if ctx.written_len() == 0 {
|
entry
|
||||||
return Err(e);
|
.file_type()
|
||||||
} else {
|
.map_err(|_| FsError::InvalidParam)?
|
||||||
break;
|
.into_fs_filetype(),
|
||||||
}
|
idx,
|
||||||
};
|
)?;
|
||||||
|
*offset = idx + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut iterate_offset = offset;
|
||||||
|
match try_iterate(&mut iterate_offset, visitor) {
|
||||||
|
Err(e) if iterate_offset == offset => Err(e),
|
||||||
|
_ => Ok(iterate_offset - offset),
|
||||||
}
|
}
|
||||||
Ok(ctx.written_len())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn io_control(&self, cmd: u32, data: usize) -> Result<()> {
|
fn io_control(&self, cmd: u32, data: usize) -> Result<()> {
|
||||||
|
@ -193,15 +193,14 @@ impl File for INodeFile {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
fn iterate_entries(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
if !self.access_mode.readable() {
|
if !self.access_mode.readable() {
|
||||||
return_errno!(EBADF, "File not readable. Can't read entry.");
|
return_errno!(EBADF, "File not readable. Can't read entry.");
|
||||||
}
|
}
|
||||||
let mut offset = self.offset.lock().unwrap();
|
let mut offset = self.offset.lock().unwrap();
|
||||||
let mut dir_ctx = DirentWriterContext::new(*offset, writer);
|
let visited_len = self.inode.iterate_entries(*offset, visitor)?;
|
||||||
let written_size = self.inode.iterate_entries(&mut dir_ctx)?;
|
*offset += visited_len;
|
||||||
*offset = dir_ctx.pos();
|
Ok(visited_len)
|
||||||
Ok(written_size)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access_mode(&self) -> Result<AccessMode> {
|
fn access_mode(&self) -> Result<AccessMode> {
|
||||||
|
@ -2,8 +2,7 @@ use super::*;
|
|||||||
|
|
||||||
use process;
|
use process;
|
||||||
use rcore_fs::vfs::{
|
use rcore_fs::vfs::{
|
||||||
DirentWriter, DirentWriterContext, FileSystem, FileType, FsError, INode, Metadata, Timespec,
|
DirentVisitor, FileSystem, FileType, FsError, INode, Metadata, Timespec, PATH_MAX,
|
||||||
PATH_MAX,
|
|
||||||
};
|
};
|
||||||
use std;
|
use std;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
@ -157,44 +157,51 @@ impl DirProcINode for LockedProcRootINode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, mut ctx: &mut DirentWriterContext) -> vfs::Result<usize> {
|
fn iterate_entries(
|
||||||
|
&self,
|
||||||
|
offset: usize,
|
||||||
|
visitor: &mut dyn DirentVisitor,
|
||||||
|
) -> vfs::Result<usize> {
|
||||||
let file = self.0.read().unwrap();
|
let file = self.0.read().unwrap();
|
||||||
let idx = ctx.pos();
|
|
||||||
|
|
||||||
// Write first two special entries
|
let try_iterate =
|
||||||
if idx == 0 {
|
|mut offset: &mut usize, mut visitor: &mut dyn DirentVisitor| -> vfs::Result<()> {
|
||||||
let this_inode = file.this.upgrade().unwrap();
|
// The two special entries
|
||||||
write_inode_entry!(&mut ctx, ".", &this_inode);
|
if *offset == 0 {
|
||||||
}
|
let this_inode = file.this.upgrade().unwrap();
|
||||||
if idx <= 1 {
|
rcore_fs::visit_inode_entry!(&mut visitor, ".", &this_inode, &mut offset);
|
||||||
let parent_inode = file.this.upgrade().unwrap();
|
}
|
||||||
write_inode_entry!(&mut ctx, "..", &parent_inode);
|
if *offset == 1 {
|
||||||
}
|
let parent_inode = file.this.upgrade().unwrap();
|
||||||
|
rcore_fs::visit_inode_entry!(&mut visitor, "..", &parent_inode, &mut offset);
|
||||||
|
}
|
||||||
|
|
||||||
// Write the non volatile entries
|
// The non volatile entries
|
||||||
let skipped = if idx < 2 { 0 } else { idx - 2 };
|
let start_offset = *offset;
|
||||||
for (name, inode) in file.non_volatile_entries.iter().skip(skipped) {
|
for (name, child) in file.non_volatile_entries.iter().skip(start_offset - 2) {
|
||||||
write_inode_entry!(&mut ctx, name, inode);
|
rcore_fs::visit_inode_entry!(&mut visitor, name, child, &mut offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the pid entries
|
// The pid entries
|
||||||
let skipped = {
|
let start_offset = *offset;
|
||||||
let prior_entries_len = 2 + file.non_volatile_entries.len();
|
let skipped_len = 2 + file.non_volatile_entries.len();
|
||||||
if idx < prior_entries_len {
|
for process in get_all_processes().iter().skip(start_offset - skipped_len) {
|
||||||
0
|
rcore_fs::visit_entry!(
|
||||||
} else {
|
&mut visitor,
|
||||||
idx - prior_entries_len
|
&process.pid().to_string(),
|
||||||
}
|
PROC_INO,
|
||||||
};
|
vfs::FileType::Dir,
|
||||||
for process in get_all_processes().iter().skip(skipped) {
|
&mut offset
|
||||||
write_entry!(
|
);
|
||||||
&mut ctx,
|
}
|
||||||
&process.pid().to_string(),
|
|
||||||
PROC_INO,
|
|
||||||
vfs::FileType::Dir
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ctx.written_len())
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut iterate_offset = offset;
|
||||||
|
match try_iterate(&mut iterate_offset, visitor) {
|
||||||
|
Err(e) if iterate_offset == offset => Err(e),
|
||||||
|
_ => Ok(iterate_offset - offset),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,26 +53,45 @@ impl DirProcINode for LockedProcFdDirINode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, mut ctx: &mut DirentWriterContext) -> vfs::Result<usize> {
|
fn iterate_entries(
|
||||||
|
&self,
|
||||||
|
offset: usize,
|
||||||
|
visitor: &mut dyn DirentVisitor,
|
||||||
|
) -> vfs::Result<usize> {
|
||||||
let file = self.0.read().unwrap();
|
let file = self.0.read().unwrap();
|
||||||
let idx = ctx.pos();
|
|
||||||
|
|
||||||
// Write first two special entries
|
let try_iterate =
|
||||||
write_first_two_entries!(idx, &mut ctx, &file);
|
|mut offset: &mut usize, mut visitor: &mut dyn DirentVisitor| -> vfs::Result<()> {
|
||||||
|
// The two special entries
|
||||||
|
visit_first_two_entries!(&mut visitor, &file, &mut offset);
|
||||||
|
|
||||||
// Write the fd entries
|
// The fd entries
|
||||||
let skipped = if idx < 2 { 0 } else { idx - 2 };
|
let main_thread = match file.process_ref.main_thread() {
|
||||||
let main_thread = match file.process_ref.main_thread() {
|
Some(main_thread) => main_thread,
|
||||||
Some(main_thread) => main_thread,
|
None => {
|
||||||
None => {
|
return Ok(());
|
||||||
return Ok(ctx.written_len());
|
}
|
||||||
}
|
};
|
||||||
};
|
let fds = main_thread.files().lock().unwrap().fds();
|
||||||
let fds = main_thread.files().lock().unwrap().fds();
|
let start_offset = *offset;
|
||||||
for fd in fds.iter().skip(skipped) {
|
for fd in fds.iter().skip(start_offset - 2) {
|
||||||
write_entry!(&mut ctx, &fd.to_string(), PROC_INO, vfs::FileType::SymLink);
|
rcore_fs::visit_entry!(
|
||||||
|
&mut visitor,
|
||||||
|
&fd.to_string(),
|
||||||
|
PROC_INO,
|
||||||
|
vfs::FileType::SymLink,
|
||||||
|
&mut offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut iterate_offset = offset;
|
||||||
|
match try_iterate(&mut iterate_offset, visitor) {
|
||||||
|
Err(e) if iterate_offset == offset => Err(e),
|
||||||
|
_ => Ok(iterate_offset - offset),
|
||||||
}
|
}
|
||||||
Ok(ctx.written_len())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,23 +113,42 @@ impl DirProcINode for LockedPidDirINode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, mut ctx: &mut DirentWriterContext) -> vfs::Result<usize> {
|
fn iterate_entries(
|
||||||
|
&self,
|
||||||
|
offset: usize,
|
||||||
|
visitor: &mut dyn DirentVisitor,
|
||||||
|
) -> vfs::Result<usize> {
|
||||||
let file = self.0.read().unwrap();
|
let file = self.0.read().unwrap();
|
||||||
let idx = ctx.pos();
|
|
||||||
|
|
||||||
// Write first two special entries
|
let try_iterate =
|
||||||
write_first_two_entries!(idx, &mut ctx, &file);
|
|mut offset: &mut usize, mut visitor: &mut dyn DirentVisitor| -> vfs::Result<()> {
|
||||||
|
// The two special entries
|
||||||
|
visit_first_two_entries!(&mut visitor, &file, &mut offset);
|
||||||
|
|
||||||
// Write the normal entries
|
// The normal entries
|
||||||
let skipped = if idx < 2 { 0 } else { idx - 2 };
|
let start_offset = *offset;
|
||||||
for (name, inode) in file.entries.iter().skip(skipped) {
|
for (name, child) in file.entries.iter().skip(start_offset - 2) {
|
||||||
write_inode_entry!(&mut ctx, name, inode);
|
rcore_fs::visit_inode_entry!(&mut visitor, name, child, &mut offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The fd entry
|
||||||
|
if *offset == 2 + file.entries.len() {
|
||||||
|
rcore_fs::visit_entry!(
|
||||||
|
&mut visitor,
|
||||||
|
"fd",
|
||||||
|
PROC_INO as u64,
|
||||||
|
vfs::FileType::Dir,
|
||||||
|
&mut offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut iterate_offset = offset;
|
||||||
|
match try_iterate(&mut iterate_offset, visitor) {
|
||||||
|
Err(e) if iterate_offset == offset => Err(e),
|
||||||
|
_ => Ok(iterate_offset - offset),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the fd entry
|
|
||||||
if idx <= 2 + file.entries.len() {
|
|
||||||
write_entry!(&mut ctx, "fd", PROC_INO, vfs::FileType::Dir);
|
|
||||||
}
|
|
||||||
Ok(ctx.written_len())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,12 @@ where
|
|||||||
self.inner().get_entry(id)
|
self.inner().get_entry(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, ctx: &mut DirentWriterContext) -> vfs::Result<usize> {
|
fn iterate_entries(
|
||||||
self.inner().iterate_entries(ctx)
|
&self,
|
||||||
|
offset: usize,
|
||||||
|
visitor: &mut dyn DirentVisitor,
|
||||||
|
) -> vfs::Result<usize> {
|
||||||
|
self.inner().iterate_entries(offset, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any_ref(&self) -> &dyn Any {
|
fn as_any_ref(&self) -> &dyn Any {
|
||||||
|
@ -15,7 +15,8 @@ pub trait ProcINode {
|
|||||||
pub trait DirProcINode {
|
pub trait DirProcINode {
|
||||||
fn find(&self, name: &str) -> vfs::Result<Arc<dyn INode>>;
|
fn find(&self, name: &str) -> vfs::Result<Arc<dyn INode>>;
|
||||||
fn get_entry(&self, id: usize) -> vfs::Result<String>;
|
fn get_entry(&self, id: usize) -> vfs::Result<String>;
|
||||||
fn iterate_entries(&self, ctx: &mut DirentWriterContext) -> vfs::Result<usize>;
|
fn iterate_entries(&self, offset: usize, visitor: &mut dyn DirentVisitor)
|
||||||
|
-> vfs::Result<usize>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@ -54,7 +55,11 @@ macro_rules! impl_inode_for_file_or_symlink {
|
|||||||
Err(FsError::NotDir)
|
Err(FsError::NotDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, ctx: &mut DirentWriterContext) -> vfs::Result<usize> {
|
fn iterate_entries(
|
||||||
|
&self,
|
||||||
|
offset: usize,
|
||||||
|
visitor: &mut dyn DirentVisitor,
|
||||||
|
) -> vfs::Result<usize> {
|
||||||
Err(FsError::NotDir)
|
Err(FsError::NotDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,47 +70,19 @@ macro_rules! impl_inode_for_file_or_symlink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! write_first_two_entries {
|
macro_rules! visit_first_two_entries {
|
||||||
($idx: expr, $ctx:expr, $file:expr) => {
|
($visitor:expr, $file:expr, $offset: expr) => {
|
||||||
let idx = $idx;
|
use rcore_fs::visit_inode_entry;
|
||||||
let file = $file;
|
let file = $file;
|
||||||
|
|
||||||
if idx == 0 {
|
let offset = **$offset;
|
||||||
|
if offset == 0 {
|
||||||
let this_inode = file.this.upgrade().unwrap();
|
let this_inode = file.this.upgrade().unwrap();
|
||||||
write_inode_entry!($ctx, ".", &this_inode);
|
visit_inode_entry!($visitor, ".", &this_inode, $offset);
|
||||||
}
|
}
|
||||||
if idx <= 1 {
|
let offset = **$offset;
|
||||||
write_inode_entry!($ctx, "..", &file.parent);
|
if offset == 1 {
|
||||||
}
|
visit_inode_entry!($visitor, "..", &file.parent, $offset);
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! write_inode_entry {
|
|
||||||
($ctx:expr, $name:expr, $inode:expr) => {
|
|
||||||
let ctx = $ctx;
|
|
||||||
let name = $name;
|
|
||||||
let ino = $inode.metadata()?.inode;
|
|
||||||
let type_ = $inode.metadata()?.type_;
|
|
||||||
|
|
||||||
write_entry!(ctx, name, ino, type_);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! write_entry {
|
|
||||||
($ctx:expr, $name:expr, $ino:expr, $type_:expr) => {
|
|
||||||
let ctx = $ctx;
|
|
||||||
let name = $name;
|
|
||||||
let ino = $ino;
|
|
||||||
let type_ = $type_;
|
|
||||||
|
|
||||||
if let Err(e) = ctx.write_entry(name, ino as u64, type_) {
|
|
||||||
if ctx.written_len() == 0 {
|
|
||||||
return Err(e);
|
|
||||||
} else {
|
|
||||||
return Ok(ctx.written_len());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user