Skip to main content

forensic_mount/
types.rs

1#![forbid(unsafe_code)]
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6/// Filesystem-agnostic file type.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub enum FsFileType {
9    RegularFile,
10    Directory,
11    Symlink,
12    CharDevice,
13    BlockDevice,
14    Fifo,
15    Socket,
16    Unknown,
17}
18
19/// Filesystem-agnostic timestamp.
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
21pub struct FsTimestamp {
22    pub seconds: i64,
23    pub nanoseconds: u32,
24}
25
26/// Filesystem-agnostic file metadata.
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct FsMetadata {
29    pub ino: u64,
30    pub file_type: FsFileType,
31    pub mode: u16,
32    pub uid: u32,
33    pub gid: u32,
34    pub size: u64,
35    pub links_count: u16,
36    pub atime: FsTimestamp,
37    pub mtime: FsTimestamp,
38    pub ctime: FsTimestamp,
39    pub crtime: FsTimestamp,
40    pub allocated: bool,
41}
42
43/// Filesystem-agnostic directory entry.
44#[derive(Debug, Clone)]
45pub struct FsDirEntry {
46    pub inode: u64,
47    pub name: Vec<u8>,
48    pub file_type: FsFileType,
49}
50
51impl FsDirEntry {
52    pub fn name_str(&self) -> String {
53        String::from_utf8_lossy(&self.name).to_string()
54    }
55}
56
57/// Deleted inode information.
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct FsDeletedInode {
60    pub ino: u64,
61    pub file_type: FsFileType,
62    pub size: u64,
63    pub dtime: u32,
64    pub recoverability: f64,
65}
66
67/// Result of attempting to recover a deleted file.
68#[derive(Debug, Clone)]
69pub struct FsRecoveryResult {
70    pub ino: u64,
71    pub data: Vec<u8>,
72    pub expected_size: u64,
73    pub recovered_bytes: u64,
74    pub recovery_percentage: f64,
75}
76
77/// A timeline event.
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct FsTimelineEvent {
80    pub timestamp: FsTimestamp,
81    pub event_type: FsEventType,
82    pub inode: u64,
83    pub size: u64,
84    pub uid: u32,
85    pub gid: u32,
86}
87
88/// Type of filesystem event.
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
90pub enum FsEventType {
91    Created,
92    Modified,
93    Accessed,
94    Changed,
95    Deleted,
96    Mounted,
97}
98
99/// A contiguous range of blocks.
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct FsBlockRange {
102    pub start: u64,
103    pub length: u64,
104}
105
106/// A journal transaction.
107#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct FsTransaction {
109    pub sequence: u64,
110    pub commit_seconds: u64,
111    pub commit_nanoseconds: u32,
112}
113
114/// Error type for `ForensicFs` operations.
115#[derive(Debug)]
116pub enum FsError {
117    Io(std::io::Error),
118    NotSupported(String),
119    NotFound(String),
120    Corrupt(String),
121    Other(String),
122}
123
124impl fmt::Display for FsError {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        match self {
127            Self::Io(e) => write!(f, "I/O error: {e}"),
128            Self::NotSupported(msg) => write!(f, "not supported: {msg}"),
129            Self::NotFound(msg) => write!(f, "not found: {msg}"),
130            Self::Corrupt(msg) => write!(f, "corrupt: {msg}"),
131            Self::Other(msg) => write!(f, "{msg}"),
132        }
133    }
134}
135
136impl std::error::Error for FsError {
137    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
138        match self {
139            Self::Io(e) => Some(e),
140            _ => None,
141        }
142    }
143}
144
145impl From<std::io::Error> for FsError {
146    fn from(e: std::io::Error) -> Self {
147        Self::Io(e)
148    }
149}
150
151/// Convenience alias.
152pub type FsResult<T> = std::result::Result<T, FsError>;
153
154/// Helper to create a "not supported" error.
155pub fn not_supported(op: &str) -> FsError {
156    FsError::NotSupported(op.to_string())
157}