about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-05-26 16:31:38 +0200
committerRalf Jung <post@ralfj.de>2024-05-26 17:20:28 +0200
commit350f5c88dbe97605d9f4e0cac037a0b9751d06ef (patch)
tree8b08111c63c2a01897dcf2854c88781fdc770f02
parent331bb3f10d755f4c7fdf29b21d7a957a76f76c1a (diff)
downloadrust-350f5c88dbe97605d9f4e0cac037a0b9751d06ef.tar.gz
rust-350f5c88dbe97605d9f4e0cac037a0b9751d06ef.zip
unix/fs: a bit of cleanup in macos_fbsd_readdir_r
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs68
1 files changed, 33 insertions, 35 deletions
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 82bc49536b0..5b0c1b2bafe 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -990,7 +990,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // The name is written with write_os_str_to_c_str, while the rest of the
                 // dirent struct is written using write_int_fields.
 
-                // For reference:
+                // For reference, on macOS this looks like:
                 // pub struct dirent {
                 //     pub d_ino: u64,
                 //     pub d_seekoff: u64,
@@ -1025,40 +1025,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                 let file_type = this.file_type_to_d_type(dir_entry.file_type())?;
 
-                // macOS offset field is d_seekoff
-                if this.projectable_has_field(&entry_place, "d_seekoff") {
-                    this.write_int_fields_named(
-                        &[
-                            ("d_ino", ino.into()),
-                            ("d_seekoff", 0),
-                            ("d_reclen", 0),
-                            ("d_namlen", file_name_len.into()),
-                            ("d_type", file_type.into()),
-                        ],
-                        &entry_place,
-                    )?;
-                } else if this.projectable_has_field(&entry_place, "d_off") {
-                    // freebsd 12 and onwards had added the d_off field
-                    this.write_int_fields_named(
-                        &[
-                            ("d_fileno", ino.into()),
-                            ("d_off", 0),
-                            ("d_reclen", 0),
-                            ("d_type", file_type.into()),
-                            ("d_namlen", file_name_len.into()),
-                        ],
-                        &entry_place,
-                    )?;
-                } else {
-                    this.write_int_fields_named(
-                        &[
-                            ("d_fileno", ino.into()),
-                            ("d_reclen", 0),
-                            ("d_type", file_type.into()),
-                            ("d_namlen", file_name_len.into()),
-                        ],
-                        &entry_place,
-                    )?;
+                // Common fields.
+                this.write_int_fields_named(
+                    &[
+                        ("d_reclen", 0),
+                        ("d_namlen", file_name_len.into()),
+                        ("d_type", file_type.into()),
+                    ],
+                    &entry_place,
+                )?;
+                // Special fields.
+                match &*this.tcx.sess.target.os {
+                    "macos" => {
+                        #[rustfmt::skip]
+                        this.write_int_fields_named(
+                            &[
+                                ("d_ino", ino.into()),
+                                ("d_seekoff", 0),
+                            ],
+                            &entry_place,
+                        )?;
+                    }
+                    "freebsd" => {
+                        this.write_int(ino, &this.project_field_named(&entry_place, "d_fileno")?)?;
+                        // `d_off` only exists on FreeBSD 12+, but we support v11 as well.
+                        // `libc` uses a build script to determine which version of the API to use,
+                        // and cross-builds always end up using v11.
+                        // To support both v11 and v12+, we dynamically check whether the field exists.
+                        if this.projectable_has_field(&entry_place, "d_off") {
+                            this.write_int(0, &this.project_field_named(&entry_place, "d_off")?)?;
+                        }
+                    }
+                    _ => unreachable!(),
                 }
 
                 let result_place = this.deref_pointer(result_op)?;