diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-06-26 13:57:21 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-06-27 18:40:17 +0200 |
| commit | 7b92bd7c340d9f9c094ed2fa57912049317d9b20 (patch) | |
| tree | b91399526ba94d87309d09d864df2935dd7a4d0a /src/util/mod.rs | |
| parent | 9c7f31870b4e1bf37df79ebbe1df9a56df83d878 (diff) | |
Basic package management
Diffstat (limited to 'src/util/mod.rs')
| -rw-r--r-- | src/util/mod.rs | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/src/util/mod.rs b/src/util/mod.rs index 71c5aefc..78c7bedf 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -2,9 +2,9 @@ pub mod fat; -mod buffer; +mod bytes; -pub use buffer::Buffer; +pub use bytes::Bytes; use std::fmt::{self, Debug, Formatter}; use std::hash::Hash; @@ -125,26 +125,60 @@ where pub trait PathExt { /// Lexically normalize a path. fn normalize(&self) -> PathBuf; + + /// Treat `self` as a virtual root relative to which the `path` is resolved. + /// + /// Returns `None` if the path lexically escapes the root. The path + /// might still escape through symlinks. + fn join_rooted(&self, path: &Path) -> Option<PathBuf>; } impl PathExt for Path { - #[tracing::instrument(skip_all)] fn normalize(&self) -> PathBuf { let mut out = PathBuf::new(); for component in self.components() { match component { Component::CurDir => {} Component::ParentDir => match out.components().next_back() { + Some(Component::RootDir) => {} Some(Component::Normal(_)) => { out.pop(); } _ => out.push(component), }, - _ => out.push(component), + Component::Prefix(_) | Component::RootDir | Component::Normal(_) => { + out.push(component) + } } } + if out.as_os_str().is_empty() { + out.push(Component::CurDir); + } out } + + fn join_rooted(&self, path: &Path) -> Option<PathBuf> { + let mut parts: Vec<_> = self.components().collect(); + let root = parts.len(); + for component in path.components() { + match component { + Component::Prefix(_) => return None, + Component::RootDir => parts.truncate(root), + Component::CurDir => {} + Component::ParentDir => { + if parts.len() <= root { + return None; + } + parts.pop(); + } + Component::Normal(_) => parts.push(component), + } + } + if parts.len() < root { + return None; + } + Some(parts.into_iter().collect()) + } } /// Format pieces separated with commas and a final "and" or "or". |
