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