usb_forensic/sources/
volume_cache.rs1use crate::{Attribute, Claim, DeviceKey, HistorySource, Provenance, SourceKind, Value};
11use peripheral_core::volume_info::VolumeLabel;
12
13pub struct VolumeCacheSource<'a> {
15 labels: &'a [VolumeLabel],
16}
17
18impl<'a> VolumeCacheSource<'a> {
19 #[must_use]
21 pub fn new(labels: &'a [VolumeLabel]) -> Self {
22 Self { labels }
23 }
24}
25
26impl HistorySource for VolumeCacheSource<'_> {
27 fn claims(&self) -> Vec<Claim> {
28 self.labels
29 .iter()
30 .map(|label| Claim {
31 device: DeviceKey(format!("{}:", label.drive_letter)),
34 attribute: Attribute::VolumeName,
35 value: Value::Text(label.volume_label.clone()),
36 provenance: Provenance {
37 source: SourceKind::VolumeInfoCache,
38 locator: label
39 .source
40 .key_path
41 .clone()
42 .unwrap_or_else(|| label.source.file.clone()),
43 },
44 })
45 .collect()
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52 use peripheral_core::Provenance as PcProvenance;
53
54 fn label(drive: char, name: &str) -> VolumeLabel {
55 VolumeLabel {
56 drive_letter: drive,
57 volume_label: name.to_string(),
58 source: PcProvenance {
59 file: "SOFTWARE".to_string(),
60 line: 0,
61 key_path: Some(format!(
62 "Microsoft\\Windows Search\\VolumeInfoCache\\{drive}:"
63 )),
64 },
65 }
66 }
67
68 #[test]
69 fn volume_label_yields_a_volume_name_claim_keyed_by_drive_letter() {
70 let labels = [label('E', "Authorized USB")];
71 let claims = VolumeCacheSource::new(&labels).claims();
72 assert_eq!(claims.len(), 1);
73 assert_eq!(claims[0].device, DeviceKey("E:".to_string()));
74 assert_eq!(claims[0].attribute, Attribute::VolumeName);
75 assert_eq!(claims[0].value, Value::Text("Authorized USB".to_string()));
76 assert_eq!(claims[0].provenance.source, SourceKind::VolumeInfoCache);
77 assert!(claims[0].provenance.locator.contains("VolumeInfoCache"));
78 }
79
80 #[test]
81 fn multiple_labels_accumulate() {
82 let labels = [label('E', "Authorized USB"), label('F', "IAMAN")];
83 let claims = VolumeCacheSource::new(&labels).claims();
84 assert_eq!(claims.len(), 2);
85 assert_eq!(claims[1].device, DeviceKey("F:".to_string()));
86 }
87
88 #[test]
89 fn locator_falls_back_to_the_file_when_no_key_path() {
90 let mut l = label('E', "Authorized USB");
92 l.source.key_path = None;
93 let labels = [l];
94 let claims = VolumeCacheSource::new(&labels).claims();
95 assert_eq!(claims[0].provenance.locator, "SOFTWARE");
96 }
97}