Make sure CreateDirectoryW works for path lengths > 247
This commit is contained in:
@@ -1411,3 +1411,32 @@ fn symlink_hard_link() {
|
|||||||
// "hard_link" should still appear as a symlink.
|
// "hard_link" should still appear as a symlink.
|
||||||
assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink());
|
assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensure `fs::create_dir` works on Windows with longer paths.
|
||||||
|
#[test]
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn create_dir_long_paths() {
|
||||||
|
use crate::{ffi::OsStr, iter, os::windows::ffi::OsStrExt};
|
||||||
|
const PATH_LEN: usize = 247;
|
||||||
|
|
||||||
|
let tmpdir = tmpdir();
|
||||||
|
let mut path = tmpdir.path().to_path_buf();
|
||||||
|
path.push("a");
|
||||||
|
let mut path = path.into_os_string();
|
||||||
|
|
||||||
|
let utf16_len = path.encode_wide().count();
|
||||||
|
if utf16_len >= PATH_LEN {
|
||||||
|
// Skip the test in the unlikely event the local user has a long temp directory path.
|
||||||
|
// This should not affect CI.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Increase the length of the path.
|
||||||
|
path.extend(iter::repeat(OsStr::new("a")).take(PATH_LEN - utf16_len));
|
||||||
|
|
||||||
|
// This should succeed.
|
||||||
|
fs::create_dir(&path).unwrap();
|
||||||
|
|
||||||
|
// This will fail if the path isn't converted to verbatim.
|
||||||
|
path.push("a");
|
||||||
|
fs::create_dir(&path).unwrap();
|
||||||
|
}
|
||||||
|
|||||||
@@ -150,7 +150,11 @@ fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) {
|
|||||||
///
|
///
|
||||||
/// This path may or may not have a verbatim prefix.
|
/// This path may or may not have a verbatim prefix.
|
||||||
pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> {
|
pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> {
|
||||||
const LEGACY_MAX_PATH: usize = 260;
|
// Normally the MAX path is 260 UTF-16 code units (including the NULL).
|
||||||
|
// However, for APIs such as CreateDirectory[1], the limit is 248.
|
||||||
|
//
|
||||||
|
// [1]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createdirectorya#parameters
|
||||||
|
const LEGACY_MAX_PATH: usize = 248;
|
||||||
// UTF-16 encoded code points, used in parsing and building UTF-16 paths.
|
// UTF-16 encoded code points, used in parsing and building UTF-16 paths.
|
||||||
// All of these are in the ASCII range so they can be cast directly to `u16`.
|
// All of these are in the ASCII range so they can be cast directly to `u16`.
|
||||||
const SEP: u16 = b'\\' as _;
|
const SEP: u16 = b'\\' as _;
|
||||||
|
|||||||
@@ -81,6 +81,13 @@ fn verbatim() {
|
|||||||
check(r"\\server\share", r"\\server\share");
|
check(r"\\server\share", r"\\server\share");
|
||||||
check(r"\\.\COM1", r"\\.\COM1");
|
check(r"\\.\COM1", r"\\.\COM1");
|
||||||
|
|
||||||
|
// Check that paths of length 247 are converted to verbatim.
|
||||||
|
// This is necessary for `CreateDirectory`.
|
||||||
|
check(
|
||||||
|
r"C:\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
r"\\?\C:\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
);
|
||||||
|
|
||||||
// Make sure opening a drive will work.
|
// Make sure opening a drive will work.
|
||||||
check("Z:", "Z:");
|
check("Z:", "Z:");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user