@@ -249,22 +249,25 @@ pub struct Stat {
249249 pub ino : u64 ,
250250 pub mode : StatMode ,
251251 pub nlink : u32 ,
252- pad : [ u64 ; 7 ] ,
252+ pub size : u64 , // added
253+ pad : [ u64 ; 6 ] ,
253254}
254255
255256impl Stat {
256- pub fn new ( ino : u64 , mode : StatMode , nlink : u32 ) -> Self {
257+ pub fn new ( ino : u64 , mode : StatMode , nlink : u32 , size : u64 ) -> Self {
257258 Self {
258259 dev : 0 ,
259260 ino,
260261 mode,
261262 nlink,
262- pad : [ 0 ; 7 ] ,
263+ size,
264+ pad : [ 0 ; 6 ] ,
263265 }
264266 }
265267}
266268
267269bitflags ! {
270+ #[ derive( Default ) ]
268271 pub struct StatMode : u32 {
269272 const NULL = 0 ;
270273 /// directory
@@ -295,8 +298,9 @@ pub fn sys_fstat(fd: usize, ptr: *mut Stat) -> isize {
295298 } else {
296299 StatMode :: NULL
297300 } ;
301+ let size = inode. get_size ( ) ;
298302 let nlink = inode. nlink ( ) ;
299- let stat = Stat :: new ( ino as u64 , mode, nlink) ;
303+ let stat = Stat :: new ( ino as u64 , mode, nlink, size as u64 ) ;
300304
301305 let dst_vs = mm:: translated_byte_buffer (
302306 task_inner. get_user_token ( ) ,
@@ -339,3 +343,61 @@ pub fn sys_dup(fd: usize) -> isize {
339343 inner. fd_table [ new_fd] = Some ( file) ;
340344 new_fd as isize
341345}
346+
347+ /// The max length of inode name
348+ const NAME_LENGTH_LIMIT : usize = 27 ;
349+ #[ repr( C , align( 32 ) ) ]
350+ #[ derive( Clone , Default ) ]
351+ pub struct Dirent {
352+ pub ftype : FileType ,
353+ pub name : [ u8 ; NAME_LENGTH_LIMIT ] ,
354+ pub next_offset : u32 ,
355+ }
356+
357+ bitflags ! {
358+ #[ derive( Default ) ]
359+ pub struct FileType : u8 {
360+ const UNKNOWN = 0 ;
361+ const DIR = 1 << 0 ;
362+ const REG = 1 << 1 ;
363+ }
364+ }
365+
366+ pub fn sys_getdents ( fd : usize , ptr : * mut Dirent , len : usize ) -> isize {
367+ let task = task:: current_task ( ) . unwrap ( ) ;
368+ let inner = task. inner_exclusive_access ( ) ;
369+ let token = inner. get_user_token ( ) ;
370+
371+ let file = match inner. fd_table . get ( fd) {
372+ Some ( Some ( file) ) => {
373+ let file_clone = file. clone ( ) ;
374+ match file_clone. downcast_arc :: < OSInode > ( ) {
375+ Some ( os_inode) if os_inode. is_dir ( ) => os_inode. clone_inner_inode ( ) ,
376+ _ => return -1 ,
377+ }
378+ }
379+ _ => return -1 ,
380+ } ;
381+ let cursor = mm:: translate_ref ( token, unsafe { ptr. add ( len - 1 ) } ) . next_offset ;
382+ let dirents = file. dirents ( cursor) ;
383+ let nread = len. min ( dirents. len ( ) ) ;
384+ for i in 0 ..nread {
385+ let ename = dirents[ i] . 0 . as_bytes ( ) ;
386+ let inode = & dirents[ i] . 1 ;
387+ let ftype = if inode. is_dir ( ) {
388+ FileType :: DIR
389+ } else if inode. is_file ( ) {
390+ FileType :: REG
391+ } else {
392+ FileType :: UNKNOWN
393+ } ;
394+ let mut name = [ 0u8 ; NAME_LENGTH_LIMIT ] ;
395+ name[ ..ename. len ( ) ] . copy_from_slice ( & ename[ ..] ) ;
396+ * mm:: translated_refmut ( token, unsafe { ptr. add ( i) } ) = Dirent {
397+ ftype,
398+ name,
399+ next_offset : cursor + i as u32 + 1 ,
400+ } ;
401+ }
402+ nread as isize
403+ }
0 commit comments