@@ -45,8 +45,7 @@ macro_rules! has {
4545pub struct FileInformation (
4646 #[ cfg( unix) ] rustix:: fs:: Stat ,
4747 #[ cfg( windows) ] winapi_util:: file:: Information ,
48- // WASI does not have nix::sys::stat, so we store std::fs::Metadata instead.
49- #[ cfg( target_os = "wasi" ) ] fs:: Metadata ,
48+ #[ cfg( target_os = "wasi" ) ] libc:: stat ,
5049) ;
5150
5251impl FileInformation {
@@ -67,8 +66,12 @@ impl FileInformation {
6766 /// Get information from a currently open file
6867 #[ cfg( target_os = "wasi" ) ]
6968 pub fn from_file ( file : & fs:: File ) -> IOResult < Self > {
70- let meta = file. metadata ( ) ?;
71- Ok ( Self ( meta) )
69+ use std:: os:: fd:: AsRawFd ;
70+ let mut stat: libc:: stat = unsafe { std:: mem:: zeroed ( ) } ;
71+ if unsafe { libc:: fstat ( file. as_raw_fd ( ) , & mut stat) } != 0 {
72+ return Err ( Error :: last_os_error ( ) ) ;
73+ }
74+ Ok ( Self ( stat) )
7275 }
7376
7477 /// Get information for a given path.
@@ -100,15 +103,22 @@ impl FileInformation {
100103 let file = open_options. read ( true ) . open ( path. as_ref ( ) ) ?;
101104 Self :: from_file ( & file)
102105 }
103- // WASI: use std::fs::metadata / symlink_metadata since nix is not available
104106 #[ cfg( target_os = "wasi" ) ]
105107 {
106- let metadata = if dereference {
107- fs:: metadata ( path. as_ref ( ) )
108+ use std:: ffi:: CString ;
109+ use std:: os:: wasi:: ffi:: OsStrExt ;
110+ let path_c = CString :: new ( path. as_ref ( ) . as_os_str ( ) . as_bytes ( ) )
111+ . map_err ( |e| Error :: new ( ErrorKind :: InvalidInput , e) ) ?;
112+ let mut stat: libc:: stat = unsafe { std:: mem:: zeroed ( ) } ;
113+ let res = if dereference {
114+ unsafe { libc:: stat ( path_c. as_ptr ( ) , & mut stat) }
108115 } else {
109- fs :: symlink_metadata ( path . as_ref ( ) )
116+ unsafe { libc :: lstat ( path_c . as_ptr ( ) , & mut stat ) }
110117 } ;
111- Ok ( Self ( metadata?) )
118+ if res != 0 {
119+ return Err ( Error :: last_os_error ( ) ) ;
120+ }
121+ Ok ( Self ( stat) )
112122 }
113123 }
114124
@@ -124,7 +134,8 @@ impl FileInformation {
124134 }
125135 #[ cfg( target_os = "wasi" ) ]
126136 {
127- self . 0 . len ( )
137+ assert ! ( self . 0 . st_size >= 0 , "File size is negative" ) ;
138+ self . 0 . st_size . try_into ( ) . unwrap ( )
128139 }
129140 }
130141
@@ -177,10 +188,7 @@ impl FileInformation {
177188 #[ cfg( windows) ]
178189 return self . 0 . number_of_links ( ) ;
179190 #[ cfg( target_os = "wasi" ) ]
180- {
181- use std:: os:: wasi:: fs:: MetadataExt ;
182- return self . 0 . nlink ( ) ;
183- }
191+ return self . 0 . st_nlink as u64 ;
184192 }
185193
186194 #[ cfg( unix) ]
@@ -211,8 +219,7 @@ impl PartialEq for FileInformation {
211219#[ cfg( target_os = "wasi" ) ]
212220impl PartialEq for FileInformation {
213221 fn eq ( & self , other : & Self ) -> bool {
214- use std:: os:: wasi:: fs:: MetadataExt ;
215- self . 0 . dev ( ) == other. 0 . dev ( ) && self . 0 . ino ( ) == other. 0 . ino ( )
222+ self . 0 . st_dev == other. 0 . st_dev && self . 0 . st_ino == other. 0 . st_ino
216223 }
217224}
218225
@@ -232,9 +239,8 @@ impl Hash for FileInformation {
232239 }
233240 #[ cfg( target_os = "wasi" ) ]
234241 {
235- use std:: os:: wasi:: fs:: MetadataExt ;
236- self . 0 . dev ( ) . hash ( state) ;
237- self . 0 . ino ( ) . hash ( state) ;
242+ self . 0 . st_dev . hash ( state) ;
243+ self . 0 . st_ino . hash ( state) ;
238244 }
239245 }
240246}
0 commit comments