standard_lib/fs/path/
rel.rs1use std::ffi::{CString, OsStr};
2use std::marker::PhantomData;
3use std::mem::MaybeUninit;
4
5use libc::{c_int, stat as Stat};
6
7use super::{Abs, OwnedPath, Path, PathState};
8use crate::fs::error::{ExcessiveLinksError, MetadataOverflowError, MissingComponentError, NoSearchError, NonDirComponentError, OOMError, PathLengthError};
9use crate::fs::file::MetadataError;
10use crate::fs::panic::{BadFdPanic, BadStackAddrPanic, InvalidOpPanic, Panic, UnexpectedErrorPanic};
11use crate::fs::{Directory, Metadata};
12use crate::fs::path::{PathError, PathOrMetadataError};
13use crate::util::{self, sealed::Sealed};
14
15#[derive(Debug)]
16pub enum Rel {}
17
18impl Sealed for Rel {}
19
20impl PathState for Rel {}
21
22impl OwnedPath<Rel> {
23 pub fn resolve_root(self) -> OwnedPath<Abs> {
24 let OwnedPath { _state, inner } = self;
25 OwnedPath {
26 _state: PhantomData,
27 inner
28 }
29 }
30}
31
32impl Path<Rel> {
33 pub fn resolve(&self, mut target: OwnedPath<Abs>) -> OwnedPath<Abs> {
34 target.push(self);
35 target
36 }
37
38 pub fn resolve_root(&self) -> OwnedPath<Abs> {
39 self.resolve(OwnedPath::root())
40 }
41
42 pub fn resolve_home(&self) -> Option<OwnedPath<Abs>> {
43 Some(self.resolve(OwnedPath::home()?))
44 }
45
46 pub fn resolve_cwd(&self) -> Option<OwnedPath<Abs>> {
47 Some(self.resolve(OwnedPath::cwd()?))
48 }
49
50 pub(crate) fn metadata_raw(&self, relative_to: Directory, flags: c_int) -> Result<Metadata, PathOrMetadataError> {
53 let pathname = CString::from(self.to_owned());
55
56 let mut raw_meta: MaybeUninit<Stat> = MaybeUninit::uninit();
57 if unsafe { libc::fstatat(
58 *relative_to.fd,
59 pathname.as_ptr().add(1).cast(),
61 raw_meta.as_mut_ptr(),
62 flags
63 ) } == -1 {
64 match util::fs::err_no() {
65 libc::EACCES => Err(PathError::from(NoSearchError))?,
66 libc::EBADF => BadFdPanic.panic(),
67 libc::EFAULT => BadStackAddrPanic.panic(),
68 libc::EINVAL => InvalidOpPanic.panic(),
69 libc::ELOOP => Err(PathError::from(ExcessiveLinksError))?,
70 libc::ENAMETOOLONG => Err(PathError::from(PathLengthError))?,
71 libc::ENOENT => Err(PathError::from(MissingComponentError))?,
72 libc::ENOMEM => Err(MetadataError::from(OOMError))?,
73 libc::ENOTDIR => Err(PathError::from(NonDirComponentError))?,
74 libc::EOVERFLOW => Err(MetadataError::from(MetadataOverflowError))?,
75 e => UnexpectedErrorPanic(e).panic(),
76 }
77 }
78 let raw = unsafe { raw_meta.assume_init() };
80
81 Ok(Metadata::from_stat(raw))
82 }
83
84 pub fn metadata(&self, relative_to: Directory) -> Result<Metadata, PathOrMetadataError> {
85 self.metadata_raw(relative_to, 0)
86 }
87
88 pub fn metadata_no_follow(&self, relative_to: Directory) -> Result<Metadata, PathOrMetadataError> {
89 self.metadata_raw(relative_to, libc::AT_SYMLINK_NOFOLLOW)
90 }
91}
92
93impl<O: AsRef<OsStr>> From<O> for OwnedPath<Rel> {
94 fn from(value: O) -> Self {
95 Self::from_os_str_sanitized(value.as_ref())
96 }
97}