Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test if reserved filenames are allowed in Windows #10322

Merged
merged 5 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/cargo-test-support/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@ termcolor = "1.1.2"
toml_edit = { version = "0.14.3", features = ["serde", "easy", "perf"] }
url = "2.2.2"

[target.'cfg(windows)'.dependencies]
winapi = "0.3"

[features]
deny-warnings = []
58 changes: 58 additions & 0 deletions crates/cargo-test-support/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,61 @@ pub fn sysroot() -> String {
let sysroot = String::from_utf8(output.stdout).unwrap();
sysroot.trim().to_string()
}

/// Returns true if names such as aux.* are allowed.
///
/// Traditionally, Windows did not allow a set of file names (see `is_windows_reserved`
/// for a list). More recent versions of Windows have relaxed this restriction. This test
/// determines whether we are running in a mode that allows Windows reserved names.
#[cfg(windows)]
pub fn windows_reserved_names_are_allowed() -> bool {
eholk marked this conversation as resolved.
Show resolved Hide resolved
use cargo_util::is_ci;

// Ensure tests still run in CI until we need to migrate.
if is_ci() {
return false;
}

use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::ptr;
use winapi::um::fileapi::GetFullPathNameW;

let test_file_name: Vec<_> = OsStr::new("aux.rs").encode_wide().collect();

let buffer_length =
unsafe { GetFullPathNameW(test_file_name.as_ptr(), 0, ptr::null_mut(), ptr::null_mut()) };

if buffer_length == 0 {
// This means the call failed, so we'll conservatively assume reserved names are not allowed.
return false;
}

let mut buffer = vec![0u16; buffer_length as usize];

let result = unsafe {
GetFullPathNameW(
test_file_name.as_ptr(),
buffer_length,
buffer.as_mut_ptr(),
ptr::null_mut(),
)
};

if result == 0 {
// Once again, conservatively assume reserved names are not allowed if the
// GetFullPathNameW call failed.
return false;
}

// Under the old rules, a file name like aux.rs would get converted into \\.\aux, so
// we detect this case by checking if the string starts with \\.\
//
// Otherwise, the filename will be something like C:\Users\Foo\Documents\aux.rs
let prefix: Vec<_> = OsStr::new("\\\\.\\").encode_wide().collect();
if buffer.starts_with(&prefix) {
false
} else {
true
}
}
6 changes: 6 additions & 0 deletions tests/testsuite/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,12 @@ src/lib.rs
#[cargo_test]
#[cfg(windows)]
fn reserved_windows_name() {
// If we are running on a version of Windows that allows these reserved filenames,
// skip this test.
if paths::windows_reserved_names_are_allowed() {
return;
}

Package::new("bar", "1.0.0")
.file("src/lib.rs", "pub mod aux;")
.file("src/aux.rs", "")
Expand Down