diff options
Diffstat (limited to 'library/std/src/sys')
| -rw-r--r-- | library/std/src/sys/sgx/path.rs | 7 | ||||
| -rw-r--r-- | library/std/src/sys/solid/path.rs | 7 | ||||
| -rw-r--r-- | library/std/src/sys/unix/path.rs | 45 | ||||
| -rw-r--r-- | library/std/src/sys/windows/path.rs | 16 |
4 files changed, 72 insertions, 3 deletions
diff --git a/library/std/src/sys/sgx/path.rs b/library/std/src/sys/sgx/path.rs index 840a7ae0426..9cfc61bf174 100644 --- a/library/std/src/sys/sgx/path.rs +++ b/library/std/src/sys/sgx/path.rs @@ -1,5 +1,6 @@ use crate::ffi::OsStr; -use crate::path::Prefix; +use crate::path::{Path, PathBuf, Prefix}; +use crate::sys::unsupported; #[inline] pub fn is_sep_byte(b: u8) -> bool { @@ -17,3 +18,7 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { pub const MAIN_SEP_STR: &str = "/"; pub const MAIN_SEP: char = '/'; + +pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> { + unsupported() +} diff --git a/library/std/src/sys/solid/path.rs b/library/std/src/sys/solid/path.rs index 4a14332d499..ed532dc989b 100644 --- a/library/std/src/sys/solid/path.rs +++ b/library/std/src/sys/solid/path.rs @@ -1,5 +1,6 @@ use crate::ffi::OsStr; -use crate::path::Prefix; +use crate::path::{Path, PathBuf, Prefix}; +use crate::sys::unsupported; #[inline] pub fn is_sep_byte(b: u8) -> bool { @@ -17,3 +18,7 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { pub const MAIN_SEP_STR: &str = "\\"; pub const MAIN_SEP: char = '\\'; + +pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> { + unsupported() +} diff --git a/library/std/src/sys/unix/path.rs b/library/std/src/sys/unix/path.rs index 717add9ec48..1fdabab4598 100644 --- a/library/std/src/sys/unix/path.rs +++ b/library/std/src/sys/unix/path.rs @@ -1,5 +1,8 @@ +use crate::env; use crate::ffi::OsStr; -use crate::path::Prefix; +use crate::io; +use crate::os::unix::ffi::OsStrExt; +use crate::path::{Path, PathBuf, Prefix}; #[inline] pub fn is_sep_byte(b: u8) -> bool { @@ -18,3 +21,43 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { pub const MAIN_SEP_STR: &str = "/"; pub const MAIN_SEP: char = '/'; + +/// Make a POSIX path absolute without changing its semantics. +pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> { + // This is mostly a wrapper around collecting `Path::components`, with + // exceptions made where this conflicts with the POSIX specification. + // See 4.13 Pathname Resolution, IEEE Std 1003.1-2017 + // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 + + let mut components = path.components(); + let path_os = path.as_os_str().as_bytes(); + + let mut normalized = if path.is_absolute() { + // "If a pathname begins with two successive <slash> characters, the + // first component following the leading <slash> characters may be + // interpreted in an implementation-defined manner, although more than + // two leading <slash> characters shall be treated as a single <slash> + // character." + if path_os.starts_with(b"//") && !path_os.starts_with(b"///") { + components.next(); + PathBuf::from("//") + } else { + PathBuf::new() + } + } else { + env::current_dir()? + }; + normalized.extend(components); + + // "Interfaces using pathname resolution may specify additional constraints + // when a pathname that does not name an existing directory contains at + // least one non- <slash> character and contains one or more trailing + // <slash> characters". + // A trailing <slash> is also meaningful if "a symbolic link is + // encountered during pathname resolution". + if path_os.ends_with(b"/") { + normalized.push(""); + } + + Ok(normalized) +} diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index 79e0eaf6c34..e54fcaed495 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -260,3 +260,19 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> { )?; Ok(path) } + +/// Make a Windows path absolute. +pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> { + if path.as_os_str().bytes().starts_with(br"\\?\") { + return Ok(path.into()); + } + let path = to_u16s(path)?; + let lpfilename = path.as_ptr(); + fill_utf16_buf( + // SAFETY: `fill_utf16_buf` ensures the `buffer` and `size` are valid. + // `lpfilename` is a pointer to a null terminated string that is not + // invalidated until after `GetFullPathNameW` returns successfully. + |buffer, size| unsafe { c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut()) }, + super::os2path, + ) +} |
