copy_on_write/
lib.rs

1mod common;
2mod platform;
3
4use common::utils::absolute;
5use std::path::PathBuf;
6
7#[cfg(target_os = "windows")]
8use platform::windows::reflink_sync;
9
10#[cfg(not(target_os = "windows"))]
11use reflink_copy::reflink as reflink_sync;
12
13pub fn reflink_file_sync(src: impl AsRef<str>, dest: impl AsRef<str>) -> std::io::Result<()> {
14    // Clone the src and dest before moving them
15    let src_clone = src.as_ref().to_string();
16    let dest_clone = dest.as_ref().to_string();
17
18    // Convert to absolute paths
19    let src_abs: PathBuf = absolute(&src_clone)?;
20    let dest_abs: PathBuf = absolute(&dest_clone)?;
21
22    #[cfg(target_os = "windows")]
23    {
24        let src_str = src_abs.to_str().unwrap_or_default();
25        let dest_str = dest_abs.to_str().unwrap_or_default();
26        reflink_sync(src_str, dest_str)
27    }
28
29    #[cfg(not(target_os = "windows"))]
30    {
31        reflink_sync(&src_abs, &dest_abs)
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38    use std::fs::File;
39    use std::io::Write;
40    use tempfile::Builder;
41
42    fn create_file(path: &str) {
43        let mut file = File::create(path).unwrap();
44        file.write_all(b"Hello, world!").unwrap();
45    }
46
47    #[test]
48    fn test_reflink_file_sync() {
49        // Create a temporary directory inside the Current Working Directory
50        let tmp_dir = Builder::new()
51            .prefix("test_reflink")
52            .tempdir_in(std::env::current_dir().unwrap())
53            .unwrap();
54        let src = tmp_dir.path().join("src.txt");
55        let dest = tmp_dir.path().join("dest.txt");
56
57        // Create a file
58        create_file(src.to_str().unwrap());
59
60        // Reflink the file
61        reflink_file_sync(src.to_str().unwrap(), dest.to_str().unwrap()).unwrap();
62
63        // Cleanup
64        tmp_dir.close().unwrap();
65    }
66}