forensic_mount/
win_map.rs1use std::time::{Duration, SystemTime, UNIX_EPOCH};
13
14use crate::types::{FsFileType, FsTimestamp};
15
16pub const FILE_ATTRIBUTE_READONLY: u32 = 0x0000_0001;
18pub const FILE_ATTRIBUTE_DIRECTORY: u32 = 0x0000_0010;
20pub const FILE_ATTRIBUTE_NORMAL: u32 = 0x0000_0080;
22
23pub fn windows_attributes(ft: FsFileType) -> u32 {
30 match ft {
31 FsFileType::Directory => FILE_ATTRIBUTE_DIRECTORY,
32 _ => FILE_ATTRIBUTE_NORMAL,
33 }
34}
35
36pub fn to_system_time(ts: FsTimestamp) -> SystemTime {
41 if ts.seconds <= 0 {
42 return UNIX_EPOCH;
43 }
44 UNIX_EPOCH + Duration::new(ts.seconds as u64, ts.nanoseconds)
45}
46
47pub fn path_components(path: &str) -> Vec<&str> {
50 path.split(['\\', '/']).filter(|c| !c.is_empty()).collect()
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn directory_maps_to_directory_attribute() {
59 assert_eq!(
60 windows_attributes(FsFileType::Directory),
61 FILE_ATTRIBUTE_DIRECTORY
62 );
63 }
64
65 #[test]
66 fn non_directory_types_map_to_normal() {
67 for ft in [
68 FsFileType::RegularFile,
69 FsFileType::Symlink,
70 FsFileType::CharDevice,
71 FsFileType::BlockDevice,
72 FsFileType::Fifo,
73 FsFileType::Socket,
74 FsFileType::Unknown,
75 ] {
76 assert_eq!(windows_attributes(ft), FILE_ATTRIBUTE_NORMAL);
77 }
78 }
79
80 #[test]
81 fn zero_and_negative_timestamps_map_to_epoch() {
82 assert_eq!(
83 to_system_time(FsTimestamp {
84 seconds: 0,
85 nanoseconds: 0
86 }),
87 UNIX_EPOCH
88 );
89 assert_eq!(
90 to_system_time(FsTimestamp {
91 seconds: -5,
92 nanoseconds: 123
93 }),
94 UNIX_EPOCH
95 );
96 }
97
98 #[test]
99 fn positive_timestamp_offsets_from_epoch() {
100 assert_eq!(
101 to_system_time(FsTimestamp {
102 seconds: 1,
103 nanoseconds: 500_000_000
104 }),
105 UNIX_EPOCH + Duration::new(1, 500_000_000)
106 );
107 }
108
109 #[test]
110 fn path_components_splits_on_both_separators_and_drops_empties() {
111 assert_eq!(path_components(r"\dir\file.txt"), vec!["dir", "file.txt"]);
112 assert_eq!(path_components("/a//b/"), vec!["a", "b"]);
113 }
114
115 #[test]
116 fn root_and_empty_paths_have_no_components() {
117 assert!(path_components("").is_empty());
118 assert!(path_components(r"\").is_empty());
119 }
120}