@@ -28,8 +28,8 @@ use crate::utils::CeilDiv;
2828
2929use super :: block:: BlockDevice ;
3030
31- use super :: cache;
3231use super :: cache:: { DirCacheItem , INodeCacheItem } ;
32+ use super :: { cache, FileSystemError } ;
3333
3434use super :: inode:: { DirEntry , INodeInterface , Metadata } ;
3535use super :: FileSystem ;
@@ -282,9 +282,83 @@ impl INodeInterface for INode {
282282 } )
283283 }
284284
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+
285315 fn dirent ( & self , parent : DirCacheItem , index : usize ) -> super :: Result < Option < DirCacheItem > > {
286316 Ok ( DirEntryIter :: new ( parent, self . sref ( ) ) . nth ( index) )
287317 }
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+ }
288362}
289363
290364#[ derive( Debug , Copy , Clone ) ]
0 commit comments