pub fn is_glob_pattern<T: AsRef<str>>(name: T) -> bool {
name.as_ref().contains(&['*', '?', '[', ']'][..])
}
+
+/// Returns true if names such as aux.* are allowed.
+///
+/// Traditionally, Windows did not allow a set of file names (see `is_windows_reserved_name`
+/// 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.
+pub fn windows_reserved_names_are_allowed() -> bool {
+ #[cfg(windows)]
+ {
+ 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
+ }
+ }
+ #[cfg(not(windows))]
+ true
+}
.run();
}
-/// Certain versions of Windows 11 have removed the restriction on filenames. To detect whether
-/// this is the case, we try to create a file with a reserved name.
-#[cfg(windows)]
-fn windows_reserved_names_are_allowed() -> bool {
- let test_file = paths::home().join("aux.rs");
- if File::create(&test_file).is_err() {
- return false;
- }
- let _ = fs::remove_file(test_file);
- true
-}
-
#[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 windows_reserved_names_are_allowed() {
+ if cargo::util::restricted_names::windows_reserved_names_are_allowed() {
return;
}