@@ -33,6 +33,9 @@ pub trait FileSystem {
33
33
///
34
34
/// [`DirEmitter::pos`] holds the current position of the directory reader.
35
35
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 > > > ;
36
39
}
37
40
38
41
/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -226,8 +229,7 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
226
229
let mode = match params. typ {
227
230
INodeType :: Dir => {
228
231
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 ;
231
233
bindings:: S_IFDIR
232
234
}
233
235
} ;
@@ -530,6 +532,62 @@ impl<T: FileSystem + ?Sized> Tables<T> {
530
532
}
531
533
} )
532
534
}
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
+ }
533
591
}
534
592
535
593
/// Directory entry emitter.
@@ -637,6 +695,9 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
637
695
/// fn read_dir(_: &INode<Self>, _: &mut DirEmitter) -> Result {
638
696
/// todo!()
639
697
/// }
698
+ /// fn lookup(_: &INode<Self>, _: &[u8]) -> Result<ARef<INode<Self>>> {
699
+ /// todo!()
700
+ /// }
640
701
/// }
641
702
/// # }
642
703
/// ```
0 commit comments