@@ -328,6 +328,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
328328 this. stat_or_lstat ( false , path_op, buf_op)
329329 }
330330
331+ fn fstat (
332+ & mut self ,
333+ fd_op : OpTy < ' tcx , Tag > ,
334+ buf_op : OpTy < ' tcx , Tag > ,
335+ ) -> InterpResult < ' tcx , i32 > {
336+ let this = self . eval_context_mut ( ) ;
337+
338+ this. check_no_isolation ( "fstat" ) ?;
339+
340+ if this. tcx . sess . target . target . target_os . to_lowercase ( ) != "macos" {
341+ throw_unsup_format ! ( "The `fstat` shim is only available for `macos` targets." )
342+ }
343+
344+ let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
345+
346+ let metadata = match FileMetadata :: from_fd ( this, fd) ? {
347+ Some ( metadata) => metadata,
348+ None => return Ok ( -1 ) ,
349+ } ;
350+ stat_write_buf ( this, metadata, buf_op)
351+ }
352+
331353 fn stat_or_lstat (
332354 & mut self ,
333355 follow_symlink : bool ,
@@ -343,66 +365,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
343365 let path_scalar = this. read_scalar ( path_op) ?. not_undef ( ) ?;
344366 let path: PathBuf = this. read_os_str_from_c_str ( path_scalar) ?. into ( ) ;
345367
346- let buf = this. deref_operand ( buf_op) ?;
347-
348368 let metadata = match FileMetadata :: from_path ( this, path, follow_symlink) ? {
349369 Some ( metadata) => metadata,
350370 None => return Ok ( -1 ) ,
351371 } ;
352-
353- let mode: u16 = metadata. mode . to_u16 ( ) ?;
354-
355- let ( access_sec, access_nsec) = metadata. accessed . unwrap_or ( ( 0 , 0 ) ) ;
356- let ( created_sec, created_nsec) = metadata. created . unwrap_or ( ( 0 , 0 ) ) ;
357- let ( modified_sec, modified_nsec) = metadata. modified . unwrap_or ( ( 0 , 0 ) ) ;
358-
359- let dev_t_layout = this. libc_ty_layout ( "dev_t" ) ?;
360- let mode_t_layout = this. libc_ty_layout ( "mode_t" ) ?;
361- let nlink_t_layout = this. libc_ty_layout ( "nlink_t" ) ?;
362- let ino_t_layout = this. libc_ty_layout ( "ino_t" ) ?;
363- let uid_t_layout = this. libc_ty_layout ( "uid_t" ) ?;
364- let gid_t_layout = this. libc_ty_layout ( "gid_t" ) ?;
365- let time_t_layout = this. libc_ty_layout ( "time_t" ) ?;
366- let long_layout = this. libc_ty_layout ( "c_long" ) ?;
367- let off_t_layout = this. libc_ty_layout ( "off_t" ) ?;
368- let blkcnt_t_layout = this. libc_ty_layout ( "blkcnt_t" ) ?;
369- let blksize_t_layout = this. libc_ty_layout ( "blksize_t" ) ?;
370- let uint32_t_layout = this. libc_ty_layout ( "uint32_t" ) ?;
371-
372- // We need to add 32 bits of padding after `st_rdev` if we are on a 64-bit platform.
373- let pad_layout = if this. tcx . sess . target . ptr_width == 64 {
374- uint32_t_layout
375- } else {
376- this. layout_of ( this. tcx . mk_unit ( ) ) ?
377- } ;
378-
379- let imms = [
380- immty_from_uint_checked ( 0u128 , dev_t_layout) ?, // st_dev
381- immty_from_uint_checked ( mode, mode_t_layout) ?, // st_mode
382- immty_from_uint_checked ( 0u128 , nlink_t_layout) ?, // st_nlink
383- immty_from_uint_checked ( 0u128 , ino_t_layout) ?, // st_ino
384- immty_from_uint_checked ( 0u128 , uid_t_layout) ?, // st_uid
385- immty_from_uint_checked ( 0u128 , gid_t_layout) ?, // st_gid
386- immty_from_uint_checked ( 0u128 , dev_t_layout) ?, // st_rdev
387- immty_from_uint_checked ( 0u128 , pad_layout) ?, // padding for 64-bit targets
388- immty_from_uint_checked ( access_sec, time_t_layout) ?, // st_atime
389- immty_from_uint_checked ( access_nsec, long_layout) ?, // st_atime_nsec
390- immty_from_uint_checked ( modified_sec, time_t_layout) ?, // st_mtime
391- immty_from_uint_checked ( modified_nsec, long_layout) ?, // st_mtime_nsec
392- immty_from_uint_checked ( 0u128 , time_t_layout) ?, // st_ctime
393- immty_from_uint_checked ( 0u128 , long_layout) ?, // st_ctime_nsec
394- immty_from_uint_checked ( created_sec, time_t_layout) ?, // st_birthtime
395- immty_from_uint_checked ( created_nsec, long_layout) ?, // st_birthtime_nsec
396- immty_from_uint_checked ( metadata. size , off_t_layout) ?, // st_size
397- immty_from_uint_checked ( 0u128 , blkcnt_t_layout) ?, // st_blocks
398- immty_from_uint_checked ( 0u128 , blksize_t_layout) ?, // st_blksize
399- immty_from_uint_checked ( 0u128 , uint32_t_layout) ?, // st_flags
400- immty_from_uint_checked ( 0u128 , uint32_t_layout) ?, // st_gen
401- ] ;
402-
403- this. write_packed_immediates ( & buf, & imms) ?;
404-
405- Ok ( 0 )
372+ stat_write_buf ( this, metadata, buf_op)
406373 }
407374
408375 fn statx (
@@ -663,3 +630,64 @@ impl FileMetadata {
663630 Ok ( Some ( FileMetadata { mode, size, created, accessed, modified } ) )
664631 }
665632}
633+
634+ fn stat_write_buf < ' tcx , ' mir > (
635+ ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
636+ metadata : FileMetadata ,
637+ buf_op : OpTy < ' tcx , Tag > ,
638+ ) -> InterpResult < ' tcx , i32 > {
639+ let mode: u16 = metadata. mode . to_u16 ( ) ?;
640+
641+ let ( access_sec, access_nsec) = metadata. accessed . unwrap_or ( ( 0 , 0 ) ) ;
642+ let ( created_sec, created_nsec) = metadata. created . unwrap_or ( ( 0 , 0 ) ) ;
643+ let ( modified_sec, modified_nsec) = metadata. modified . unwrap_or ( ( 0 , 0 ) ) ;
644+
645+ let dev_t_layout = ecx. libc_ty_layout ( "dev_t" ) ?;
646+ let mode_t_layout = ecx. libc_ty_layout ( "mode_t" ) ?;
647+ let nlink_t_layout = ecx. libc_ty_layout ( "nlink_t" ) ?;
648+ let ino_t_layout = ecx. libc_ty_layout ( "ino_t" ) ?;
649+ let uid_t_layout = ecx. libc_ty_layout ( "uid_t" ) ?;
650+ let gid_t_layout = ecx. libc_ty_layout ( "gid_t" ) ?;
651+ let time_t_layout = ecx. libc_ty_layout ( "time_t" ) ?;
652+ let long_layout = ecx. libc_ty_layout ( "c_long" ) ?;
653+ let off_t_layout = ecx. libc_ty_layout ( "off_t" ) ?;
654+ let blkcnt_t_layout = ecx. libc_ty_layout ( "blkcnt_t" ) ?;
655+ let blksize_t_layout = ecx. libc_ty_layout ( "blksize_t" ) ?;
656+ let uint32_t_layout = ecx. libc_ty_layout ( "uint32_t" ) ?;
657+
658+ // We need to add 32 bits of padding after `st_rdev` if we are on a 64-bit platform.
659+ let pad_layout = if ecx. tcx . sess . target . ptr_width == 64 {
660+ uint32_t_layout
661+ } else {
662+ ecx. layout_of ( ecx. tcx . mk_unit ( ) ) ?
663+ } ;
664+
665+ let imms = [
666+ immty_from_uint_checked ( 0u128 , dev_t_layout) ?, // st_dev
667+ immty_from_uint_checked ( mode, mode_t_layout) ?, // st_mode
668+ immty_from_uint_checked ( 0u128 , nlink_t_layout) ?, // st_nlink
669+ immty_from_uint_checked ( 0u128 , ino_t_layout) ?, // st_ino
670+ immty_from_uint_checked ( 0u128 , uid_t_layout) ?, // st_uid
671+ immty_from_uint_checked ( 0u128 , gid_t_layout) ?, // st_gid
672+ immty_from_uint_checked ( 0u128 , dev_t_layout) ?, // st_rdev
673+ immty_from_uint_checked ( 0u128 , pad_layout) ?, // padding for 64-bit targets
674+ immty_from_uint_checked ( access_sec, time_t_layout) ?, // st_atime
675+ immty_from_uint_checked ( access_nsec, long_layout) ?, // st_atime_nsec
676+ immty_from_uint_checked ( modified_sec, time_t_layout) ?, // st_mtime
677+ immty_from_uint_checked ( modified_nsec, long_layout) ?, // st_mtime_nsec
678+ immty_from_uint_checked ( 0u128 , time_t_layout) ?, // st_ctime
679+ immty_from_uint_checked ( 0u128 , long_layout) ?, // st_ctime_nsec
680+ immty_from_uint_checked ( created_sec, time_t_layout) ?, // st_birthtime
681+ immty_from_uint_checked ( created_nsec, long_layout) ?, // st_birthtime_nsec
682+ immty_from_uint_checked ( metadata. size , off_t_layout) ?, // st_size
683+ immty_from_uint_checked ( 0u128 , blkcnt_t_layout) ?, // st_blocks
684+ immty_from_uint_checked ( 0u128 , blksize_t_layout) ?, // st_blksize
685+ immty_from_uint_checked ( 0u128 , uint32_t_layout) ?, // st_flags
686+ immty_from_uint_checked ( 0u128 , uint32_t_layout) ?, // st_gen
687+ ] ;
688+
689+ let buf = ecx. deref_operand ( buf_op) ?;
690+ ecx. write_packed_immediates ( & buf, & imms) ?;
691+
692+ Ok ( 0 )
693+ }
0 commit comments