1use std::borrow::Borrow;
2
3use super::*;
4
5#[derive(Clone, Debug)]
6pub struct Dir {
7 path_buf: PathBuf,
8 block_size: u64,
9 supports_file_cloning: bool,
10}
11
12impl AsRef<Path> for Dir {
13 fn as_ref(&self) -> &Path {
14 &self.path_buf
15 }
16}
17
18impl Borrow<Path> for Dir {
19 fn borrow(&self) -> &Path {
20 &self.path_buf
21 }
22}
23
24impl Dir {
25 pub fn new(path_buf: PathBuf) -> Result<Self> {
26 fs::create_dir_all(&path_buf)?;
27 let block_size = path_min_hole_size(&path_buf)?;
28 let file = open_dir_as_file(&path_buf)?;
29 let supports_file_cloning_flag = file.file_system_flags()?.supports_block_cloning();
30 let supports_file_cloning = match supports_file_cloning_flag {
31 Some(some) => some,
32 None => {
33 let src = tempfile::NamedTempFile::new_in(&path_buf)?;
34 let dst_path = random_file_name_in_dir(&path_buf, ".clone_test-");
35 assert!(!dst_path.exists());
36 let clone_res = clonefile(src.path(), &dst_path);
37 let _ = std::fs::remove_file(&dst_path);
38 match clone_res {
39 Ok(()) => true,
40 Err(err) if CloneFileError::is_unsupported(&err) => {
41 warn!(?err, "clonefile unsupported");
42 false
43 }
44 Err(err) => {
45 error!(?err);
46 return Err(err).context("testing clonefile");
47 }
48 }
49 }
50 };
51 Ok(Self {
52 path_buf,
53 block_size,
54 supports_file_cloning,
55 })
56 }
57
58 pub fn path(&self) -> &Path {
59 &self.path_buf
60 }
61
62 pub fn block_size(&self) -> u64 {
63 self.block_size
64 }
65
66 pub fn supports_file_cloning(&self) -> bool {
67 self.supports_file_cloning
68 }
69
70 pub fn walk_dir(&self) -> Result<Vec<walk::Entry>> {
72 crate::walk::walk_dir(self)
73 }
74}