From bccec41ea5889fd95f760486fdbd9ebfb9ae940e Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 12 Nov 2024 21:52:57 +0000 Subject: [PATCH] filesystem support for solarish. close #3890 --- ci/ci.sh | 4 +- src/shims/unix/freebsd/foreign_items.rs | 8 +-- src/shims/unix/fs.rs | 75 +++++++++++++++--------- src/shims/unix/macos/foreign_items.rs | 8 +-- src/shims/unix/solarish/foreign_items.rs | 26 ++++++++ tests/pass/shims/fs.rs | 7 ++- 6 files changed, 89 insertions(+), 39 deletions(-) diff --git a/ci/ci.sh b/ci/ci.sh index 1e5a2847c6..8e6e31bee4 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -152,8 +152,8 @@ case $HOST_TARGET in UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe - TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe - TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe + TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs + TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std diff --git a/src/shims/unix/freebsd/foreign_items.rs b/src/shims/unix/freebsd/foreign_items.rs index 1346d8de7e..b69ac4e4cd 100644 --- a/src/shims/unix/freebsd/foreign_items.rs +++ b/src/shims/unix/freebsd/foreign_items.rs @@ -53,25 +53,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "stat" | "stat@FBSD_1.0" => { let [path, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_stat(path, buf)?; + let result = this.macos_fbsd_solaris_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat@FBSD_1.0" => { let [path, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_lstat(path, buf)?; + let result = this.macos_fbsd_solaris_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat@FBSD_1.0" => { let [fd, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_fstat(fd, buf)?; + let result = this.macos_fbsd_solaris_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r@FBSD_1.0" => { let [dirp, entry, result] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; + let result = this.macos_fbsd_solaris_readdir_r(dirp, entry, result)?; this.write_scalar(result, dest)?; } diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 091def7ac6..0edc5ba895 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -265,47 +265,59 @@ impl FileDescription for FileHandle { impl<'tcx> EvalContextExtPrivate<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn macos_stat_write_buf( + fn macos_fbsd_solaris_write_buf( &mut self, metadata: FileMetadata, buf_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let mode: u16 = metadata.mode.to_u16()?; - let (access_sec, access_nsec) = metadata.accessed.unwrap_or((0, 0)); let (created_sec, created_nsec) = metadata.created.unwrap_or((0, 0)); let (modified_sec, modified_nsec) = metadata.modified.unwrap_or((0, 0)); + let mode = metadata.mode.to_uint(this.libc_ty_layout("mode_t").size)?; let buf = this.deref_pointer_as(buf_op, this.libc_ty_layout("stat"))?; - this.write_int_fields_named( &[ ("st_dev", 0), - ("st_mode", mode.into()), + ("st_mode", mode.try_into().unwrap()), ("st_nlink", 0), ("st_ino", 0), ("st_uid", 0), ("st_gid", 0), ("st_rdev", 0), ("st_atime", access_sec.into()), - ("st_atime_nsec", access_nsec.into()), ("st_mtime", modified_sec.into()), - ("st_mtime_nsec", modified_nsec.into()), ("st_ctime", 0), - ("st_ctime_nsec", 0), - ("st_birthtime", created_sec.into()), - ("st_birthtime_nsec", created_nsec.into()), ("st_size", metadata.size.into()), ("st_blocks", 0), ("st_blksize", 0), - ("st_flags", 0), - ("st_gen", 0), ], &buf, )?; + if matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { + this.write_int_fields_named( + &[ + ("st_atime_nsec", access_nsec.into()), + ("st_mtime_nsec", modified_nsec.into()), + ("st_ctime_nsec", 0), + ("st_birthtime", created_sec.into()), + ("st_birthtime_nsec", created_nsec.into()), + ("st_flags", 0), + ("st_gen", 0), + ], + &buf, + )?; + } + + if matches!(&*this.tcx.sess.target.os, "solaris" | "illumos") { + // FIXME: libc crate, update stat struct, as `st_fstype` will be uninitialised + // https://github.com/rust-lang/libc/pull/4145 + //this.write_int_fields_named(&[("st_fstype", 0)], &buf)?; + } + interp_ok(0) } @@ -648,15 +660,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn macos_fbsd_stat( + fn macos_fbsd_solaris_stat( &mut self, path_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { - panic!("`macos_fbsd_stat` should not be called on {}", this.tcx.sess.target.os); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") { + panic!("`macos_fbsd_solaris_stat` should not be called on {}", this.tcx.sess.target.os); } let path_scalar = this.read_pointer(path_op)?; @@ -674,19 +686,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) } // `lstat` is used to get symlink metadata. - fn macos_fbsd_lstat( + fn macos_fbsd_solaris_lstat( &mut self, path_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { - panic!("`macos_fbsd_lstat` should not be called on {}", this.tcx.sess.target.os); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") { + panic!( + "`macos_fbsd_solaris_lstat` should not be called on {}", + this.tcx.sess.target.os + ); } let path_scalar = this.read_pointer(path_op)?; @@ -703,18 +718,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) } - fn macos_fbsd_fstat( + fn macos_fbsd_solaris_fstat( &mut self, fd_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { - panic!("`macos_fbsd_fstat` should not be called on {}", this.tcx.sess.target.os); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") { + panic!( + "`macos_fbsd_solaris_fstat` should not be called on {}", + this.tcx.sess.target.os + ); } let fd = this.read_scalar(fd_op)?.to_i32()?; @@ -730,7 +748,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(metadata) => metadata, Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) } fn linux_statx( @@ -1112,7 +1130,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_maybe_pointer(entry.unwrap_or_else(Pointer::null), this)) } - fn macos_fbsd_readdir_r( + fn macos_fbsd_solaris_readdir_r( &mut self, dirp_op: &OpTy<'tcx>, entry_op: &OpTy<'tcx>, @@ -1120,8 +1138,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { - panic!("`macos_fbsd_readdir_r` should not be called on {}", this.tcx.sess.target.os); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") { + panic!( + "`macos_fbsd_solaris_readdir_r` should not be called on {}", + this.tcx.sess.target.os + ); } let dirp = this.read_target_usize(dirp_op)?; diff --git a/src/shims/unix/macos/foreign_items.rs b/src/shims/unix/macos/foreign_items.rs index 003025916c..3d52c58124 100644 --- a/src/shims/unix/macos/foreign_items.rs +++ b/src/shims/unix/macos/foreign_items.rs @@ -40,19 +40,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "stat" | "stat64" | "stat$INODE64" => { let [path, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_stat(path, buf)?; + let result = this.macos_fbsd_solaris_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" | "lstat$INODE64" => { let [path, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_lstat(path, buf)?; + let result = this.macos_fbsd_solaris_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" | "fstat$INODE64" => { let [fd, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_fstat(fd, buf)?; + let result = this.macos_fbsd_solaris_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "opendir$INODE64" => { @@ -64,7 +64,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "readdir_r" | "readdir_r$INODE64" => { let [dirp, entry, result] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; + let result = this.macos_fbsd_solaris_readdir_r(dirp, entry, result)?; this.write_scalar(result, dest)?; } "realpath$DARWIN_EXTSN" => { diff --git a/src/shims/unix/solarish/foreign_items.rs b/src/shims/unix/solarish/foreign_items.rs index 1bbd25617e..7bb49d70ba 100644 --- a/src/shims/unix/solarish/foreign_items.rs +++ b/src/shims/unix/solarish/foreign_items.rs @@ -57,6 +57,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } + // File related shims + "stat" | "stat64" => { + let [path, buf] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_solaris_stat(path, buf)?; + this.write_scalar(result, dest)?; + } + "lstat" | "lstat64" => { + let [path, buf] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_solaris_lstat(path, buf)?; + this.write_scalar(result, dest)?; + } + "fstat" | "fstat64" => { + let [fd, buf] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_solaris_fstat(fd, buf)?; + this.write_scalar(result, dest)?; + } + "readdir_r" => { + let [dirp, entry, result] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_solaris_readdir_r(dirp, entry, result)?; + this.write_scalar(result, dest)?; + } + // Miscellaneous "___errno" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/tests/pass/shims/fs.rs b/tests/pass/shims/fs.rs index 81151f4ac4..3e514d95ee 100644 --- a/tests/pass/shims/fs.rs +++ b/tests/pass/shims/fs.rs @@ -27,8 +27,11 @@ fn main() { test_file_sync(); test_errors(); test_rename(); - test_directory(); - test_canonicalize(); + // solarish needs to support readdir/readdir64 for these tests. + if cfg!(not(any(target_os = "solaris", target_os = "illumos"))) { + test_directory(); + test_canonicalize(); + } test_from_raw_os_error(); #[cfg(unix)] test_pread_pwrite();