1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use internal::{self, DirEntry, consts};
use std::path::{Path, PathBuf};
use std::time::SystemTime;
#[derive(Clone)]
pub struct Entry {
name: String,
path: PathBuf,
obj_type: u8,
clsid: [u8; 16],
state_bits: u32,
creation_time: u64,
modified_time: u64,
stream_len: u64,
}
pub fn new_entry(dir_entry: &DirEntry, path: PathBuf) -> Entry {
Entry {
name: dir_entry.name.clone(),
path: path,
obj_type: dir_entry.obj_type,
clsid: dir_entry.clsid,
state_bits: dir_entry.state_bits,
creation_time: dir_entry.creation_time,
modified_time: dir_entry.modified_time,
stream_len: dir_entry.stream_len,
}
}
impl Entry {
pub fn name(&self) -> &str { &self.name }
pub fn path(&self) -> &Path { &self.path }
pub fn is_stream(&self) -> bool {
self.obj_type == consts::OBJ_TYPE_STREAM
}
pub fn is_storage(&self) -> bool {
self.obj_type == consts::OBJ_TYPE_STORAGE ||
self.obj_type == consts::OBJ_TYPE_ROOT
}
pub fn is_root(&self) -> bool { self.obj_type == consts::OBJ_TYPE_ROOT }
pub fn len(&self) -> u64 { self.stream_len }
pub fn clsid(&self) -> &[u8; 16] { &self.clsid }
pub fn state_bits(&self) -> u32 { self.state_bits }
pub fn created(&self) -> SystemTime {
internal::time::system_time_from_timestamp(self.creation_time)
}
pub fn modified(&self) -> SystemTime {
internal::time::system_time_from_timestamp(self.modified_time)
}
}
pub struct Entries<'a> {
directory: &'a Vec<DirEntry>,
path: PathBuf,
stack: Vec<u32>,
current: u32,
}
pub fn new_entries<'a>(directory: &'a Vec<DirEntry>, path: PathBuf,
start: u32)
-> Entries<'a> {
Entries {
directory: directory,
path: path,
stack: Vec::new(),
current: start,
}
}
impl<'a> Iterator for Entries<'a> {
type Item = Entry;
fn next(&mut self) -> Option<Entry> {
while self.current != consts::NO_STREAM {
self.stack.push(self.current);
self.current = self.directory[self.current as usize].left_sibling;
}
if let Some(parent) = self.stack.pop() {
let dir_entry = &self.directory[parent as usize];
self.current = dir_entry.right_sibling;
Some(new_entry(dir_entry, self.path.join(&dir_entry.name)))
} else {
None
}
}
}