@@ -11,8 +11,8 @@ use memory_addresses::VirtAddr;
1111use uhyve_interface:: GuestPhysAddr ;
1212use uhyve_interface:: v2:: Hypercall ;
1313use uhyve_interface:: v2:: parameters:: {
14- CloseParams , GetdentParams , GetdentResult , LseekParams , OpenParams , ReadParams , UnlinkParams ,
15- WriteParams ,
14+ CloseParams , FstatParams , GetdentParams , GetdentResult , LseekParams , OpenParams , ReadParams ,
15+ StatKind , StatParams , StatResult , UnlinkParams , WriteParams ,
1616} ;
1717
1818use crate :: arch:: mm:: paging:: virtual_to_physical;
@@ -25,6 +25,25 @@ use crate::fs::{
2525use crate :: io;
2626use crate :: uhyve:: uhyve_hypercall;
2727
28+ fn fstat_hypercall ( fd : i32 ) -> io:: Result < FileAttr > {
29+ let mut attr = FileAttr :: default ( ) ;
30+ let mut fstat_params = FstatParams {
31+ fd,
32+ attr : GuestPhysAddr :: new (
33+ virtual_to_physical ( VirtAddr :: from_ptr ( ( & raw mut attr) . cast :: < FileAttr > ( ) ) )
34+ . unwrap ( )
35+ . as_u64 ( ) ,
36+ ) ,
37+ ret : StatResult :: None ,
38+ } ;
39+ uhyve_hypercall ( Hypercall :: FileFstat ( & mut fstat_params) ) ;
40+ match fstat_params. ret {
41+ StatResult :: None => Err ( Errno :: Nosys ) ,
42+ StatResult :: Success => Ok ( attr) ,
43+ StatResult :: Error ( errno) => Err ( Errno :: try_from ( errno) . unwrap ( ) ) ,
44+ }
45+ }
46+
2847#[ derive( Debug ) ]
2948struct UhyveFileHandleInner ( i32 ) ;
3049
@@ -140,6 +159,10 @@ impl ObjectInterface for UhyveFileHandle {
140159 async fn lseek ( & self , offset : isize , whence : SeekWhence ) -> io:: Result < isize > {
141160 self . 0 . lock ( ) . await . lseek ( offset, whence)
142161 }
162+
163+ async fn fstat ( & self ) -> io:: Result < FileAttr > {
164+ fstat_hypercall ( self . 0 . lock ( ) . await . 0 )
165+ }
143166}
144167
145168impl Clone for UhyveFileHandle {
@@ -189,6 +212,10 @@ impl ObjectInterface for UhyveDirectoryHandle {
189212 GetdentResult :: Error ( errno) => Err ( Errno :: try_from ( errno) . unwrap ( ) ) ,
190213 }
191214 }
215+
216+ async fn fstat ( & self ) -> io:: Result < FileAttr > {
217+ fstat_hypercall ( self . fd )
218+ }
192219}
193220
194221#[ derive( Debug ) ]
@@ -208,9 +235,37 @@ impl UhyveDirectory {
208235 fn traversal_path ( & self , path : & str ) -> CString {
209236 let prefix = self . prefix . as_str ( ) ;
210237 let prefix = prefix. strip_suffix ( "/" ) . unwrap_or ( prefix) ;
238+ if path. is_empty ( ) {
239+ return CString :: new ( prefix) . unwrap ( ) ;
240+ }
211241 let path = [ prefix, path] . join ( "/" ) ;
212242 CString :: new ( path) . unwrap ( )
213243 }
244+
245+ fn stat_hypercall ( & self , path : & str , kind : StatKind ) -> io:: Result < FileAttr > {
246+ let path = self . traversal_path ( path) ;
247+ let mut attr = FileAttr :: default ( ) ;
248+ let mut stat_params = StatParams {
249+ name : GuestPhysAddr :: new (
250+ virtual_to_physical ( VirtAddr :: from_ptr ( path. as_ptr ( ) ) )
251+ . unwrap ( )
252+ . as_u64 ( ) ,
253+ ) ,
254+ kind,
255+ attr : GuestPhysAddr :: new (
256+ virtual_to_physical ( VirtAddr :: from_ptr ( ( & raw mut attr) . cast :: < FileAttr > ( ) ) )
257+ . unwrap ( )
258+ . as_u64 ( ) ,
259+ ) ,
260+ ret : StatResult :: None ,
261+ } ;
262+ uhyve_hypercall ( Hypercall :: FileStat ( & mut stat_params) ) ;
263+ match stat_params. ret {
264+ StatResult :: None => Err ( Errno :: Nosys ) ,
265+ StatResult :: Success => Ok ( attr) ,
266+ StatResult :: Error ( errno) => Err ( Errno :: try_from ( errno) . unwrap ( ) ) ,
267+ }
268+ }
214269}
215270
216271impl VfsNode for UhyveDirectory {
@@ -219,12 +274,16 @@ impl VfsNode for UhyveDirectory {
219274 NodeKind :: Directory
220275 }
221276
222- fn traverse_stat ( & self , _path : & str ) -> io:: Result < FileAttr > {
223- Err ( Errno :: Nosys )
277+ fn get_file_attributes ( & self ) -> io:: Result < FileAttr > {
278+ self . stat_hypercall ( "" , StatKind :: Stat )
224279 }
225280
226- fn traverse_lstat ( & self , _path : & str ) -> io:: Result < FileAttr > {
227- Err ( Errno :: Nosys )
281+ fn traverse_stat ( & self , path : & str ) -> io:: Result < FileAttr > {
282+ self . stat_hypercall ( path, StatKind :: Stat )
283+ }
284+
285+ fn traverse_lstat ( & self , path : & str ) -> io:: Result < FileAttr > {
286+ self . stat_hypercall ( path, StatKind :: LStat )
228287 }
229288
230289 fn traverse_open (
@@ -249,9 +308,14 @@ impl VfsNode for UhyveDirectory {
249308 let ret = open_params. ret ; // circumvent packed field access
250309 match ret {
251310 // Assumption: Uhyve will never return a standard stream.
252- ret if ret >= 0 => Ok ( Arc :: new ( async_lock:: RwLock :: new (
253- UhyveFileHandle :: new ( ret) . into ( ) ,
254- ) ) ) ,
311+ ret if ret >= 0 => {
312+ let obj = if opt. contains ( OpenOption :: O_DIRECTORY ) {
313+ UhyveDirectoryHandle :: new ( ret) . into ( )
314+ } else {
315+ UhyveFileHandle :: new ( ret) . into ( )
316+ } ;
317+ Ok ( Arc :: new ( async_lock:: RwLock :: new ( obj) ) )
318+ }
255319 _ => Err ( ret. abs ( ) . try_into ( ) . unwrap ( ) ) ,
256320 }
257321 }
0 commit comments