diff --git a/src/helpers.rs b/src/helpers.rs index 9f718b0665..ed761c6d0c 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -225,7 +225,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { bug!("No field named {} in type {}", name, base.layout().ty); } - fn project_field_hasname>( + /// Search if Project (which must be a struct or union type) contains the `name` field. + fn project_field_has_field>( &self, base: &P, name: &str, diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 4ce731e3b5..35036ce078 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -158,13 +158,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let fd = this.read_scalar(fd)?.to_i32()?; let offset = this.read_scalar(offset)?.to_i64()?; let whence = this.read_scalar(whence)?.to_i32()?; - let result = this.lseek64(fd, offset, whence)?; + let result = this.lseek64(fd, offset.into(), whence)?; this.write_scalar(result, dest)?; } "lseek" => { let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let fd = this.read_scalar(fd)?.to_i32()?; - let offset = this.read_target_isize(offset)?; + let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; let whence = this.read_scalar(whence)?.to_i32()?; let result = this.lseek64(fd, offset, whence)?; this.write_scalar(result, dest)?; diff --git a/src/shims/unix/freebsd/foreign_items.rs b/src/shims/unix/freebsd/foreign_items.rs index 133c916a9d..64094ac307 100644 --- a/src/shims/unix/freebsd/foreign_items.rs +++ b/src/shims/unix/freebsd/foreign_items.rs @@ -65,8 +65,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // File related shims - // For those, we both intercept `call` and `call@FBSD_1.0` symbols cases - // since freebsd 12 they can be expected + // For those, we both intercept `func` and `call@FBSD_1.0` symbols cases + // since freebsd 12 the former form can be expected. "stat" | "stat@FBSD_1.0" => { let [path, buf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index afdf448449..b5e29afabb 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -828,7 +828,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn lseek64( &mut self, fd: i32, - offset: i64, + offset: i128, whence: i32, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); @@ -838,9 +838,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let seek_from = if whence == this.eval_libc_i32("SEEK_SET") { SeekFrom::Start(u64::try_from(offset).unwrap()) } else if whence == this.eval_libc_i32("SEEK_CUR") { - SeekFrom::Current(offset) + SeekFrom::Current(i64::try_from(offset).unwrap()) } else if whence == this.eval_libc_i32("SEEK_END") { - SeekFrom::End(offset) + SeekFrom::End(i64::try_from(offset).unwrap()) } else { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; @@ -852,7 +852,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) { let result = file_descriptor .seek(communicate, seek_from)? - .map(|offset| offset.try_into().unwrap()); + .map(|offset| i64::try_from(offset).unwrap()); this.try_unwrap_io_result(result)? } else { this.handle_not_found()? @@ -1454,7 +1454,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let file_type = this.file_type_to_d_type(dir_entry.file_type())?; - if this.tcx.sess.target.os == "macos" { + // macOS offset field is d_seekoff + if this.project_field_has_field(&entry_place, "d_seekoff") { this.write_int_fields_named( &[ ("d_ino", ino.into()), @@ -1466,7 +1467,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &entry_place, )?; } else { - if this.project_field_hasname(&entry_place, "d_off") { + // freebsd 12 and onwards had added the d_off field + if this.project_field_has_field(&entry_place, "d_off") { this.write_int_fields_named( &[ ("d_fileno", ino.into()), diff --git a/tests/pass-dep/shims/libc-fs.rs b/tests/pass-dep/shims/libc-fs.rs index 3810abe285..697970a088 100644 --- a/tests/pass-dep/shims/libc-fs.rs +++ b/tests/pass-dep/shims/libc-fs.rs @@ -23,7 +23,6 @@ fn main() { test_file_open_unix_extra_third_arg(); #[cfg(target_os = "linux")] test_o_tmpfile_flag(); - #[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] test_posix_mkstemp(); } @@ -154,7 +153,6 @@ fn test_o_tmpfile_flag() { ); } -#[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] fn test_posix_mkstemp() { use std::ffi::OsStr; use std::os::unix::io::FromRawFd; diff --git a/tests/pass/shims/fs.rs b/tests/pass/shims/fs.rs index aae57bec68..97c61505d2 100644 --- a/tests/pass/shims/fs.rs +++ b/tests/pass/shims/fs.rs @@ -13,22 +13,16 @@ mod utils; fn main() { test_path_conversion(); - #[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] test_file(); - #[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] test_file_clone(); test_file_create_new(); - #[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] test_seek(); test_metadata(); - #[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] test_file_set_len(); test_file_sync(); - #[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] test_symlink(); test_errors(); test_rename(); - #[cfg(not(target_os = "freebsd"))] test_directory(); test_canonicalize(); test_from_raw_os_error(); @@ -64,8 +58,6 @@ fn test_path_conversion() { assert!(tmp.is_dir(), "{:?} is not a directory", tmp); } -// FIXME: lseek64 does not work yet on freebsd 32 bits -#[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] fn test_file() { use std::io::{IsTerminal, Read}; let bytes = b"Hello, World!\n"; @@ -94,7 +86,6 @@ fn test_file() { remove_file(&path).unwrap(); } -#[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] fn test_file_clone() { use std::io::Read; let bytes = b"Hello, World!\n"; @@ -184,7 +175,6 @@ fn test_metadata() { remove_file(&path).unwrap(); } -#[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] fn test_file_set_len() { use std::io::{Read, Seek, SeekFrom}; let bytes = b"Hello, World!\n"; @@ -229,7 +219,6 @@ fn test_file_sync() { remove_file(&path).unwrap(); } -#[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] fn test_symlink() { use std::fs::read_link; use std::io::Read; @@ -309,7 +298,6 @@ fn test_canonicalize() { remove_dir_all(&dir_path).unwrap(); } -#[cfg(not(target_os = "freebsd"))] // FIXME: freebsd does not support readdir yet fn test_directory() { use std::collections::HashMap; use std::ffi::OsString;