1 | use crate::env; |
2 | use crate::ffi::OsStr; |
3 | use crate::io; |
4 | use crate::path::{Path, PathBuf, Prefix}; |
5 | |
6 | #[inline ] |
7 | pub fn is_sep_byte(b: u8) -> bool { |
8 | b == b'/' |
9 | } |
10 | |
11 | #[inline ] |
12 | pub fn is_verbatim_sep(b: u8) -> bool { |
13 | b == b'/' |
14 | } |
15 | |
16 | #[inline ] |
17 | pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { |
18 | None |
19 | } |
20 | |
21 | pub const MAIN_SEP_STR: &str = "/" ; |
22 | pub const MAIN_SEP: char = '/' ; |
23 | |
24 | /// Make a POSIX path absolute without changing its semantics. |
25 | pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> { |
26 | // This is mostly a wrapper around collecting `Path::components`, with |
27 | // exceptions made where this conflicts with the POSIX specification. |
28 | // See 4.13 Pathname Resolution, IEEE Std 1003.1-2017 |
29 | // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 |
30 | |
31 | // Get the components, skipping the redundant leading "." component if it exists. |
32 | let mut components = path.strip_prefix("." ).unwrap_or(path).components(); |
33 | let path_os = path.as_os_str().as_encoded_bytes(); |
34 | |
35 | let mut normalized = if path.is_absolute() { |
36 | // "If a pathname begins with two successive <slash> characters, the |
37 | // first component following the leading <slash> characters may be |
38 | // interpreted in an implementation-defined manner, although more than |
39 | // two leading <slash> characters shall be treated as a single <slash> |
40 | // character." |
41 | if path_os.starts_with(b"//" ) && !path_os.starts_with(b"///" ) { |
42 | components.next(); |
43 | PathBuf::from("//" ) |
44 | } else { |
45 | PathBuf::new() |
46 | } |
47 | } else { |
48 | env::current_dir()? |
49 | }; |
50 | normalized.extend(components); |
51 | |
52 | // "Interfaces using pathname resolution may specify additional constraints |
53 | // when a pathname that does not name an existing directory contains at |
54 | // least one non- <slash> character and contains one or more trailing |
55 | // <slash> characters". |
56 | // A trailing <slash> is also meaningful if "a symbolic link is |
57 | // encountered during pathname resolution". |
58 | if path_os.ends_with(b"/" ) { |
59 | normalized.push("" ); |
60 | } |
61 | |
62 | Ok(normalized) |
63 | } |
64 | |