-
Notifications
You must be signed in to change notification settings - Fork 349
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #3591 - RalfJung:win-symlink-trouble, r=RalfJung
do not run symlink tests on Windows hosts Fixes #3587
- Loading branch information
Showing
6 changed files
with
144 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// 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::fs; | ||
use std::io::{Error, ErrorKind}; | ||
use std::os::unix::ffi::OsStrExt; | ||
use std::path::PathBuf; | ||
|
||
#[path = "../../utils/mod.rs"] | ||
mod utils; | ||
|
||
/// Prepare: compute filename and make sure the file does not exist. | ||
fn prepare(filename: &str) -> PathBuf { | ||
let path = utils::tmp().join(filename); | ||
// Clean the paths for robustness. | ||
fs::remove_file(&path).ok(); | ||
path | ||
} | ||
|
||
/// Prepare like above, and also write some initial content to the file. | ||
fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf { | ||
let path = prepare(filename); | ||
fs::write(&path, content).unwrap(); | ||
path | ||
} | ||
|
||
fn main() { | ||
let bytes = b"Hello, World!\n"; | ||
let path = prepare_with_content("miri_test_fs_link_target.txt", bytes); | ||
let expected_path = path.as_os_str().as_bytes(); | ||
|
||
let symlink_path = 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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// 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::fs::{self, read_link, remove_file, File}; | ||
use std::io::{Read, Result}; | ||
use std::path::{Path, PathBuf}; | ||
|
||
#[path = "../../utils/mod.rs"] | ||
mod utils; | ||
|
||
/// Prepare: compute filename and make sure the file does not exist. | ||
fn prepare(filename: &str) -> PathBuf { | ||
let path = utils::tmp().join(filename); | ||
// Clean the paths for robustness. | ||
fs::remove_file(&path).ok(); | ||
path | ||
} | ||
|
||
/// Prepare like above, and also write some initial content to the file. | ||
fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf { | ||
let path = prepare(filename); | ||
fs::write(&path, content).unwrap(); | ||
path | ||
} | ||
|
||
fn check_metadata(bytes: &[u8], path: &Path) -> Result<()> { | ||
// Test that the file metadata is correct. | ||
let metadata = path.metadata()?; | ||
// `path` should point to a file. | ||
assert!(metadata.is_file()); | ||
// The size of the file must be equal to the number of written bytes. | ||
assert_eq!(bytes.len() as u64, metadata.len()); | ||
Ok(()) | ||
} | ||
|
||
fn main() { | ||
let bytes = b"Hello, World!\n"; | ||
let path = prepare_with_content("miri_test_fs_link_target.txt", bytes); | ||
let symlink_path = prepare("miri_test_fs_symlink.txt"); | ||
|
||
// Creating a symbolic link should succeed. | ||
#[cfg(unix)] | ||
std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); | ||
#[cfg(windows)] | ||
std::os::windows::fs::symlink_file(&path, &symlink_path).unwrap(); | ||
// Test that the symbolic link has the same contents as the file. | ||
let mut symlink_file = File::open(&symlink_path).unwrap(); | ||
let mut contents = Vec::new(); | ||
symlink_file.read_to_end(&mut contents).unwrap(); | ||
assert_eq!(bytes, contents.as_slice()); | ||
|
||
// Test that metadata of a symbolic link (i.e., the file it points to) is correct. | ||
check_metadata(bytes, &symlink_path).unwrap(); | ||
// Test that the metadata of a symbolic link is correct when not following it. | ||
assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink()); | ||
// Check that we can follow the link. | ||
assert_eq!(read_link(&symlink_path).unwrap(), path); | ||
// Removing symbolic link should succeed. | ||
remove_file(&symlink_path).unwrap(); | ||
|
||
// Removing file should succeed. | ||
remove_file(&path).unwrap(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters