@@ -28,8 +28,8 @@ use crate::utils::CeilDiv;
28
28
29
29
use super :: block:: BlockDevice ;
30
30
31
- use super :: cache;
32
31
use super :: cache:: { DirCacheItem , INodeCacheItem } ;
32
+ use super :: { cache, FileSystemError } ;
33
33
34
34
use super :: inode:: { DirEntry , INodeInterface , Metadata } ;
35
35
use super :: FileSystem ;
@@ -282,9 +282,83 @@ impl INodeInterface for INode {
282
282
} )
283
283
}
284
284
285
+ fn stat ( & self ) -> super :: Result < aero_syscall:: Stat > {
286
+ use super :: inode:: FileType ;
287
+ use aero_syscall:: { Mode , Stat } ;
288
+
289
+ let filesystem = self . fs . upgrade ( ) . unwrap ( ) ;
290
+ let filetype = self . metadata ( ) ?. file_type ( ) ;
291
+
292
+ let mut mode = Mode :: empty ( ) ;
293
+
294
+ match filetype {
295
+ FileType :: File => mode. insert ( Mode :: S_IFREG ) ,
296
+ FileType :: Directory => mode. insert ( Mode :: S_IFDIR ) ,
297
+ FileType :: Device => mode. insert ( Mode :: S_IFCHR ) ,
298
+ FileType :: Socket => mode. insert ( Mode :: S_IFSOCK ) ,
299
+ FileType :: Symlink => mode. insert ( Mode :: S_IFLNK ) ,
300
+ }
301
+
302
+ // FIXME: read permission bits from the inode.
303
+ mode. insert ( Mode :: S_IRWXU | Mode :: S_IRWXG | Mode :: S_IRWXO ) ;
304
+
305
+ Ok ( Stat {
306
+ st_ino : self . id as _ ,
307
+ st_blksize : filesystem. superblock . block_size ( ) as _ ,
308
+ st_size : self . inode . size_lower as _ ,
309
+ st_mode : mode,
310
+
311
+ ..Default :: default ( )
312
+ } )
313
+ }
314
+
285
315
fn dirent ( & self , parent : DirCacheItem , index : usize ) -> super :: Result < Option < DirCacheItem > > {
286
316
Ok ( DirEntryIter :: new ( parent, self . sref ( ) ) . nth ( index) )
287
317
}
318
+
319
+ fn lookup ( & self , dir : DirCacheItem , name : & str ) -> super :: Result < DirCacheItem > {
320
+ DirEntryIter :: new ( dir, self . sref ( ) )
321
+ . find ( |e| & e. name ( ) == name)
322
+ . ok_or ( FileSystemError :: EntryNotFound )
323
+ }
324
+
325
+ fn read_at ( & self , offset : usize , buffer : & mut [ u8 ] ) -> super :: Result < usize > {
326
+ let filesystem = self . fs . upgrade ( ) . unwrap ( ) ;
327
+ let block_size = filesystem. superblock . block_size ( ) ;
328
+
329
+ let mut progress = 0 ;
330
+
331
+ let count = core:: cmp:: min ( self . inode . size_lower as usize - offset, buffer. len ( ) ) ;
332
+
333
+ while progress < count {
334
+ let block = ( offset + progress) / block_size;
335
+ let loc = ( offset + progress) % block_size;
336
+
337
+ let mut chunk = count - progress;
338
+
339
+ if chunk > block_size - loc {
340
+ chunk = block_size - loc;
341
+ }
342
+
343
+ let block_index = self . inode . data_ptr [ block] ;
344
+
345
+ // TODO: We really should not allocate another buffer here.
346
+ let mut data = Box :: < [ u8 ] > :: new_uninit_slice ( chunk) ;
347
+
348
+ filesystem. block . device ( ) . read (
349
+ ( block_index as usize * block_size) + loc,
350
+ MaybeUninit :: slice_as_bytes_mut ( & mut data) ,
351
+ ) ;
352
+
353
+ // SAFETY: We have initialized the data buffer above.
354
+ let data = unsafe { data. assume_init ( ) } ;
355
+
356
+ buffer[ progress..progress + data. len ( ) ] . copy_from_slice ( & * data) ;
357
+ progress += chunk;
358
+ }
359
+
360
+ Ok ( count)
361
+ }
288
362
}
289
363
290
364
#[ derive( Debug , Copy , Clone ) ]
0 commit comments