Auto merge of #3632 - RalfJung:readdir, r=RalfJung · rust-lang/rust@8e861c6
@@ -990,7 +990,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
990990// The name is written with write_os_str_to_c_str, while the rest of the
991991// dirent struct is written using write_int_fields.
992992993-// For reference:
993+// For reference, on macOS this looks like:
994994// pub struct dirent {
995995// pub d_ino: u64,
996996// pub d_seekoff: u64,
@@ -1025,40 +1025,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
1025102510261026let file_type = this.file_type_to_d_type(dir_entry.file_type())?;
102710271028-// macOS offset field is d_seekoff
1029-if this.projectable_has_field(&entry_place, "d_seekoff") {
1030- this.write_int_fields_named(
1031-&[
1032-("d_ino", ino.into()),
1033-("d_seekoff", 0),
1034-("d_reclen", 0),
1035-("d_namlen", file_name_len.into()),
1036-("d_type", file_type.into()),
1037-],
1038-&entry_place,
1039-)?;
1040-} else if this.projectable_has_field(&entry_place, "d_off") {
1041-// freebsd 12 and onwards had added the d_off field
1042- this.write_int_fields_named(
1043-&[
1044-("d_fileno", ino.into()),
1045-("d_off", 0),
1046-("d_reclen", 0),
1047-("d_type", file_type.into()),
1048-("d_namlen", file_name_len.into()),
1049-],
1050-&entry_place,
1051-)?;
1052-} else {
1053- this.write_int_fields_named(
1054-&[
1055-("d_fileno", ino.into()),
1056-("d_reclen", 0),
1057-("d_type", file_type.into()),
1058-("d_namlen", file_name_len.into()),
1059-],
1060-&entry_place,
1061-)?;
1028+// Common fields.
1029+ this.write_int_fields_named(
1030+&[
1031+("d_reclen", 0),
1032+("d_namlen", file_name_len.into()),
1033+("d_type", file_type.into()),
1034+],
1035+&entry_place,
1036+)?;
1037+// Special fields.
1038+match &*this.tcx.sess.target.os {
1039+"macos" => {
1040+#[rustfmt::skip]
1041+ this.write_int_fields_named(
1042+&[
1043+("d_ino", ino.into()),
1044+("d_seekoff", 0),
1045+],
1046+&entry_place,
1047+)?;
1048+}
1049+"freebsd" => {
1050+ this.write_int(ino, &this.project_field_named(&entry_place, "d_fileno")?)?;
1051+// `d_off` only exists on FreeBSD 12+, but we support v11 as well.
1052+// `libc` uses a build script to determine which version of the API to use,
1053+// and cross-builds always end up using v11.
1054+// To support both v11 and v12+, we dynamically check whether the field exists.
1055+if this.projectable_has_field(&entry_place, "d_off") {
1056+ this.write_int(0, &this.project_field_named(&entry_place, "d_off")?)?;
1057+}
1058+}
1059+ _ => unreachable!(),
10621060}
1063106110641062let result_place = this.deref_pointer(result_op)?;