standard_lib/fs/path/
abs.rs

1use std::env;
2use std::ffi::CString;
3use std::io::RawOsError;
4use std::marker::PhantomData;
5use std::mem::MaybeUninit;
6
7use libc::{EACCES, EBADF, EFAULT, ELOOP, ENAMETOOLONG, ENOENT, ENOMEM, ENOTDIR, EOVERFLOW, stat as Stat};
8
9use super::{OwnedPath, Path, PathState, Rel};
10use crate::fs::error::{ExcessiveLinksError, MetadataOverflowError, MissingComponentError, NoSearchError, NonDirComponentError, OOMError, PathLengthError};
11use crate::fs::panic::{BadFdPanic, BadStackAddrPanic, Panic, UnexpectedErrorPanic};
12use crate::fs::path::{PathError, PathOrMetadataError};
13use crate::fs::Metadata;
14use crate::fs::file::MetadataError;
15use crate::util::{self, sealed::Sealed};
16
17#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Abs {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match *self {}
    }
}Debug)]
18pub enum Abs {}
19
20impl Sealed for Abs {}
21
22impl PathState for Abs {}
23
24impl OwnedPath<Abs> {
25    pub fn root() -> OwnedPath<Abs> {
26        OwnedPath::<Abs> {
27            _state: PhantomData,
28            bytes: b"/".into(),
29        }
30    }
31
32    pub fn home() -> Option<OwnedPath<Abs>> {
33        Some(OwnedPath::<Abs>::from(
34            env::home_dir()?.into_os_string()
35        ))
36    }
37
38    pub fn cwd() -> Option<OwnedPath<Abs>> {
39        // libc::getcwd()
40        Some(OwnedPath::<Abs>::from(
41            env::current_dir().ok()?.into_os_string()
42        ))
43    }
44}
45
46impl Path<Abs> {
47    pub fn root() -> &'static Path<Abs> {
48        unsafe { Path::from_unchecked("/") }
49    }
50
51    pub fn read_all_links(&self) -> Result<OwnedPath<Abs>, RawOsError> {
52        // TODO: canonicalize with many readlink calls, needs to handle nonexistence
53        ::core::panicking::panic("not yet implemented")todo!()
54    }
55
56    pub fn normalize_lexically(&self) -> OwnedPath<Abs> {
57        // TODO: use components iter and collect
58        ::core::panicking::panic("not yet implemented")todo!()
59    }
60
61    pub fn make_relative<P: AsRef<Path<Abs>>>(&self, from: P) -> OwnedPath<Rel> {
62        // TODO: Include ../.. etc.
63        {
    ::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
            format_args!("{0:?}", &from.as_ref())));
}todo!("{:?}", &from.as_ref())
64    }
65
66    // no follow with O_NOFOLLOW
67
68    // read_* shortcuts for file
69
70    pub(crate) fn match_metadata_error() -> Result<(), PathOrMetadataError> {
71        match util::fs::err_no() {
72            EACCES       => Err(PathError::from(NoSearchError))?,
73            EBADF        => BadFdPanic.panic(),
74            EFAULT       => BadStackAddrPanic.panic(),
75            ELOOP        => Err(PathError::from(ExcessiveLinksError))?,
76            ENAMETOOLONG => Err(PathError::from(PathLengthError))?,
77            ENOENT       => Err(PathError::from(MissingComponentError))?,
78            ENOMEM       => Err(MetadataError::from(OOMError))?,
79            ENOTDIR      => Err(PathError::from(NonDirComponentError))?,
80            EOVERFLOW    => Err(MetadataError::from(MetadataOverflowError))?,
81            e            => UnexpectedErrorPanic(e).panic(),
82        }
83    }
84
85    // TODO: Move to OwnedPath and redirect?
86    pub fn metadata(&self) -> Result<Metadata, PathOrMetadataError> {
87        let pathname = CString::from(self.to_owned());
88
89        let mut raw_meta: MaybeUninit<Stat> = MaybeUninit::uninit();
90        // SAFETY:
91        // - pathname.as_ptr() is a valid pointer to a null-terminated C string for the lifetime of
92        //   `pathname`. CString guarantees no interior null bytes.
93        // - raw_meta.as_mut_ptr() points to valid, properly aligned stack memory allocated for a
94        //   Stat structure. MaybeUninit allows passing uninitialized memory to stat, which will
95        //   initialize it.
96        if unsafe { libc::stat(pathname.as_ptr().cast(), raw_meta.as_mut_ptr()) } == -1 {
97            Self::match_metadata_error()?
98        }
99        // SAFETY: stat either initializes raw_meta or returns an error and diverges.
100        let raw = unsafe { raw_meta.assume_init() };
101
102        Ok(Metadata::from_stat(raw))
103    }
104
105    pub fn metadata_no_follow(&self) -> Result<Metadata, PathOrMetadataError> {
106        let pathname = CString::from(self.to_owned());
107
108        let mut raw_meta: MaybeUninit<Stat> = MaybeUninit::uninit();
109        // SAFETY:
110        // - pathname.as_ptr() is a valid pointer to a null-terminated C string for the lifetime of
111        //   `pathname`. CString guarantees no interior null bytes.
112        // - raw_meta.as_mut_ptr() points to valid, properly aligned stack memory allocated for a
113        //   Stat structure. MaybeUninit allows passing uninitialized memory to lstat, which will
114        //   initialize it.
115        // - lstat is like stat but doesn't follow symbolic links.
116        if unsafe { libc::lstat(pathname.as_ptr().cast(), raw_meta.as_mut_ptr()) } == -1 {
117            Self::match_metadata_error()?
118        }
119        // SAFETY: lstat either initializes raw_meta or returns an error and diverges.
120        let raw = unsafe { raw_meta.assume_init() };
121
122        Ok(Metadata::from_stat(raw))
123    }
124
125    // NOTE: Symlinks can't be opened, so all symlink-related APIs need to be handled here.
126
127    // create_symlink
128    // read_link
129    // is_symlink
130    // create_hardlink
131
132    // rename
133    // move_dir
134    // remove (unlink)
135    // rmdir
136    // copy (sendfile)
137    // chmod
138    // chown
139    // exists
140    // try_exists
141    // access
142
143    // set_cwd
144}