@@ -33,6 +33,9 @@ pub trait FileSystem {
3333 ///
3434 /// [`DirEmitter::pos`] holds the current position of the directory reader.
3535 fn read_dir ( inode : & INode < Self > , emitter : & mut DirEmitter ) -> Result ;
36+
37+ /// Returns the inode corresponding to the directory entry with the given name.
38+ fn lookup ( parent : & INode < Self > , name : & [ u8 ] ) -> Result < ARef < INode < Self > > > ;
3639}
3740
3841/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -226,8 +229,7 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
226229 let mode = match params. typ {
227230 INodeType :: Dir => {
228231 inode. __bindgen_anon_3 . i_fop = & Tables :: < T > :: DIR_FILE_OPERATIONS ;
229- // SAFETY: `simple_dir_inode_operations` never changes, it's safe to reference it.
230- inode. i_op = unsafe { & bindings:: simple_dir_inode_operations } ;
232+ inode. i_op = & Tables :: < T > :: DIR_INODE_OPERATIONS ;
231233 bindings:: S_IFDIR
232234 }
233235 } ;
@@ -530,6 +532,62 @@ impl<T: FileSystem + ?Sized> Tables<T> {
530532 }
531533 } )
532534 }
535+
536+ const DIR_INODE_OPERATIONS : bindings:: inode_operations = bindings:: inode_operations {
537+ lookup : Some ( Self :: lookup_callback) ,
538+ get_link : None ,
539+ permission : None ,
540+ get_inode_acl : None ,
541+ readlink : None ,
542+ create : None ,
543+ link : None ,
544+ unlink : None ,
545+ symlink : None ,
546+ mkdir : None ,
547+ rmdir : None ,
548+ mknod : None ,
549+ rename : None ,
550+ setattr : None ,
551+ getattr : None ,
552+ listxattr : None ,
553+ fiemap : None ,
554+ update_time : None ,
555+ atomic_open : None ,
556+ tmpfile : None ,
557+ get_acl : None ,
558+ set_acl : None ,
559+ fileattr_set : None ,
560+ fileattr_get : None ,
561+ get_offset_ctx : None ,
562+ } ;
563+
564+ extern "C" fn lookup_callback (
565+ parent_ptr : * mut bindings:: inode ,
566+ dentry : * mut bindings:: dentry ,
567+ _flags : u32 ,
568+ ) -> * mut bindings:: dentry {
569+ // SAFETY: The C API guarantees that `parent_ptr` is a valid inode.
570+ let parent = unsafe { & * parent_ptr. cast :: < INode < T > > ( ) } ;
571+
572+ // SAFETY: The C API guarantees that `dentry` is valid for read. Since the name is
573+ // immutable, it's ok to read its length directly.
574+ let len = unsafe { ( * dentry) . d_name . __bindgen_anon_1 . __bindgen_anon_1 . len } ;
575+ let Ok ( name_len) = usize:: try_from ( len) else {
576+ return ENOENT . to_ptr ( ) ;
577+ } ;
578+
579+ // SAFETY: The C API guarantees that `dentry` is valid for read. Since the name is
580+ // immutable, it's ok to read it directly.
581+ let name = unsafe { core:: slice:: from_raw_parts ( ( * dentry) . d_name . name , name_len) } ;
582+ match T :: lookup ( parent, name) {
583+ Err ( e) => e. to_ptr ( ) ,
584+ // SAFETY: The returned inode is valid and referenced (by the type invariants), so
585+ // it is ok to transfer this increment to `d_splice_alias`.
586+ Ok ( inode) => unsafe {
587+ bindings:: d_splice_alias ( ManuallyDrop :: new ( inode) . 0 . get ( ) , dentry)
588+ } ,
589+ }
590+ }
533591}
534592
535593/// Directory entry emitter.
@@ -637,6 +695,9 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
637695/// fn read_dir(_: &INode<Self>, _: &mut DirEmitter) -> Result {
638696/// todo!()
639697/// }
698+ /// fn lookup(_: &INode<Self>, _: &[u8]) -> Result<ARef<INode<Self>>> {
699+ /// todo!()
700+ /// }
640701/// }
641702/// # }
642703/// ```
0 commit comments