diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
commit | 631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch) | |
tree | a1b87c8f8cad01cf18f7c5f57a08f102771ed303 /library/std/src/sys/windows/path.rs | |
parent | Adding debian version 1.69.0+dfsg1-1. (diff) | |
download | rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.tar.xz rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.zip |
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/std/src/sys/windows/path.rs')
-rw-r--r-- | library/std/src/sys/windows/path.rs | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index beeca1917..c3573d14c 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -220,6 +220,19 @@ fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) { /// /// This path may or may not have a verbatim prefix. pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> { + let path = to_u16s(path)?; + get_long_path(path, true) +} + +/// Get a normalized absolute path that can bypass path length limits. +/// +/// Setting prefer_verbatim to true suggests a stronger preference for verbatim +/// paths even when not strictly necessary. This allows the Windows API to avoid +/// repeating our work. However, if the path may be given back to users or +/// passed to other application then it's preferable to use non-verbatim paths +/// when possible. Non-verbatim paths are better understood by users and handled +/// by more software. +pub(crate) fn get_long_path(mut path: Vec<u16>, prefer_verbatim: bool) -> io::Result<Vec<u16>> { // Normally the MAX_PATH is 260 UTF-16 code units (including the NULL). // However, for APIs such as CreateDirectory[1], the limit is 248. // @@ -243,7 +256,6 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> { // \\?\UNC\ const UNC_PREFIX: &[u16] = &[SEP, SEP, QUERY, SEP, U, N, C, SEP]; - let mut path = to_u16s(path)?; if path.starts_with(VERBATIM_PREFIX) || path.starts_with(NT_PREFIX) || path == &[0] { // Early return for paths that are already verbatim or empty. return Ok(path); @@ -275,29 +287,34 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> { |mut absolute| { path.clear(); - // Secondly, add the verbatim prefix. This is easier here because we know the - // path is now absolute and fully normalized (e.g. `/` has been changed to `\`). - let prefix = match absolute { - // C:\ => \\?\C:\ - [_, COLON, SEP, ..] => VERBATIM_PREFIX, - // \\.\ => \\?\ - [SEP, SEP, DOT, SEP, ..] => { - absolute = &absolute[4..]; - VERBATIM_PREFIX - } - // Leave \\?\ and \??\ as-is. - [SEP, SEP, QUERY, SEP, ..] | [SEP, QUERY, QUERY, SEP, ..] => &[], - // \\ => \\?\UNC\ - [SEP, SEP, ..] => { - absolute = &absolute[2..]; - UNC_PREFIX - } - // Anything else we leave alone. - _ => &[], - }; - - path.reserve_exact(prefix.len() + absolute.len() + 1); - path.extend_from_slice(prefix); + // Only prepend the prefix if needed. + if prefer_verbatim || absolute.len() + 1 >= LEGACY_MAX_PATH { + // Secondly, add the verbatim prefix. This is easier here because we know the + // path is now absolute and fully normalized (e.g. `/` has been changed to `\`). + let prefix = match absolute { + // C:\ => \\?\C:\ + [_, COLON, SEP, ..] => VERBATIM_PREFIX, + // \\.\ => \\?\ + [SEP, SEP, DOT, SEP, ..] => { + absolute = &absolute[4..]; + VERBATIM_PREFIX + } + // Leave \\?\ and \??\ as-is. + [SEP, SEP, QUERY, SEP, ..] | [SEP, QUERY, QUERY, SEP, ..] => &[], + // \\ => \\?\UNC\ + [SEP, SEP, ..] => { + absolute = &absolute[2..]; + UNC_PREFIX + } + // Anything else we leave alone. + _ => &[], + }; + + path.reserve_exact(prefix.len() + absolute.len() + 1); + path.extend_from_slice(prefix); + } else { + path.reserve_exact(absolute.len() + 1); + } path.extend_from_slice(absolute); path.push(0); }, |