forked from ForensicRS/forensic-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvfs.rs
159 lines (145 loc) · 4.73 KB
/
vfs.rs
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use std::{
fmt::Display,
path::{Path, PathBuf},
};
use crate::err::ForensicResult;
pub struct VPath(PathBuf);
impl From<&str> for VPath {
fn from(v: &str) -> Self {
VPath(PathBuf::from(v))
}
}
impl From<String> for VPath {
fn from(v: String) -> Self {
VPath(PathBuf::from(v))
}
}
impl From<PathBuf> for VPath {
fn from(v: PathBuf) -> Self {
VPath(v)
}
}
impl From<&Path> for VPath {
fn from(v: &Path) -> Self {
VPath(v.to_path_buf())
}
}
pub trait VirtualFile: std::io::Seek + std::io::Read {
fn metadata(&self) -> ForensicResult<VMetadata>;
}
pub trait VirtualFileSystem {
/// Initializes a virtual filesystem from a file. Ex: a Zip FS from a file
fn from_file(&self, file: Box<dyn VirtualFile>) -> ForensicResult<Box<dyn VirtualFileSystem>>;
/// Initializes a virtual filesystem from a filesyste. Ex: a remapping of windows routes to Linux routes.
fn from_fs(&self, fs: Box<dyn VirtualFileSystem>)
-> ForensicResult<Box<dyn VirtualFileSystem>>;
/// Read the entire contents of a file into a string.
fn read_to_string(&mut self, path: &Path) -> ForensicResult<String>;
/// Read the entire contents of a file into a bytes vector.
fn read_all(&mut self, path: &Path) -> ForensicResult<Vec<u8>>;
/// Read part of the content of a file into a bytes vector.
fn read(&mut self, path: &Path, pos: u64, buf: &mut [u8]) -> ForensicResult<usize>;
/// Get the metadata of a file/dir
fn metadata(&mut self, path: &Path) -> ForensicResult<VMetadata>;
/// Lists the contents of a Directory
fn read_dir(&mut self, path: &Path) -> ForensicResult<Vec<VDirEntry>>;
/// Check if the VirtualFileSystem is an abstraction over the real filesystem and not a virtual (like a ZIP file).
fn is_live(&self) -> bool;
/// Open a file
fn open(&mut self, path: &Path) -> ForensicResult<Box<dyn VirtualFile>>;
/// Allows duplicating the existing file system
fn duplicate(&self) -> Box<dyn VirtualFileSystem>;
/// Check if a file exists
#[allow(unused_variables)]
fn exists(&self, path: &Path) -> bool {
false
}
}
pub struct VMetadata {
/// Seconds elapsed since UNIX_EPOCH in UTC
///
/// this is optional, because some filesystems might not support this timestamp
pub created: Option<usize>,
/// Seconds elapsed since UNIX_EPOCH in UTC
///
/// this is optional, because some filesystems might not support this timestamp
pub accessed: Option<usize>,
/// Seconds elapsed since UNIX_EPOCH in UTC
///
/// this is optional, because some filesystems might not support this timestamp
pub modified: Option<usize>,
pub file_type: VFileType,
pub size: u64,
}
#[derive(PartialEq)]
pub enum VFileType {
File,
Directory,
Symlink,
}
impl VMetadata {
/// Seconds elapsed since UNIX_EPOCH in UTC
pub fn created(&self) -> usize {
self.created.unwrap_or_else(|| {
crate::warn!(
"this filesystem has no support for creation time, using UNIX_EPOCH instead"
);
0
})
}
/// Seconds elapsed since UNIX_EPOCH in UTC
pub fn accessed(&self) -> usize {
self.accessed.unwrap_or_else(|| {
crate::warn!("this filesystem has no support for access time, using UNIX_EPOCH instead");
0
})
}
/// Seconds elapsed since UNIX_EPOCH in UTC
pub fn modified(&self) -> usize {
self.modified.unwrap_or_else(|| {
crate::warn!(
"this filesystem has no support for modification time, using UNIX_EPOCH instead"
);
0
})
}
/// Seconds elapsed since UNIX_EPOCH in UTC
pub fn created_opt(&self) -> Option<&usize> {
self.created.as_ref()
}
/// Seconds elapsed since UNIX_EPOCH in UTC
pub fn accessed_opt(&self) -> Option<&usize> {
self.accessed.as_ref()
}
/// Seconds elapsed since UNIX_EPOCH in UTC
pub fn modified_opt(&self) -> Option<&usize> {
self.modified.as_ref()
}
pub fn is_file(&self) -> bool {
self.file_type == VFileType::File
}
pub fn is_dir(&self) -> bool {
self.file_type == VFileType::Directory
}
pub fn is_symlink(&self) -> bool {
self.file_type == VFileType::Symlink
}
pub fn len(&self) -> u64 {
self.size
}
}
pub enum VDirEntry {
Directory(String),
File(String),
Symlink(String),
}
impl Display for VDirEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let content = match self {
VDirEntry::Directory(v) => v,
VDirEntry::File(v) => v,
VDirEntry::Symlink(v) => v,
};
write!(f, "{}", content)
}
}