1#![forbid(unsafe_code)]
2
3pub mod detect;
4pub mod filter;
5pub mod fusefs;
6pub mod inode_map;
7pub mod session;
8pub mod types;
9
10#[cfg(unix)]
11pub mod fuse_unix;
12pub mod fuse_windows;
13
14#[cfg(feature = "ext4")]
15pub mod fs_ext4;
16
17#[cfg(feature = "iso")]
18pub mod fs_iso;
19
20pub mod fs_raw;
21
22pub use types::*;
23
24use std::io;
25use std::path::Path;
26
27pub struct MountOptions {
32 pub read_only: bool,
33 pub daemon: bool,
34 pub fs_name: String,
35}
36
37impl Default for MountOptions {
38 fn default() -> Self {
39 Self {
40 read_only: false,
41 daemon: false,
42 fs_name: "4n6mount".to_string(),
43 }
44 }
45}
46
47pub trait ForensicFs {
52 fn root_ino(&self) -> u64;
56
57 fn read_dir(&mut self, ino: u64) -> FsResult<Vec<FsDirEntry>>;
59
60 fn lookup(&mut self, parent_ino: u64, name: &[u8]) -> FsResult<Option<u64>>;
62
63 fn metadata(&mut self, ino: u64) -> FsResult<FsMetadata>;
65
66 fn read_file(&mut self, ino: u64) -> FsResult<Vec<u8>>;
68
69 fn read_file_range(&mut self, ino: u64, offset: u64, len: u64) -> FsResult<Vec<u8>>;
71
72 fn read_link(&mut self, ino: u64) -> FsResult<Vec<u8>>;
74
75 fn deleted_inodes(&mut self) -> FsResult<Vec<FsDeletedInode>> {
79 Ok(vec![])
80 }
81
82 fn recover_file(&mut self, _ino: u64) -> FsResult<FsRecoveryResult> {
84 Err(not_supported("recover_file"))
85 }
86
87 fn timeline(&mut self) -> FsResult<Vec<FsTimelineEvent>> {
89 Ok(vec![])
90 }
91
92 fn unallocated_blocks(&mut self) -> FsResult<Vec<FsBlockRange>> {
94 Ok(vec![])
95 }
96
97 fn read_unallocated(&mut self, _range: &FsBlockRange) -> FsResult<Vec<u8>> {
99 Err(not_supported("read_unallocated"))
100 }
101
102 fn journal_transactions(&mut self) -> FsResult<Vec<FsTransaction>> {
104 Ok(vec![])
105 }
106
107 fn fs_info(&self) -> FsResult<serde_json::Value> {
109 Ok(serde_json::Value::Null)
110 }
111
112 fn block_size(&self) -> u64 {
114 4096
115 }
116}
117
118pub fn mount(
128 fs: Box<dyn ForensicFs + Send>,
129 mountpoint: &Path,
130 session: Option<session::Session>,
131 options: &MountOptions,
132) -> io::Result<()> {
133 #[cfg(unix)]
134 {
135 fuse_unix::mount_unix(fs, mountpoint, session, options)
136 }
137 #[cfg(windows)]
138 {
139 fuse_windows::mount_windows(fs, mountpoint, session, options)
140 }
141 #[cfg(not(any(unix, windows)))]
142 {
143 let _ = (fs, mountpoint, session, options);
144 Err(io::Error::new(
145 io::ErrorKind::Unsupported,
146 "no FUSE support on this platform",
147 ))
148 }
149}