Skip to content

Commit

Permalink
addressing remarks
Browse files Browse the repository at this point in the history
  • Loading branch information
devnexen committed Dec 5, 2024
1 parent a851fbf commit 15d8b58
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 20 deletions.
15 changes: 15 additions & 0 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<P: Projectable<'tcx, Provenance>>(
&self,
base: &P,
name: &str,
) -> InterpResult<'tcx, Option<P>> {
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<P: Projectable<'tcx, Provenance>>(
&self,
Expand Down
27 changes: 16 additions & 11 deletions src/shims/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand All @@ -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(
Expand All @@ -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);
Expand Down
15 changes: 6 additions & 9 deletions tests/pass/shims/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,12 @@ fn test_directory() {
.collect::<BTreeMap<_, _>>()
);
// 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();
Expand Down

0 comments on commit 15d8b58

Please sign in to comment.