server: wire fs2 statvfs into scan spool free-space check
3 files changed,
+26 insertions,
-7 deletions
| 2836 |
2836 |
|
]
|
| 2837 |
2837 |
|
|
| 2838 |
2838 |
|
[[package]]
|
|
2839 |
+ |
name = "fs2"
|
|
2840 |
+ |
version = "0.4.3"
|
|
2841 |
+ |
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2842 |
+ |
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
|
2843 |
+ |
dependencies = [
|
|
2844 |
+ |
"libc",
|
|
2845 |
+ |
"winapi",
|
|
2846 |
+ |
]
|
|
2847 |
+ |
|
|
2848 |
+ |
[[package]]
|
| 2839 |
2849 |
|
name = "fs_extra"
|
| 2840 |
2850 |
|
version = "1.3.0"
|
| 2841 |
2851 |
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 4158 |
4168 |
|
"docengine",
|
| 4159 |
4169 |
|
"dotenvy",
|
| 4160 |
4170 |
|
"email_address",
|
|
4171 |
+ |
"fs2",
|
| 4161 |
4172 |
|
"git2",
|
| 4162 |
4173 |
|
"goblin 0.10.5",
|
| 4163 |
4174 |
|
"governor",
|
| 80 |
80 |
|
goblin = "0.10"
|
| 81 |
81 |
|
zip = "8.2"
|
| 82 |
82 |
|
yara-x = "1.16"
|
|
83 |
+ |
fs2 = "0.4"
|
| 83 |
84 |
|
|
| 84 |
85 |
|
# CSV parsing (import system)
|
| 85 |
86 |
|
csv = "1.3"
|
| 44 |
44 |
|
/// Refuse the job if writing `expected_size` would leave the spool volume
|
| 45 |
45 |
|
/// with less than `SCAN_SPOOL_FREE_RESERVE_BYTES` free, or if it exceeds
|
| 46 |
46 |
|
/// the per-object cap.
|
| 47 |
|
- |
///
|
| 48 |
|
- |
/// TODO: the free-space half of this check requires a `statvfs` call.
|
| 49 |
|
- |
/// Pending the user's call on adding a `fs2` (or `nix`) dependency, this
|
| 50 |
|
- |
/// only enforces the per-object cap; full free-space enforcement lands
|
| 51 |
|
- |
/// with the dep.
|
| 52 |
|
- |
pub fn check_free_space(_spool_dir: &Path, expected_size: u64) -> Result<(), String> {
|
|
47 |
+ |
pub fn check_free_space(spool_dir: &Path, expected_size: u64) -> Result<(), String> {
|
| 53 |
48 |
|
if expected_size > SCAN_SPOOL_MAX_BYTES {
|
| 54 |
49 |
|
return Err(format!(
|
| 55 |
50 |
|
"object exceeds scan spool cap ({} > {} bytes)",
|
| 56 |
51 |
|
expected_size, SCAN_SPOOL_MAX_BYTES
|
| 57 |
52 |
|
));
|
| 58 |
53 |
|
}
|
| 59 |
|
- |
let _ = SCAN_SPOOL_FREE_RESERVE_BYTES;
|
|
54 |
+ |
let probe = if spool_dir.exists() {
|
|
55 |
+ |
spool_dir
|
|
56 |
+ |
} else {
|
|
57 |
+ |
spool_dir.parent().unwrap_or(Path::new("/"))
|
|
58 |
+ |
};
|
|
59 |
+ |
let free = fs2::available_space(probe)
|
|
60 |
+ |
.map_err(|e| format!("statvfs {}: {e}", probe.display()))?;
|
|
61 |
+ |
if free.saturating_sub(expected_size) < SCAN_SPOOL_FREE_RESERVE_BYTES {
|
|
62 |
+ |
return Err(format!(
|
|
63 |
+ |
"scan spool volume short on space: free={} expected={} reserve={}",
|
|
64 |
+ |
free, expected_size, SCAN_SPOOL_FREE_RESERVE_BYTES
|
|
65 |
+ |
));
|
|
66 |
+ |
}
|
| 60 |
67 |
|
Ok(())
|
| 61 |
68 |
|
}
|
| 62 |
69 |
|
|