dupe_krill/
metadata.rs

1#[cfg(unix)]
2use std::os::unix::fs::MetadataExt;
3use std::path::Path;
4use std::{fs, io};
5
6#[derive(Copy, Clone, Hash, Ord, PartialOrd, PartialEq, Eq, Debug, Default)]
7pub struct Metadata {
8    pub dev: u64,
9    pub size: u64,
10}
11
12impl Metadata {
13    pub fn from_path(path: impl AsRef<Path>) -> Result<Self, io::Error> {
14        let m = fs::symlink_metadata(path)?;
15        Ok(Self::new(&m))
16    }
17
18    pub fn new(m: &fs::Metadata) -> Self {
19        Self { dev: get_device_id(m), size: get_size(m) }
20    }
21}
22
23#[cfg(unix)]
24fn get_device_id(m: &fs::Metadata) -> u64 {
25    m.dev()
26}
27
28#[cfg(windows)]
29fn get_device_id(_m: &fs::Metadata) -> u64 {
30    // On Windows, we'll use a simple constant for device identification
31    // This means hardlinking across different drives won't work properly,
32    // but that's expected behavior and matches filesystem limitations
33    // TODO: In the future, we could use Windows-specific APIs to get proper device IDs
34    0
35}
36
37#[cfg(unix)]
38fn get_size(m: &fs::Metadata) -> u64 {
39    m.size()
40}
41
42#[cfg(windows)]
43fn get_size(m: &fs::Metadata) -> u64 {
44    // Windows polyfill: round up to the next 4KB block to account for block overhead
45    let len = m.len();
46    const BLOCK_SIZE: u64 = 4096;
47    ((len + BLOCK_SIZE - 1) / BLOCK_SIZE) * BLOCK_SIZE
48}