cap_primitives/rustix/linux/fs/
canonicalize_impl.rs1use super::procfs::get_path_from_proc_self_fd;
4use crate::fs::OpenOptionsExt;
5use crate::fs::{manually, open_beneath, FollowSymlinks, OpenOptions};
6use rustix::fs::OFlags;
7use std::path::{Component, Path, PathBuf};
8use std::{fs, io};
9
10pub(crate) fn canonicalize_impl(start: &fs::File, path: &Path) -> io::Result<PathBuf> {
12 let result = open_beneath(
16 start,
17 path,
18 OpenOptions::new()
19 .read(true)
20 .follow(FollowSymlinks::Yes)
21 .custom_flags(OFlags::PATH.bits() as i32),
22 );
23
24 match result {
26 Ok(file) => {
27 if let Ok(start_path) = get_path_from_proc_self_fd(start) {
28 if let Ok(file_path) = get_path_from_proc_self_fd(&file) {
29 if let Ok(canonical_path) = file_path.strip_prefix(start_path) {
30 #[cfg(racy_asserts)]
31 if canonical_path.as_os_str().is_empty() {
32 assert_eq!(
33 Component::CurDir.as_os_str(),
34 manually::canonicalize(start, path).unwrap()
35 );
36 } else {
37 assert_eq!(
38 canonical_path,
39 manually::canonicalize(start, path).unwrap()
40 );
41 }
42
43 let mut path_buf = canonical_path.to_path_buf();
44
45 if path_buf.as_os_str().is_empty() {
48 path_buf.push(Component::CurDir);
49 }
50
51 return Ok(path_buf);
52 }
53 }
54 }
55 }
56 Err(err) => match rustix::io::Errno::from_io_error(&err) {
57 Some(rustix::io::Errno::NOSYS) => (),
60 _ => return Err(err),
61 },
62 }
63
64 manually::canonicalize(start, path)
66}