1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
//! # Handling Files Relative to File Descriptor //! //! Main concept here is a `Dir` which holds `O_PATH` file descriptor, you //! can create it with: //! //! * `Dir::open("/some/path")` -- open this directory as a file descriptor //! * `Dir::cwd()` -- current working directory //! //! *Note after opening file descriptors refer to same directory regardless of //! where it's moved or mounted (with `pivot_root` or `mount --move`). It may //! also be unmounted or be out of chroot and you will still be able to //! access files relative to it.* //! //! *Note that `Dir::cwd()` always refers to the current working directory of //! an application (and doesn't keep file descriptor too) and is sensitive //! to `chdir`. But otherwise behaves the same (i.e. directory may be //! moved and process is still in it). Anyway it's not more useful than //! just using relative paths and traditional filesystem utilities.* //! //! Most other operations are done on `Dir` object and are executed relative //! to it: //! //! * `Dir::list_dir()` //! * `Dir::sub_dir()` //! * `Dir::read_link()` //! * `Dir::open_file()` //! * `Dir::create_file()` //! * `Dir::update_file()` //! * `Dir::create_dir()` //! * `Dir::symlink()` //! * `Dir::local_rename()` //! //! Functions that expect path relative to the directory accept both the //! traditional path-like objects, such as Path, PathBuf and &str, and //! `Entry` type returned from `list_dir()`. The latter is faster as underlying //! system call wants `CString` and we keep that in entry. //! //! Note that if path supplied to any method of dir is absolute the Dir file //! descriptor is ignored. //! //! Also while all methods of dir accept any path if you want to prevent //! certain symlink attacks and race condition you should only use //! a single-component path. I.e. open one part of a chain at a time. //! #![warn(missing_docs)] extern crate libc; mod dir; mod ffi; mod list; mod name; mod filetype; mod metadata; pub use list::DirIter; pub use name::AsPath; pub use dir::{rename, hardlink}; pub use filetype::SimpleType; pub use metadata::Metadata; use std::ffi::CString; use std::os::unix::io::RawFd; /// A safe wrapper around directory file descriptor /// /// Construct it either with ``Dir::cwd()`` or ``Dir::open(path)`` /// #[derive(Debug)] pub struct Dir(DirFd); #[derive(Debug)] enum DirFd { Fd(RawFd), Cwd, } /// Entry returned by iterating over `DirIter` iterator #[derive(Debug)] pub struct Entry { name: CString, file_type: Option<SimpleType>, } #[cfg(test)] mod test { use std::mem; use super::{Dir, DirFd}; fn assert_sync<T: Sync>(x: T) -> T { x } fn assert_send<T: Send>(x: T) -> T { x } #[test] fn test() { let d = Dir(DirFd::Fd(3)); let d = assert_sync(d); let d = assert_send(d); // don't execute close for our fake DirFd mem::forget(d); } }