standard_lib/fs/dir/
dir.rs1use std::ffi::CString;
2use std::io::RawOsError;
3
4use libc::{O_DIRECTORY, c_int, mode_t};
5
6use crate::collections::contiguous::Array;
7use crate::fs::dir::{DirEntries, DirEntry};
8#[doc(inline)]
9pub use crate::fs::file::{CloneError, CloseError, MetadataError, OpenError};
10use crate::fs::{Abs, Fd, FileType, Metadata, OwnedPath, Path, Rel};
11use crate::util;
12
13use super::BUFFER_SIZE;
14
15pub(crate) const DEF_DIR_MODE: c_int = 0o777;
16
17pub const CWD: Directory = Directory {
22 fd: Fd(libc::AT_FDCWD),
23};
24
25#[derive(Debug)]
28pub struct Directory {
29 pub(crate) fd: Fd,
30}
31
32impl Directory {
33 pub fn open<P: Into<OwnedPath<Abs>>>(dir_path: P) -> Result<Directory, OpenError> {
35 match Fd::open(dir_path, O_DIRECTORY, DEF_DIR_MODE) {
36 Ok(fd) => Ok(Directory {
37 fd: fd.assert_type(FileType::Directory)?,
38 }),
39 Err(e) => Err(OpenError::interpret_raw_error(e)),
40 }
41 }
42
43 pub fn open_rel<P: Into<OwnedPath<Rel>>>(
44 &self,
45 relative_to: &Directory,
46 dir_path: P
47 ) -> Result<Directory, OpenError> {
48 match Fd::open_rel(relative_to, dir_path, O_DIRECTORY, DEF_DIR_MODE) {
49 Ok(fd) => Ok(Directory {
50 fd: fd.assert_type(FileType::Directory)?,
51 }),
52 Err(e) => Err(OpenError::interpret_raw_error(e)),
53 }
54 }
55
56 pub fn open_dir_entry(&self, dir_ent: &DirEntry) -> Result<Directory, OpenError> {
57 self.open_rel(dir_ent.parent, dir_ent.path.clone())
59 }
60
61 pub fn create<P: AsRef<Path<Abs>>>(
62 dir_path: P,
63 file_mode: u16
64 ) -> Result<Directory, RawOsError> {
65 let pathname = CString::from(dir_path.as_ref().to_owned());
66
67 match unsafe { libc::mkdir(pathname.as_ptr().cast(), file_mode as mode_t) } {
68 -1 => Err(util::fs::err_no()), fd => Ok(Directory {
70 fd: Fd(fd),
71 }),
72 }
73 }
74
75 pub fn read_entries<'a>(&'a self) -> DirEntries<'a> {
76 let buf = Array::new_uninit(BUFFER_SIZE);
77 DirEntries {
78 dir: self,
79 head: buf.ptr,
80 buf,
81 rem: 0,
82 }
83 }
84
85 pub fn metadata(&self) -> Result<Metadata, MetadataError> {
86 self.fd.metadata()
87 }
88
89 pub fn close(self) -> Result<(), CloseError> {
90 self.fd.close()
91 }
92
93 pub fn try_clone(&self) -> Result<Directory, CloneError> {
94 self.fd.try_clone().map(|new_fd| Directory {
95 fd: new_fd,
96 })
97 }
98}