Skip to content

Commit 7259757

Browse files
committed
Auto merge of #10322 - eholk:reserved-windows-name, r=ehuss
Test if reserved filenames are allowed in Windows Recent versions of Windows have removed the limitation on filenames like `aux` or `con`. This change allows the `package::reserved_windows_name` to still pass by first trying to create a file with a reserved name to see if Windows supports it. If so, it skips the rest of the test. Otherwise, we keep the same behavior as before.
2 parents 471b80d + 8de9adf commit 7259757

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

crates/cargo-test-support/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,8 @@ termcolor = "1.1.2"
2525
toml_edit = { version = "0.14.3", features = ["serde", "easy", "perf"] }
2626
url = "2.2.2"
2727

28+
[target.'cfg(windows)'.dependencies]
29+
winapi = "0.3"
30+
2831
[features]
2932
deny-warnings = []

crates/cargo-test-support/src/paths.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,61 @@ pub fn sysroot() -> String {
287287
let sysroot = String::from_utf8(output.stdout).unwrap();
288288
sysroot.trim().to_string()
289289
}
290+
291+
/// Returns true if names such as aux.* are allowed.
292+
///
293+
/// Traditionally, Windows did not allow a set of file names (see `is_windows_reserved`
294+
/// for a list). More recent versions of Windows have relaxed this restriction. This test
295+
/// determines whether we are running in a mode that allows Windows reserved names.
296+
#[cfg(windows)]
297+
pub fn windows_reserved_names_are_allowed() -> bool {
298+
use cargo_util::is_ci;
299+
300+
// Ensure tests still run in CI until we need to migrate.
301+
if is_ci() {
302+
return false;
303+
}
304+
305+
use std::ffi::OsStr;
306+
use std::os::windows::ffi::OsStrExt;
307+
use std::ptr;
308+
use winapi::um::fileapi::GetFullPathNameW;
309+
310+
let test_file_name: Vec<_> = OsStr::new("aux.rs").encode_wide().collect();
311+
312+
let buffer_length =
313+
unsafe { GetFullPathNameW(test_file_name.as_ptr(), 0, ptr::null_mut(), ptr::null_mut()) };
314+
315+
if buffer_length == 0 {
316+
// This means the call failed, so we'll conservatively assume reserved names are not allowed.
317+
return false;
318+
}
319+
320+
let mut buffer = vec![0u16; buffer_length as usize];
321+
322+
let result = unsafe {
323+
GetFullPathNameW(
324+
test_file_name.as_ptr(),
325+
buffer_length,
326+
buffer.as_mut_ptr(),
327+
ptr::null_mut(),
328+
)
329+
};
330+
331+
if result == 0 {
332+
// Once again, conservatively assume reserved names are not allowed if the
333+
// GetFullPathNameW call failed.
334+
return false;
335+
}
336+
337+
// Under the old rules, a file name like aux.rs would get converted into \\.\aux, so
338+
// we detect this case by checking if the string starts with \\.\
339+
//
340+
// Otherwise, the filename will be something like C:\Users\Foo\Documents\aux.rs
341+
let prefix: Vec<_> = OsStr::new("\\\\.\\").encode_wide().collect();
342+
if buffer.starts_with(&prefix) {
343+
false
344+
} else {
345+
true
346+
}
347+
}

tests/testsuite/package.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,6 +2009,12 @@ src/lib.rs
20092009
#[cargo_test]
20102010
#[cfg(windows)]
20112011
fn reserved_windows_name() {
2012+
// If we are running on a version of Windows that allows these reserved filenames,
2013+
// skip this test.
2014+
if paths::windows_reserved_names_are_allowed() {
2015+
return;
2016+
}
2017+
20122018
Package::new("bar", "1.0.0")
20132019
.file("src/lib.rs", "pub mod aux;")
20142020
.file("src/aux.rs", "")

0 commit comments

Comments
 (0)