]> git.proxmox.com Git - proxmox-backup.git/blob - src/tools/fs.rs
tools: start fs submodule, add read_subdir
[proxmox-backup.git] / src / tools / fs.rs
1 //! File system helper utilities.
2
3 use std::os::unix::io::RawFd;
4
5 use failure::Error;
6 use nix::dir;
7 use nix::dir::Dir;
8
9 use crate::tools::borrow::Tied;
10
11 // Since Tied<T, U> implements Deref to U, a Tied<Dir, Iterator> already implements Iterator.
12 // This is simply a wrapper with a shorter type name mapping nix::Error to failure::Error.
13 /// Wrapper over a pair of `nix::dir::Dir` and `nix::dir::Iter`, returned by `read_subdir()`.
14 pub struct ReadDir {
15 iter: Tied<Dir, Iterator<Item = nix::Result<dir::Entry>>>,
16 }
17
18 impl Iterator for ReadDir {
19 type Item = Result<dir::Entry, Error>;
20
21 fn next(&mut self) -> Option<Self::Item> {
22 self.iter.next().map(|res| res.map_err(|e| Error::from(e)))
23 }
24 }
25
26 /// Create an iterator over sub directory entries.
27 /// This uses `openat` on `dirfd`, so `path` can be relative to that or an absolute path.
28 pub fn read_subdir<P: ?Sized + nix::NixPath>(dirfd: RawFd, path: &P) -> Result<ReadDir, Error> {
29 use nix::fcntl::OFlag;
30 use nix::sys::stat::Mode;
31
32 let dir = Dir::openat(dirfd, path, OFlag::O_RDONLY, Mode::empty())?;
33 let iter = Tied::new(dir, |dir| {
34 Box::new(unsafe { (*dir).iter() }) as Box<Iterator<Item = nix::Result<dir::Entry>>>
35 });
36 Ok(ReadDir { iter })
37 }