[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