standard_lib/fs/path/
rel.rs1use std::ffi::CString;
2use std::marker::PhantomData;
3use std::mem::MaybeUninit;
4
5use libc::{EACCES, EBADF, EFAULT, EINVAL, ELOOP, ENAMETOOLONG, ENOENT, ENOMEM, ENOTDIR, EOVERFLOW, 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(#[automatically_derived]
impl ::core::fmt::Debug for Rel {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {}
}
}Debug)]
16pub enum Rel {}
17
18impl Sealed for Rel {}
19
20impl PathState for Rel {}
21
22impl OwnedPath<Rel> {
23 pub(crate) unsafe fn dot_slash_dot() -> OwnedPath<Rel> {
25 OwnedPath::<Rel> {
26 _state: PhantomData,
27 bytes: b"/.".into(),
28 }
29 }
30
31 pub fn dot() -> OwnedPath<Rel> {
32 OwnedPath::<Rel> {
33 _state: PhantomData,
34 bytes: b"/".into(),
35 }
36 }
37
38 pub fn resolve_root(self) -> OwnedPath<Abs> {
39 let OwnedPath { bytes, .. } = self;
40 OwnedPath {
41 _state: PhantomData,
42 bytes
43 }
44 }
45}
46
47impl Path<Rel> {
48 pub fn resolve(&self, mut target: OwnedPath<Abs>) -> OwnedPath<Abs> {
53 target.push(self);
54 target
55 }
56
57 pub fn resolve_root(&self) -> OwnedPath<Abs> {
58 self.resolve(OwnedPath::root())
59 }
60
61 pub fn resolve_home(&self) -> Option<OwnedPath<Abs>> {
62 Some(self.resolve(OwnedPath::home()?))
63 }
64
65 pub fn resolve_cwd(&self) -> Option<OwnedPath<Abs>> {
66 Some(self.resolve(OwnedPath::cwd()?))
67 }
68
69 pub(crate) fn metadata_raw(&self, relative_to: Directory, flags: c_int) -> Result<Metadata, PathOrMetadataError> {
72 let pathname = CString::from(self.to_owned());
74
75 let mut raw_meta: MaybeUninit<Stat> = MaybeUninit::uninit();
76 if unsafe { libc::fstatat(
89 *relative_to.fd,
90 pathname.as_ptr().add(1).cast(),
92 raw_meta.as_mut_ptr(),
93 flags
94 ) } == -1 {
95 match util::fs::err_no() {
96 EACCES => Err(PathError::from(NoSearchError))?,
97 EBADF => BadFdPanic.panic(),
98 EFAULT => BadStackAddrPanic.panic(),
99 EINVAL => InvalidOpPanic.panic(),
100 ELOOP => Err(PathError::from(ExcessiveLinksError))?,
101 ENAMETOOLONG => Err(PathError::from(PathLengthError))?,
102 ENOENT => Err(PathError::from(MissingComponentError))?,
103 ENOMEM => Err(MetadataError::from(OOMError))?,
104 ENOTDIR => Err(PathError::from(NonDirComponentError))?,
105 EOVERFLOW => Err(MetadataError::from(MetadataOverflowError))?,
106 e => UnexpectedErrorPanic(e).panic(),
107 }
108 }
109 let raw = unsafe { raw_meta.assume_init() };
111
112 Ok(Metadata::from_stat(raw))
113 }
114
115 pub fn metadata(&self, relative_to: Directory) -> Result<Metadata, PathOrMetadataError> {
116 self.metadata_raw(relative_to, 0)
117 }
118
119 pub fn metadata_no_follow(&self, relative_to: Directory) -> Result<Metadata, PathOrMetadataError> {
120 self.metadata_raw(relative_to, libc::AT_SYMLINK_NOFOLLOW)
121 }
122}