coven_foundation/files/
local_bytes.rs1use super::{device_reset, FileError};
6use std::fs;
7use std::path::Path;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11pub struct DirectoryBytes {
12 pub library: u64,
14 pub archives: Option<u64>,
16}
17
18pub(super) fn measure(store: &Path, cache: &str) -> Result<DirectoryBytes, FileError> {
21 let archives = device_reset::archives(store)?;
22 let mut library = 0u64;
23 let entries = fs::read_dir(store)
24 .map_err(|source| FileError::at("list the store's directory", store, source))?;
25 for entry in entries {
26 let entry =
27 entry.map_err(|source| FileError::at("list the store's directory", store, source))?;
28 let path = entry.path();
29 let name = entry.file_name();
30 if name == cache || name == device_reset::AREA || archives.contains(&path) {
31 continue;
32 }
33 library = library.saturating_add(size_of(&path)?);
34 }
35 let archives = if archives.is_empty() {
36 None
37 } else {
38 let mut total = 0u64;
39 for archive in &archives {
40 total = total.saturating_add(size_of(archive)?);
41 }
42 Some(total)
43 };
44 Ok(DirectoryBytes { library, archives })
45}
46
47fn size_of(path: &Path) -> Result<u64, FileError> {
50 let metadata = match fs::symlink_metadata(path) {
51 Ok(metadata) => metadata,
52 Err(source) if source.kind() == std::io::ErrorKind::NotFound => return Ok(0),
53 Err(source) => return Err(FileError::at("measure a store file", path, source)),
54 };
55 if metadata.is_file() {
56 return Ok(metadata.len());
57 }
58 if !metadata.is_dir() {
59 return Ok(0);
60 }
61 let entries = match fs::read_dir(path) {
62 Ok(entries) => entries,
63 Err(source) if source.kind() == std::io::ErrorKind::NotFound => return Ok(0),
64 Err(source) => return Err(FileError::at("list a store folder", path, source)),
65 };
66 let mut total = 0u64;
67 for entry in entries {
68 let entry = entry.map_err(|source| FileError::at("list a store folder", path, source))?;
69 total = total.saturating_add(size_of(&entry.path())?);
70 }
71 Ok(total)
72}