@@ -22,7 +22,8 @@ mod group_desc;
22
22
23
23
use core:: mem:: MaybeUninit ;
24
24
25
- use aero_syscall:: MMapFlags ;
25
+ use aero_syscall:: socket:: MessageHeader ;
26
+ use aero_syscall:: { MMapFlags , SyscallError } ;
26
27
use alloc:: boxed:: Box ;
27
28
use alloc:: string:: ToString ;
28
29
use alloc:: sync:: { Arc , Weak } ;
@@ -33,28 +34,39 @@ use crate::fs::cache::CachedINode;
33
34
use crate :: fs:: ext2:: disk:: { FileType , SuperBlock } ;
34
35
use crate :: mem:: paging:: { FrameAllocator , PhysFrame , FRAME_ALLOCATOR } ;
35
36
37
+ use crate :: socket:: unix:: UnixSocket ;
38
+ use crate :: socket:: SocketAddr ;
39
+
36
40
use self :: group_desc:: GroupDescriptors ;
37
41
38
42
use super :: block:: { BlockDevice , CachedAccess } ;
39
43
40
44
use super :: cache:: { DirCacheItem , INodeCacheItem } ;
41
45
use super :: { cache, FileSystemError } ;
42
46
43
- use super :: inode:: { DirEntry , INodeInterface , Metadata } ;
47
+ use super :: inode:: { DirEntry , INodeInterface , Metadata , PollFlags , PollTable } ;
44
48
use super :: FileSystem ;
45
49
46
50
pub struct INode {
47
51
id : usize ,
48
52
fs : Weak < Ext2 > ,
49
53
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 > > ,
50
58
51
59
// TODO: Do not store this in the inode, but rather in a different
52
60
// cache using the API provided by fs::cache (consider LRU only?).
53
61
sref : Weak < INode > ,
54
62
}
55
63
56
64
impl 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 > {
58
70
debug_assert ! ( id != 0 ) ;
59
71
60
72
let icache = cache:: icache ( ) ;
@@ -71,6 +83,7 @@ impl INode {
71
83
inode : RwLock :: new ( inode) ,
72
84
id,
73
85
fs : ext2,
86
+ proxy,
74
87
75
88
sref : sref. clone ( ) ,
76
89
} ) ) ) ,
@@ -229,7 +242,12 @@ impl INode {
229
242
todo ! ( "triply indirect block" )
230
243
}
231
244
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 > {
233
251
if !self . metadata ( ) ?. is_directory ( ) {
234
252
return Err ( FileSystemError :: NotSupported ) ;
235
253
}
@@ -246,6 +264,8 @@ impl INode {
246
264
let fs = self . fs . upgrade ( ) . expect ( "ext2: filesystem was dropped" ) ;
247
265
248
266
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
+
249
269
let ext2_inode = inode. downcast_arc :: < INode > ( ) . expect ( "ext2: invalid inode" ) ;
250
270
251
271
{
@@ -284,7 +304,7 @@ impl INode {
284
304
name : & str ,
285
305
entry : & disk:: DirEntry ,
286
306
) -> 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 ) ?;
288
308
Some ( DirEntry :: new ( parent, inode, name. to_string ( ) ) )
289
309
}
290
310
@@ -358,6 +378,10 @@ impl INodeInterface for INode {
358
378
}
359
379
360
380
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
+
361
385
if !self . metadata ( ) ?. is_file ( ) {
362
386
return Err ( FileSystemError :: NotSupported ) ;
363
387
}
@@ -374,6 +398,10 @@ impl INodeInterface for INode {
374
398
}
375
399
376
400
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
+
377
405
if !self . metadata ( ) ?. is_file ( ) && !self . metadata ( ) ?. is_symlink ( ) {
378
406
return Err ( FileSystemError :: NotSupported ) ;
379
407
}
@@ -390,23 +418,40 @@ impl INodeInterface for INode {
390
418
return Err ( FileSystemError :: NotSupported ) ;
391
419
}
392
420
393
- let inode = self . make_inode ( name, FileType :: Symlink ) ?;
421
+ let inode = self . make_inode ( name, FileType :: Symlink , None ) ?;
394
422
inode. write_at ( 0 , src. name ( ) . as_bytes ( ) ) ?;
395
423
396
424
Ok ( ( ) )
397
425
}
398
426
399
427
fn truncate ( & self , _size : usize ) -> super :: Result < ( ) > {
428
+ log:: warn!( "ext2::truncate is a stub!" ) ;
400
429
Ok ( ( ) )
401
430
}
402
431
403
432
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 ) ?;
405
438
Ok ( DirEntry :: new ( parent, inode, name. to_string ( ) ) )
406
439
}
407
440
408
441
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) ) ?)
410
455
}
411
456
412
457
fn resolve_link ( & self ) -> super :: Result < String > {
@@ -428,6 +473,8 @@ impl INodeInterface for INode {
428
473
}
429
474
430
475
fn mmap ( & self , offset : usize , size : usize , flags : MMapFlags ) -> super :: Result < PhysFrame > {
476
+ assert ! ( self . proxy. is_none( ) ) ;
477
+
431
478
// TODO: support shared file mappings.
432
479
assert ! ( !flags. contains( MMapFlags :: MAP_SHARED ) ) ;
433
480
@@ -438,6 +485,49 @@ impl INodeInterface for INode {
438
485
439
486
Ok ( private_cp)
440
487
}
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
+ }
441
531
}
442
532
443
533
pub struct DirEntryIter {
@@ -526,15 +616,19 @@ impl Ext2 {
526
616
} ) )
527
617
}
528
618
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)
531
625
}
532
626
}
533
627
534
628
impl FileSystem for Ext2 {
535
629
fn root_dir ( & self ) -> DirCacheItem {
536
630
let inode = self
537
- . find_inode ( Ext2 :: ROOT_INODE_ID )
631
+ . find_inode ( Ext2 :: ROOT_INODE_ID , None )
538
632
. expect ( "ext2: invalid filesystem (root inode not found)" ) ;
539
633
540
634
DirEntry :: new_root ( inode, String :: from ( "/" ) )
0 commit comments