forensic_rs/traits/
vfs.rs1use std::{
2 fmt::Display,
3 path::{Path, PathBuf},
4};
5
6use crate::err::ForensicResult;
7
8pub struct VPath(PathBuf);
9
10impl From<&str> for VPath {
11 fn from(v: &str) -> Self {
12 VPath(PathBuf::from(v))
13 }
14}
15impl From<String> for VPath {
16 fn from(v: String) -> Self {
17 VPath(PathBuf::from(v))
18 }
19}
20impl From<PathBuf> for VPath {
21 fn from(v: PathBuf) -> Self {
22 VPath(v)
23 }
24}
25impl From<&Path> for VPath {
26 fn from(v: &Path) -> Self {
27 VPath(v.to_path_buf())
28 }
29}
30
31pub trait VirtualFile: std::io::Seek + std::io::Read {
32 fn metadata(&self) -> ForensicResult<VMetadata>;
33}
34
35pub trait VirtualFileSystem {
36 fn from_file(&self, file: Box<dyn VirtualFile>) -> ForensicResult<Box<dyn VirtualFileSystem>>;
38 fn from_fs(&self, fs: Box<dyn VirtualFileSystem>)
40 -> ForensicResult<Box<dyn VirtualFileSystem>>;
41 fn read_to_string(&mut self, path: &Path) -> ForensicResult<String>;
43 fn read_all(&mut self, path: &Path) -> ForensicResult<Vec<u8>>;
45 fn read(&mut self, path: &Path, pos: u64, buf: &mut [u8]) -> ForensicResult<usize>;
47 fn metadata(&mut self, path: &Path) -> ForensicResult<VMetadata>;
49 fn read_dir(&mut self, path: &Path) -> ForensicResult<Vec<VDirEntry>>;
51 fn is_live(&self) -> bool;
53 fn open(&mut self, path: &Path) -> ForensicResult<Box<dyn VirtualFile>>;
55 fn duplicate(&self) -> Box<dyn VirtualFileSystem>;
57 #[allow(unused_variables)]
59 fn exists(&self, path: &Path) -> bool {
60 false
61 }
62}
63
64pub struct VMetadata {
65 pub created: Option<usize>,
69
70 pub accessed: Option<usize>,
74
75 pub modified: Option<usize>,
79
80 pub file_type: VFileType,
81 pub size: u64,
82}
83
84#[derive(PartialEq)]
85pub enum VFileType {
86 File,
87 Directory,
88 Symlink,
89}
90
91impl VMetadata {
92 pub fn created(&self) -> usize {
94 self.created.unwrap_or_else(|| {
95 crate::warn!(
96 "this filesystem has no support for creation time, using UNIX_EPOCH instead"
97 );
98 0
99 })
100 }
101 pub fn accessed(&self) -> usize {
103 self.accessed.unwrap_or_else(|| {
104 crate::warn!("this filesystem has no support for access time, using UNIX_EPOCH instead");
105 0
106 })
107 }
108 pub fn modified(&self) -> usize {
110 self.modified.unwrap_or_else(|| {
111 crate::warn!(
112 "this filesystem has no support for modification time, using UNIX_EPOCH instead"
113 );
114 0
115 })
116 }
117
118 pub fn created_opt(&self) -> Option<&usize> {
120 self.created.as_ref()
121 }
122 pub fn accessed_opt(&self) -> Option<&usize> {
124 self.accessed.as_ref()
125 }
126 pub fn modified_opt(&self) -> Option<&usize> {
128 self.modified.as_ref()
129 }
130 pub fn is_file(&self) -> bool {
131 self.file_type == VFileType::File
132 }
133 pub fn is_dir(&self) -> bool {
134 self.file_type == VFileType::Directory
135 }
136 pub fn is_symlink(&self) -> bool {
137 self.file_type == VFileType::Symlink
138 }
139 pub fn len(&self) -> u64 {
140 self.size
141 }
142}
143
144pub enum VDirEntry {
145 Directory(String),
146 File(String),
147 Symlink(String),
148}
149
150impl Display for VDirEntry {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 let content = match self {
153 VDirEntry::Directory(v) => v,
154 VDirEntry::File(v) => v,
155 VDirEntry::Symlink(v) => v,
156 };
157 write!(f, "{}", content)
158 }
159}