fh.insert_fd_with_min_fd(FileHandle { file: duplicated, writable }, start)
});
this.try_unwrap_io_result(fd_result)
+ } else if this.tcx.sess.target.target.target_os == "macos"
+ && cmd == this.eval_libc_i32("F_FULLFSYNC")?
+ {
+ if let Some(FileHandle { file, writable: _ }) = this.machine.file_handler.handles.get_mut(&fd) {
+ let result = file.sync_all();
+ this.try_unwrap_io_result(result.map(|_| 0i32))
+ } else {
+ this.handle_not_found()
+ }
} else {
throw_unsup_format!("the {:#x} command is not supported for `fcntl`)", cmd);
}
this.handle_not_found()
}
}
+
+ fn fsync(&mut self, fd_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
+ let this = self.eval_context_mut();
+
+ this.check_no_isolation("fsync")?;
+
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+ if let Some(FileHandle { file, writable: _ }) = this.machine.file_handler.handles.get_mut(&fd) {
+ let result = file.sync_all();
+ this.try_unwrap_io_result(result.map(|_| 0i32))
+ } else {
+ this.handle_not_found()
+ }
+ }
+
+ fn fdatasync(&mut self, fd_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
+ let this = self.eval_context_mut();
+
+ this.check_no_isolation("fdatasync")?;
+
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+ if let Some(FileHandle { file, writable: _ }) = this.machine.file_handler.handles.get_mut(&fd) {
+ let result = file.sync_data();
+ this.try_unwrap_io_result(result.map(|_| 0i32))
+ } else {
+ this.handle_not_found()
+ }
+ }
+
+ fn sync_file_range(
+ &mut self,
+ fd_op: OpTy<'tcx, Tag>,
+ offset_op: OpTy<'tcx, Tag>,
+ nbytes_op: OpTy<'tcx, Tag>,
+ flags_op: OpTy<'tcx, Tag>,
+ ) -> InterpResult<'tcx, i32> {
+ let this = self.eval_context_mut();
+
+ this.check_no_isolation("sync_file_range")?;
+
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+ let _offset = this.read_scalar(offset_op)?.to_i64()?;
+ let _nbytes = this.read_scalar(nbytes_op)?.to_i64()?;
+ let _flags = this.read_scalar(flags_op)?.to_u32()?;
+ if let Some(FileHandle { file, writable: _ }) = this.machine.file_handler.handles.get_mut(&fd) {
+ // In the interest of host compatibility, we conservatively ignore
+ // offset, nbytes, and flags, and sync the entire file.
+ let result = file.sync_data();
+ this.try_unwrap_io_result(result.map(|_| 0i32))
+ } else {
+ this.handle_not_found()
+ }
+ }
}
/// Extracts the number of seconds and nanoseconds elapsed between `time` and the unix epoch when
test_seek();
test_metadata();
test_file_set_len();
+ test_file_sync_all();
+ test_file_sync_data();
test_symlink();
test_errors();
test_rename();
remove_file(&path).unwrap();
}
+fn test_file_sync_all() {
+ let bytes = b"Hello, World!\n";
+ let path = prepare_with_content("miri_test_fs_sync_all.txt", bytes);
+
+ // Test that we can call sync_all (can't readily test effects of this operation)
+ let file = File::open(&path).unwrap();
+ file.sync_all().unwrap();
+
+ remove_file(&path).unwrap();
+}
+
+fn test_file_sync_data() {
+ let bytes = b"Hello, World!\n";
+ let path = prepare_with_content("miri_test_fs_sync_data.txt", bytes);
+
+ // Test that we can call sync_data (can't readily test effects of this operation)
+ let file = File::open(&path).unwrap();
+ file.sync_data().unwrap();
+
+ remove_file(&path).unwrap();
+}
+
fn test_symlink() {
let bytes = b"Hello, World!\n";
let path = prepare_with_content("miri_test_fs_link_target.txt", bytes);
use std::io::Write;
use std::os::unix::io::AsRawFd;
- let path = tmp().join("miri_test_libc.txt");
+ let path = tmp().join("miri_test_libc_posix_fadvise.txt");
// Cleanup before test
remove_file(&path).ok();
assert_eq!(result, 0);
}
+#[cfg(target_os = "linux")]
+fn test_sync_file_range() {
+ use std::fs::{remove_file, File};
+ use std::io::Write;
+ use std::os::unix::io::AsRawFd;
+
+ let path = tmp().join("miri_test_libc_sync_file_range.txt");
+ // Cleanup before test
+ remove_file(&path).ok();
+
+ // Write to a file
+ let mut file = File::create(&path).unwrap();
+ let bytes = b"Hello, World!\n";
+ file.write(bytes).unwrap();
+
+ // Test calling sync_file_range on a file.
+ let result = unsafe {
+ libc::sync_file_range(
+ file.as_raw_fd(),
+ 0,
+ 0,
+ libc::SYNC_FILE_RANGE_WAIT_BEFORE
+ | libc::SYNC_FILE_RANGE_WRITE
+ | libc::SYNC_FILE_RANGE_WAIT_AFTER,
+ )
+ };
+ drop(file);
+ remove_file(&path).unwrap();
+ assert_eq!(result, 0);
+}
+
fn test_mutex_libc_init_recursive() {
unsafe {
let mut attr: libc::pthread_mutexattr_t = std::mem::zeroed();
#[cfg(target_os = "linux")]
test_posix_fadvise();
+ #[cfg(target_os = "linux")]
+ test_sync_file_range();
+
test_mutex_libc_init_recursive();
test_mutex_libc_init_normal();
test_mutex_libc_init_errorcheck();