diff options
author | pandaninjas <admin@malwarefight.wip.la> | 2024-02-24 10:05:11 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-24 15:05:11 +0000 |
commit | a4b5d8573b73b493ec659eb0da6987bb15a7c95a (patch) | |
tree | 28b434b23eb95c267a8b1a77e31f5c1a4f46431d | |
parent | 4a2778b6eafde25449aa4a120bb528353663595b (diff) |
feat(win): use size on disk for apparent size for OneDrive files (#370)
* feat(win): use size on disk for apparent size for OneDrive files
* apply changes from code review
* run cargo fmt
-rw-r--r-- | Cargo.lock | 10 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/platform.rs | 46 |
3 files changed, 46 insertions, 11 deletions
@@ -249,6 +249,7 @@ dependencies = [ "clap_mangen", "config-file", "directories", + "filesize", "lscolors", "rayon", "regex", @@ -285,6 +286,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] +name = "filesize" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12d741e2415d4e2e5bd1c1d00409d1a8865a57892c2d689b504365655d237d43" +dependencies = [ + "winapi", +] + +[[package]] name = "getrandom" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -43,6 +43,7 @@ sysinfo = "0.27" [target.'cfg(windows)'.dependencies] winapi-util = "0.1" +filesize = "0.2.0" [dev-dependencies] assert_cmd = "2" diff --git a/src/platform.rs b/src/platform.rs index 77c578a..3071bf6 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -26,7 +26,7 @@ pub fn get_metadata(d: &Path, use_apparent_size: bool) -> Option<(u64, Option<(u } #[cfg(target_family = "windows")] -pub fn get_metadata(d: &Path, _use_apparent_size: bool) -> Option<(u64, Option<(u64, u64)>)> { +pub fn get_metadata(d: &Path, use_apparent_size: bool) -> Option<(u64, Option<(u64, u64)>)> { // On windows opening the file to get size, file ID and volume can be very // expensive because 1) it causes a few system calls, and more importantly 2) it can cause // windows defender to scan the file. @@ -90,16 +90,27 @@ pub fn get_metadata(d: &Path, _use_apparent_size: bool) -> Option<(u64, Option<( Ok(Handle::from_file(file)) } - fn get_metadata_expensive(d: &Path) -> Option<(u64, Option<(u64, u64)>)> { + fn get_metadata_expensive( + d: &Path, + use_apparent_size: bool, + ) -> Option<(u64, Option<(u64, u64)>)> { use winapi_util::file::information; let h = handle_from_path_limited(d).ok()?; let info = information(&h).ok()?; - Some(( - info.file_size(), - Some((info.file_index(), info.volume_serial_number())), - )) + if use_apparent_size { + use filesize::PathExt; + Some(( + d.size_on_disk().ok()?, + Some((info.file_index(), info.volume_serial_number())), + )) + } else { + Some(( + info.file_size(), + Some((info.file_index(), info.volume_serial_number())), + )) + } } use std::os::windows::fs::MetadataExt; @@ -111,18 +122,31 @@ pub fn get_metadata(d: &Path, _use_apparent_size: bool) -> Option<(u64, Option<( const FILE_ATTRIBUTE_SYSTEM: u32 = 0x04; const FILE_ATTRIBUTE_NORMAL: u32 = 0x80; const FILE_ATTRIBUTE_DIRECTORY: u32 = 0x10; - + const FILE_ATTRIBUTE_SPARSE_FILE: u32 = 0x00000200; + const FILE_ATTRIBUTE_PINNED: u32 = 0x00080000; + const FILE_ATTRIBUTE_UNPINNED: u32 = 0x00100000; + const FILE_ATTRIBUTE_RECALL_ON_OPEN: u32 = 0x00040000; + const FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS: u32 = 0x00400000; + const FILE_ATTRIBUTE_OFFLINE: u32 = 0x00001000; + // normally FILE_ATTRIBUTE_SPARSE_FILE would be enough, however Windows sometimes likes to mask it out. see: https://stackoverflow.com/q/54560454 + const IS_PROBABLY_ONEDRIVE: u32 = FILE_ATTRIBUTE_SPARSE_FILE + | FILE_ATTRIBUTE_PINNED + | FILE_ATTRIBUTE_UNPINNED + | FILE_ATTRIBUTE_RECALL_ON_OPEN + | FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS + | FILE_ATTRIBUTE_OFFLINE; let attr_filtered = md.file_attributes() & !(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM); - if (attr_filtered & FILE_ATTRIBUTE_ARCHIVE) != 0 + if ((attr_filtered & FILE_ATTRIBUTE_ARCHIVE) != 0 || (attr_filtered & FILE_ATTRIBUTE_DIRECTORY) != 0 - || md.file_attributes() == FILE_ATTRIBUTE_NORMAL + || md.file_attributes() == FILE_ATTRIBUTE_NORMAL) + && !((attr_filtered & IS_PROBABLY_ONEDRIVE != 0) && use_apparent_size) { Some((md.len(), None)) } else { - get_metadata_expensive(d) + get_metadata_expensive(d, use_apparent_size) } } - _ => get_metadata_expensive(d), + _ => get_metadata_expensive(d, use_apparent_size), } } |