@@ -269,25 +269,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
269269 let this = self . eval_context_mut ( ) ;
270270
271271 if this. tcx . sess . target . target . target_os . to_lowercase ( ) != "macos" {
272- throw_unsup_format ! ( "The `stat` shim is only only available for `macos` targets." )
272+ throw_unsup_format ! ( "The `stat` shim is only available for `macos` targets." )
273273 }
274274
275275 let path_scalar = this. read_scalar ( path_op) ?. not_undef ( ) ?;
276276 let path: PathBuf = this. read_os_str_from_c_str ( path_scalar) ?. into ( ) ;
277277
278278 let buf = this. deref_operand ( buf_op) ?;
279279
280- let status = match FileStatus :: new ( this, path, false ) ? {
281- Some ( status) => status,
280+ // `stat` always follows symlinks. `lstat` is used to get symlink metadata.
281+ let metadata = match FileMetadata :: new ( this, path, true ) ? {
282+ Some ( metadata) => metadata,
282283 None => return Ok ( -1 ) ,
283284 } ;
284285
285286 // FIXME: use Scalar::to_u16
286- let mode: u16 = status . mode . to_bits ( Size :: from_bits ( 16 ) ) ? as u16 ;
287+ let mode: u16 = metadata . mode . to_bits ( Size :: from_bits ( 16 ) ) ? as u16 ;
287288
288- let ( access_sec, access_nsec) = status . accessed . unwrap_or ( ( 0 , 0 ) ) ;
289- let ( created_sec, created_nsec) = status . created . unwrap_or ( ( 0 , 0 ) ) ;
290- let ( modified_sec, modified_nsec) = status . modified . unwrap_or ( ( 0 , 0 ) ) ;
289+ let ( access_sec, access_nsec) = metadata . accessed . unwrap_or ( ( 0 , 0 ) ) ;
290+ let ( created_sec, created_nsec) = metadata . created . unwrap_or ( ( 0 , 0 ) ) ;
291+ let ( modified_sec, modified_nsec) = metadata . modified . unwrap_or ( ( 0 , 0 ) ) ;
291292
292293 let dev_t_layout = this. libc_ty_layout ( "dev_t" ) ?;
293294 let mode_t_layout = this. libc_ty_layout ( "mode_t" ) ?;
@@ -302,7 +303,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
302303 let blksize_t_layout = this. libc_ty_layout ( "blksize_t" ) ?;
303304 let uint32_t_layout = this. libc_ty_layout ( "uint32_t" ) ?;
304305
305- // We need to add 32 bits of padding after `st_rdev` if we are in a 64-bit platform.
306+ // We need to add 32 bits of padding after `st_rdev` if we are on a 64-bit platform.
306307 let pad_layout = if this. tcx . sess . target . ptr_width == 64 {
307308 uint32_t_layout
308309 } else {
@@ -326,7 +327,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
326327 immty_from_uint_checked ( 0u128 , long_layout) ?, // st_ctime_nsec
327328 immty_from_uint_checked ( created_sec, time_t_layout) ?, // st_birthtime
328329 immty_from_uint_checked ( created_nsec, long_layout) ?, // st_birthtime_nsec
329- immty_from_uint_checked ( status . size , off_t_layout) ?, // st_size
330+ immty_from_uint_checked ( metadata . size , off_t_layout) ?, // st_size
330331 immty_from_uint_checked ( 0u128 , blkcnt_t_layout) ?, // st_blocks
331332 immty_from_uint_checked ( 0u128 , blksize_t_layout) ?, // st_blksize
332333 immty_from_uint_checked ( 0u128 , uint32_t_layout) ?, // st_flags
@@ -351,7 +352,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
351352 this. check_no_isolation ( "statx" ) ?;
352353
353354 if this. tcx . sess . target . target . target_os . to_lowercase ( ) != "linux" {
354- throw_unsup_format ! ( "The `statx` shim is only only available for `linux` targets." )
355+ throw_unsup_format ! ( "The `statx` shim is only available for `linux` targets." )
355356 }
356357
357358 let statxbuf_scalar = this. read_scalar ( statxbuf_op) ?. not_undef ( ) ?;
@@ -413,34 +414,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
413414 // symbolic links.
414415 let follow_symlink = flags & this. eval_libc ( "AT_SYMLINK_NOFOLLOW" ) ?. to_i32 ( ) ? == 0 ;
415416
416- let status = match FileStatus :: new ( this, path, follow_symlink) ? {
417- Some ( status ) => status ,
417+ let metadata = match FileMetadata :: new ( this, path, follow_symlink) ? {
418+ Some ( metadata ) => metadata ,
418419 None => return Ok ( -1 ) ,
419420 } ;
420421
421422 // The `mode` field specifies the type of the file and the permissions over the file for
422423 // the owner, its group and other users. Given that we can only provide the file type
423424 // without using platform specific methods, we only set the bits corresponding to the file
424425 // type. This should be an `__u16` but `libc` provides its values as `u32`.
425- let mode: u16 = status
426+ let mode: u16 = metadata
426427 . mode
427428 . to_u32 ( ) ?
428429 . try_into ( )
429430 . unwrap_or_else ( |_| bug ! ( "libc contains bad value for constant" ) ) ;
430431
431432 // We need to set the corresponding bits of `mask` if the access, creation and modification
432433 // times were available. Otherwise we let them be zero.
433- let ( access_sec, access_nsec) = status . accessed . map ( |tup| {
434+ let ( access_sec, access_nsec) = metadata . accessed . map ( |tup| {
434435 mask |= this. eval_libc ( "STATX_ATIME" ) ?. to_u32 ( ) ?;
435436 InterpResult :: Ok ( tup)
436437 } ) . unwrap_or ( Ok ( ( 0 , 0 ) ) ) ?;
437438
438- let ( created_sec, created_nsec) = status . created . map ( |tup| {
439+ let ( created_sec, created_nsec) = metadata . created . map ( |tup| {
439440 mask |= this. eval_libc ( "STATX_BTIME" ) ?. to_u32 ( ) ?;
440441 InterpResult :: Ok ( tup)
441442 } ) . unwrap_or ( Ok ( ( 0 , 0 ) ) ) ?;
442443
443- let ( modified_sec, modified_nsec) = status . modified . map ( |tup| {
444+ let ( modified_sec, modified_nsec) = metadata . modified . map ( |tup| {
444445 mask |= this. eval_libc ( "STATX_MTIME" ) ?. to_u32 ( ) ?;
445446 InterpResult :: Ok ( tup)
446447 } ) . unwrap_or ( Ok ( ( 0 , 0 ) ) ) ?;
@@ -461,7 +462,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
461462 immty_from_uint_checked ( mode, __u16_layout) ?, // stx_mode
462463 immty_from_uint_checked ( 0u128 , __u16_layout) ?, // statx padding
463464 immty_from_uint_checked ( 0u128 , __u64_layout) ?, // stx_ino
464- immty_from_uint_checked ( status . size , __u64_layout) ?, // stx_size
465+ immty_from_uint_checked ( metadata . size , __u64_layout) ?, // stx_size
465466 immty_from_uint_checked ( 0u128 , __u64_layout) ?, // stx_blocks
466467 immty_from_uint_checked ( 0u128 , __u64_layout) ?, // stx_attributes
467468 immty_from_uint_checked ( access_sec, __u64_layout) ?, // stx_atime.tv_sec
@@ -511,25 +512,27 @@ fn extract_sec_and_nsec<'tcx>(
511512 } ) . transpose ( )
512513}
513514
514- struct FileStatus {
515+ /// Stores a file's metadata in order to avoid code duplication in the different metadata related
516+ /// shims.
517+ struct FileMetadata {
515518 mode : Scalar < Tag > ,
516519 size : u64 ,
517520 created : Option < ( u64 , u32 ) > ,
518521 accessed : Option < ( u64 , u32 ) > ,
519522 modified : Option < ( u64 , u32 ) > ,
520523}
521524
522- impl FileStatus {
525+ impl FileMetadata {
523526 fn new < ' tcx , ' mir > (
524527 ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
525528 path : PathBuf ,
526529 follow_symlink : bool
527- ) -> InterpResult < ' tcx , Option < FileStatus > > {
530+ ) -> InterpResult < ' tcx , Option < FileMetadata > > {
528531 let metadata = if follow_symlink {
532+ std:: fs:: metadata ( path)
533+ } else {
529534 // FIXME: metadata for symlinks need testing.
530535 std:: fs:: symlink_metadata ( path)
531- } else {
532- std:: fs:: metadata ( path)
533536 } ;
534537
535538 let metadata = match metadata {
@@ -559,6 +562,6 @@ impl FileStatus {
559562 let modified = extract_sec_and_nsec ( metadata. modified ( ) ) ?;
560563
561564 // FIXME: Provide more fields using platform specific methods.
562- Ok ( Some ( FileStatus { mode, size, created, accessed, modified } ) )
565+ Ok ( Some ( FileMetadata { mode, size, created, accessed, modified } ) )
563566 }
564567}
0 commit comments