From 15d8b58120669554bab787800906bdae09a58bde Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 5 Dec 2024 23:18:38 +0000 Subject: [PATCH] addressing remarks --- src/helpers.rs | 15 +++++++++++++++ src/shims/unix/fs.rs | 27 ++++++++++++++++----------- tests/pass/shims/fs.rs | 15 ++++++--------- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index b57ce4e070..d440a143d7 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -324,6 +324,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { bug!("No field named {} in type {}", name, base.layout().ty); } + fn try_project_field_named>( + &self, + base: &P, + name: &str, + ) -> InterpResult<'tcx, Option

> { + let this = self.eval_context_ref(); + let adt = base.layout().ty.ty_adt_def().unwrap(); + for (idx, field) in adt.non_enum_variant().fields.iter().enumerate() { + if field.name.as_str() == name { + return interp_ok(Some(this.project_field(base, idx)?)); + } + } + interp_ok(None) + } + /// Search if `base` (which must be a struct or union type) contains the `name` field. fn projectable_has_field>( &self, diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 387459be20..1b2ea64802 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -1072,7 +1072,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Some(Ok(dir_entry)) => { // Write the directory entry into a newly allocated buffer. // The name is written with write_bytes, while the rest of the - // dirent64 struct is written using write_int_fields. + // dirent64 (or dirent) struct is written using write_int_fields. // For reference: // pub struct dirent64 { @@ -1082,6 +1082,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // pub d_type: c_uchar, // pub d_name: [c_char; 256], // } + // + // pub struct dirent { + // pub d_ino: ino64_t, + // pub d_off: off64_t, + // pub d_reclen: c_ushort, + // pub d_name: [c_char; 3], + // } let mut name = dir_entry.file_name(); // not a Path as there are no separators! name.push("\0"); // Add a NUL terminator @@ -1095,11 +1102,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { this.libc_ty_layout("dirent") }; - let d_name_offset = if is_linux { - dirent64_layout.fields.offset(4 /* d_name */).bytes() - } else { - dirent64_layout.fields.offset(3 /* d_name */).bytes() - }; + let fields = &dirent64_layout.fields; + let fcount = (*fields).count().checked_sub(1).expect("invalid count"); + let d_name_offset = (*fields).offset(fcount).bytes(); let size = d_name_offset.strict_add(name_len); let entry = this.allocate_ptr( @@ -1122,11 +1127,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &this.ptr_to_mplace(entry, dirent64_layout), )?; - if is_linux { - this.write_int_fields_named( - &[("d_type", file_type.into())], - &this.ptr_to_mplace(entry, dirent64_layout), - )?; + if let Some(d_type) = this.try_project_field_named( + &this.ptr_to_mplace(entry, dirent64_layout), + "d_type", + )? { + this.write_int(file_type, &d_type)?; } let name_ptr = entry.wrapping_offset(Size::from_bytes(d_name_offset), this); diff --git a/tests/pass/shims/fs.rs b/tests/pass/shims/fs.rs index c3653d6657..0481a8f3dc 100644 --- a/tests/pass/shims/fs.rs +++ b/tests/pass/shims/fs.rs @@ -276,15 +276,12 @@ fn test_directory() { .collect::>() ); // Deleting the directory should fail, since it is not empty. - let errno = if cfg!(any(target_os = "solaris", target_os = "illumos")) { - // Solaris/Illumos `rmdir` call set errno to EEXIST if directory contains - // other entries than `.` and `..`. - // https://docs.oracle.com/cd/E86824_01/html/E54765/rmdir-2.html - ErrorKind::AlreadyExists - } else { - ErrorKind::DirectoryNotEmpty - }; - assert_eq!(errno, remove_dir(&dir_path).unwrap_err().kind()); + + // Solaris/Illumos `rmdir` call set errno to EEXIST if directory contains + // other entries than `.` and `..`. + // https://docs.oracle.com/cd/E86824_01/html/E54765/rmdir-2.html + let err = remove_dir(&dir_path).unwrap_err().kind(); + assert!(err == ErrorKind::AlreadyExists || err == ErrorKind::DirectoryNotEmpty); // Clean up the files in the directory remove_file(&path_1).unwrap(); remove_file(&path_2).unwrap();