diff --git a/src/backup/chunk_store.rs b/src/backup/chunk_store.rs index c166bbb5..4977d9e7 100644 --- a/src/backup/chunk_store.rs +++ b/src/backup/chunk_store.rs @@ -7,9 +7,10 @@ use openssl::sha; use std::sync::Mutex; use std::fs::File; -use std::os::unix::io::AsRawFd; +use std::os::unix::io::{AsRawFd, RawFd}; use crate::tools; +use crate::tools::borrow::Tied; pub struct GarbageCollectionStatus { pub used_bytes: usize, @@ -56,6 +57,83 @@ fn digest_to_prefix(digest: &[u8]) -> PathBuf { path.into() } +// This is one thing which would actually get nicer with futures & tokio-fs... +pub struct ChunkIterator { + base_dir: nix::dir::Dir, + index: usize, + subdir: Option< + Tied>> + >, + subdir_fd: RawFd, +} + +impl ChunkIterator { + fn new(base_dir: nix::dir::Dir) -> Self { + ChunkIterator { + base_dir, + index: 0, + subdir: None, + subdir_fd: 0, + } + } + + fn next_subdir(&mut self) -> Result { + if self.index == 0x10000 { + return Ok(false); + } + + let l1name = PathBuf::from(format!("{:04x}", self.index)); + self.index += 1; + + use nix::dir::{Dir, Entry}; + use nix::fcntl::OFlag; + use nix::sys::stat::Mode; + match Dir::openat(self.base_dir.as_raw_fd(), &l1name, OFlag::O_RDONLY, Mode::empty()) { + Ok(dir) => { + self.subdir_fd = dir.as_raw_fd(); + self.subdir = Some(Tied::new(dir, |dir| { + Box::new(unsafe { (*dir).iter() }) + as Box>> + })); + return Ok(true); + } + Err(err) => { + self.index = 0x10000; + bail!("unable to open chunk dir {:?}: {}", l1name, err); + } + } + } +} + +impl Iterator for ChunkIterator { + type Item = Result<(RawFd, nix::dir::Entry), Error>; + + fn next(&mut self) -> Option { + loop { + match self.subdir { + None => { + match self.next_subdir() { + Ok(true) => continue, // Enter the Some case + Ok(false) => return None, + Err(e) => return Some(Err(e)), + } + } + Some(ref mut dir) => { + let dir = dir.as_mut(); + match dir.next() { + Some(Ok(entry)) => return Some(Ok((self.subdir_fd, entry))), + Some(Err(e)) => return Some(Err(e.into())), + None => { + // Go to the next directory + self.subdir = None; + continue; + } + } + } + } + } + } +} impl ChunkStore {