| // Symlink tests are separate since they don't in general work on a Windows host. |
| //@ignore-host-windows: creating symlinks requires admin permissions on Windows |
| //@ignore-target-windows: File handling is not implemented yet |
| //@compile-flags: -Zmiri-disable-isolation |
| |
| use std::ffi::CString; |
| use std::io::{Error, ErrorKind}; |
| use std::os::unix::ffi::OsStrExt; |
| |
| #[path = "../../utils/mod.rs"] |
| mod utils; |
| |
| fn main() { |
| let bytes = b"Hello, World!\n"; |
| let path = utils::prepare_with_content("miri_test_fs_link_target.txt", bytes); |
| let expected_path = path.as_os_str().as_bytes(); |
| |
| let symlink_path = utils::prepare("miri_test_fs_symlink.txt"); |
| std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); |
| |
| // Test that the expected string gets written to a buffer of proper |
| // length, and that a trailing null byte is not written. |
| let symlink_c_str = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); |
| let symlink_c_ptr = symlink_c_str.as_ptr(); |
| |
| // Make the buf one byte larger than it needs to be, |
| // and check that the last byte is not overwritten. |
| let mut large_buf = vec![0xFF; expected_path.len() + 1]; |
| let res = |
| unsafe { libc::readlink(symlink_c_ptr, large_buf.as_mut_ptr().cast(), large_buf.len()) }; |
| // Check that the resolved path was properly written into the buf. |
| assert_eq!(&large_buf[..(large_buf.len() - 1)], expected_path); |
| assert_eq!(large_buf.last(), Some(&0xFF)); |
| assert_eq!(res, large_buf.len() as isize - 1); |
| |
| // Test that the resolved path is truncated if the provided buffer |
| // is too small. |
| let mut small_buf = [0u8; 2]; |
| let res = |
| unsafe { libc::readlink(symlink_c_ptr, small_buf.as_mut_ptr().cast(), small_buf.len()) }; |
| assert_eq!(small_buf, &expected_path[..small_buf.len()]); |
| assert_eq!(res, small_buf.len() as isize); |
| |
| // Test that we report a proper error for a missing path. |
| let bad_path = CString::new("MIRI_MISSING_FILE_NAME").unwrap(); |
| let res = unsafe { |
| libc::readlink(bad_path.as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len()) |
| }; |
| assert_eq!(res, -1); |
| assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); |
| } |