@@ -22,7 +22,8 @@ mod group_desc;
2222
2323use core:: mem:: MaybeUninit ;
2424
25- use aero_syscall:: MMapFlags ;
25+ use aero_syscall:: socket:: MessageHeader ;
26+ use aero_syscall:: { MMapFlags , SyscallError } ;
2627use alloc:: boxed:: Box ;
2728use alloc:: string:: ToString ;
2829use alloc:: sync:: { Arc , Weak } ;
@@ -33,28 +34,39 @@ use crate::fs::cache::CachedINode;
3334use crate :: fs:: ext2:: disk:: { FileType , SuperBlock } ;
3435use crate :: mem:: paging:: { FrameAllocator , PhysFrame , FRAME_ALLOCATOR } ;
3536
37+ use crate :: socket:: unix:: UnixSocket ;
38+ use crate :: socket:: SocketAddr ;
39+
3640use self :: group_desc:: GroupDescriptors ;
3741
3842use super :: block:: { BlockDevice , CachedAccess } ;
3943
4044use super :: cache:: { DirCacheItem , INodeCacheItem } ;
4145use super :: { cache, FileSystemError } ;
4246
43- use super :: inode:: { DirEntry , INodeInterface , Metadata } ;
47+ use super :: inode:: { DirEntry , INodeInterface , Metadata , PollFlags , PollTable } ;
4448use super :: FileSystem ;
4549
4650pub struct INode {
4751 id : usize ,
4852 fs : Weak < Ext2 > ,
4953 inode : RwLock < Box < disk:: INode > > ,
54+ // Forwards all of the inode operations to the proxy inode. Note that the
55+ // proxy inode is not saved on the disk. (e.g. This is useful for binding
56+ // a socket inode to a file).
57+ proxy : Option < Arc < dyn INodeInterface > > ,
5058
5159 // TODO: Do not store this in the inode, but rather in a different
5260 // cache using the API provided by fs::cache (consider LRU only?).
5361 sref : Weak < INode > ,
5462}
5563
5664impl INode {
57- pub fn new ( ext2 : Weak < Ext2 > , id : usize ) -> Option < INodeCacheItem > {
65+ pub fn new (
66+ ext2 : Weak < Ext2 > ,
67+ id : usize ,
68+ proxy : Option < Arc < dyn INodeInterface > > ,
69+ ) -> Option < INodeCacheItem > {
5870 debug_assert ! ( id != 0 ) ;
5971
6072 let icache = cache:: icache ( ) ;
@@ -71,6 +83,7 @@ impl INode {
7183 inode : RwLock :: new ( inode) ,
7284 id,
7385 fs : ext2,
86+ proxy,
7487
7588 sref : sref. clone ( ) ,
7689 } ) ) ) ,
@@ -229,7 +242,12 @@ impl INode {
229242 todo ! ( "triply indirect block" )
230243 }
231244
232- pub fn make_inode ( & self , name : & str , typ : FileType ) -> super :: Result < INodeCacheItem > {
245+ pub fn make_inode (
246+ & self ,
247+ name : & str ,
248+ typ : FileType ,
249+ proxy : Option < Arc < dyn INodeInterface > > ,
250+ ) -> super :: Result < INodeCacheItem > {
233251 if !self . metadata ( ) ?. is_directory ( ) {
234252 return Err ( FileSystemError :: NotSupported ) ;
235253 }
@@ -246,6 +264,8 @@ impl INode {
246264 let fs = self . fs . upgrade ( ) . expect ( "ext2: filesystem was dropped" ) ;
247265
248266 let inode = fs. bgdt . alloc_inode ( ) . expect ( "ext2: out of inodes" ) ;
267+ let inode = fs. find_inode ( inode, proxy) . expect ( "ext2: inode not found" ) ;
268+
249269 let ext2_inode = inode. downcast_arc :: < INode > ( ) . expect ( "ext2: invalid inode" ) ;
250270
251271 {
@@ -284,7 +304,7 @@ impl INode {
284304 name : & str ,
285305 entry : & disk:: DirEntry ,
286306 ) -> Option < DirCacheItem > {
287- let inode = self . fs . upgrade ( ) ?. find_inode ( entry. inode as usize ) ?;
307+ let inode = self . fs . upgrade ( ) ?. find_inode ( entry. inode as usize , None ) ?;
288308 Some ( DirEntry :: new ( parent, inode, name. to_string ( ) ) )
289309 }
290310
@@ -358,6 +378,10 @@ impl INodeInterface for INode {
358378 }
359379
360380 fn read_at ( & self , offset : usize , usr_buffer : & mut [ u8 ] ) -> super :: Result < usize > {
381+ if let Some ( proxy) = self . proxy . as_ref ( ) {
382+ return proxy. read_at ( offset, usr_buffer) ;
383+ }
384+
361385 if !self . metadata ( ) ?. is_file ( ) {
362386 return Err ( FileSystemError :: NotSupported ) ;
363387 }
@@ -374,6 +398,10 @@ impl INodeInterface for INode {
374398 }
375399
376400 fn write_at ( & self , offset : usize , usr_buffer : & [ u8 ] ) -> super :: Result < usize > {
401+ if let Some ( proxy) = self . proxy . as_ref ( ) {
402+ return proxy. write_at ( offset, usr_buffer) ;
403+ }
404+
377405 if !self . metadata ( ) ?. is_file ( ) && !self . metadata ( ) ?. is_symlink ( ) {
378406 return Err ( FileSystemError :: NotSupported ) ;
379407 }
@@ -390,23 +418,40 @@ impl INodeInterface for INode {
390418 return Err ( FileSystemError :: NotSupported ) ;
391419 }
392420
393- let inode = self . make_inode ( name, FileType :: Symlink ) ?;
421+ let inode = self . make_inode ( name, FileType :: Symlink , None ) ?;
394422 inode. write_at ( 0 , src. name ( ) . as_bytes ( ) ) ?;
395423
396424 Ok ( ( ) )
397425 }
398426
399427 fn truncate ( & self , _size : usize ) -> super :: Result < ( ) > {
428+ log:: warn!( "ext2::truncate is a stub!" ) ;
400429 Ok ( ( ) )
401430 }
402431
403432 fn touch ( & self , parent : DirCacheItem , name : & str ) -> super :: Result < DirCacheItem > {
404- let inode = self . make_inode ( name, FileType :: File ) ?;
433+ if !self . metadata ( ) ?. is_directory ( ) {
434+ return Err ( FileSystemError :: NotSupported ) ;
435+ }
436+
437+ let inode = self . make_inode ( name, FileType :: File , None ) ?;
405438 Ok ( DirEntry :: new ( parent, inode, name. to_string ( ) ) )
406439 }
407440
408441 fn mkdir ( & self , name : & str ) -> super :: Result < INodeCacheItem > {
409- self . make_inode ( name, FileType :: Directory )
442+ if !self . metadata ( ) ?. is_directory ( ) {
443+ return Err ( FileSystemError :: NotSupported ) ;
444+ }
445+
446+ self . make_inode ( name, FileType :: Directory , None )
447+ }
448+
449+ fn make_local_socket_inode (
450+ & self ,
451+ name : & str ,
452+ inode : Arc < dyn INodeInterface > ,
453+ ) -> super :: Result < INodeCacheItem > {
454+ Ok ( self . make_inode ( name, FileType :: Socket , Some ( inode) ) ?)
410455 }
411456
412457 fn resolve_link ( & self ) -> super :: Result < String > {
@@ -428,6 +473,8 @@ impl INodeInterface for INode {
428473 }
429474
430475 fn mmap ( & self , offset : usize , size : usize , flags : MMapFlags ) -> super :: Result < PhysFrame > {
476+ assert ! ( self . proxy. is_none( ) ) ;
477+
431478 // TODO: support shared file mappings.
432479 assert ! ( !flags. contains( MMapFlags :: MAP_SHARED ) ) ;
433480
@@ -438,6 +485,49 @@ impl INodeInterface for INode {
438485
439486 Ok ( private_cp)
440487 }
488+
489+ fn listen ( & self , backlog : usize ) -> Result < ( ) , SyscallError > {
490+ if let Some ( proxy) = self . proxy . as_ref ( ) {
491+ return proxy. listen ( backlog) ;
492+ }
493+
494+ return Err ( SyscallError :: EACCES ) ;
495+ }
496+
497+ // XXX: We do not require to handle `bind` here since if this function
498+ // is being is called on an EXT2 inode then, it has already been bound.
499+
500+ fn connect ( & self , address : SocketAddr , length : usize ) -> super :: Result < ( ) > {
501+ if let Some ( proxy) = self . proxy . as_ref ( ) {
502+ return proxy. connect ( address, length) ;
503+ }
504+
505+ return Err ( FileSystemError :: NotSupported ) ;
506+ }
507+
508+ fn accept ( & self , address : Option < & mut SocketAddr > ) -> super :: Result < Arc < UnixSocket > > {
509+ if let Some ( proxy) = self . proxy . as_ref ( ) {
510+ return proxy. accept ( address) ;
511+ }
512+
513+ return Err ( FileSystemError :: NotSupported ) ;
514+ }
515+
516+ fn recv ( & self , message_header : & mut MessageHeader ) -> super :: Result < usize > {
517+ if let Some ( proxy) = self . proxy . as_ref ( ) {
518+ return proxy. recv ( message_header) ;
519+ }
520+
521+ return Err ( FileSystemError :: NotSupported ) ;
522+ }
523+
524+ fn poll ( & self , table : Option < & mut PollTable > ) -> super :: Result < PollFlags > {
525+ if let Some ( proxy) = self . proxy . as_ref ( ) {
526+ return proxy. poll ( table) ;
527+ }
528+
529+ return Err ( FileSystemError :: NotSupported ) ;
530+ }
441531}
442532
443533pub struct DirEntryIter {
@@ -526,15 +616,19 @@ impl Ext2 {
526616 } ) )
527617 }
528618
529- pub fn find_inode ( & self , id : usize ) -> Option < INodeCacheItem > {
530- INode :: new ( self . sref . clone ( ) , id)
619+ pub fn find_inode (
620+ & self ,
621+ id : usize ,
622+ proxy : Option < Arc < dyn INodeInterface > > ,
623+ ) -> Option < INodeCacheItem > {
624+ INode :: new ( self . sref . clone ( ) , id, proxy)
531625 }
532626}
533627
534628impl FileSystem for Ext2 {
535629 fn root_dir ( & self ) -> DirCacheItem {
536630 let inode = self
537- . find_inode ( Ext2 :: ROOT_INODE_ID )
631+ . find_inode ( Ext2 :: ROOT_INODE_ID , None )
538632 . expect ( "ext2: invalid filesystem (root inode not found)" ) ;
539633
540634 DirEntry :: new_root ( inode, String :: from ( "/" ) )
0 commit comments