standard_lib/fs/path/
abs.rs1use std::env;
2use std::ffi::{CString, OsStr, OsString};
3use std::io::RawOsError;
4use std::marker::PhantomData;
5use std::mem::MaybeUninit;
6
7use libc::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(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 inner: OsString::from("/"),
29 }
30 }
31
32 pub fn home() -> Option<OwnedPath<Abs>> {
33 env::home_dir().map(|dir| OwnedPath::<Abs>::from(dir.as_os_str()))
36 }
37
38 pub fn cwd() -> Option<OwnedPath<Abs>> {
39 env::current_dir().ok().map(|dir| OwnedPath::<Abs>::from(dir.as_os_str()))
41 }
42}
43
44impl Path<Abs> {
45 pub fn read_all_links(&self) -> Result<OwnedPath<Abs>, RawOsError> {
46 todo!("canonicalize with many readlink calls, needs to handle nonexistence")
47 }
48
49 pub fn normalize_lexically(&self) -> OwnedPath<Abs> {
50 todo!("use components iter and collect")
51 }
52
53 pub fn make_relative<P: AsRef<Path<Abs>>>(&self, from: P) -> OwnedPath<Rel> {
54 todo!("{:?}", &from.as_ref())
56 }
57
58 pub(crate) fn match_metadata_error() -> Result<(), PathOrMetadataError> {
63 match util::fs::err_no() {
64 libc::EACCES => Err(PathError::from(NoSearchError))?,
65 libc::EBADF => BadFdPanic.panic(),
66 libc::EFAULT => BadStackAddrPanic.panic(),
67 libc::ELOOP => Err(PathError::from(ExcessiveLinksError))?,
68 libc::ENAMETOOLONG => Err(PathError::from(PathLengthError))?,
69 libc::ENOENT => Err(PathError::from(MissingComponentError))?,
70 libc::ENOMEM => Err(MetadataError::from(OOMError))?,
71 libc::ENOTDIR => Err(PathError::from(NonDirComponentError))?,
72 libc::EOVERFLOW => Err(MetadataError::from(MetadataOverflowError))?,
73 e => UnexpectedErrorPanic(e).panic(),
74 }
75 }
76
77 pub fn metadata(&self) -> Result<Metadata, PathOrMetadataError> {
78 let pathname = CString::from(self.to_owned());
80
81 let mut raw_meta: MaybeUninit<Stat> = MaybeUninit::uninit();
82 if unsafe { libc::stat(pathname.as_ptr().cast(), raw_meta.as_mut_ptr()) } == -1 {
83 Self::match_metadata_error()?
84 }
85 let raw = unsafe { raw_meta.assume_init() };
87
88 Ok(Metadata::from_stat(raw))
89 }
90
91 pub fn metadata_no_follow(&self) -> Result<Metadata, PathOrMetadataError> {
92 let pathname = CString::from(self.to_owned());
93
94 let mut raw_meta: MaybeUninit<Stat> = MaybeUninit::uninit();
95 if unsafe { libc::lstat(pathname.as_ptr().cast(), raw_meta.as_mut_ptr()) } == -1 {
96 Self::match_metadata_error()?
97 }
98 let raw = unsafe { raw_meta.assume_init() };
100
101 Ok(Metadata::from_stat(raw))
102 }
103
104 }
124
125impl<O: AsRef<OsStr>> From<O> for OwnedPath<Abs> {
126 fn from(value: O) -> Self {
127 Self::from_os_str_sanitized(value.as_ref())
128 }
129}