ic_backup/model/command_custody/
mod.rs1use serde::{Deserialize, Serialize};
4use std::path::{Path, PathBuf};
5use thiserror::Error;
6
7pub const MAX_COMMAND_CUSTODY_RECORD_BYTES: u64 = 32 * 1024;
9
10#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
12#[serde(try_from = "CustodyFields")]
13pub struct CommandCustodyRecord {
14 version: u16,
15 journal: PathBuf,
16 operation_sequence: u64,
17 device: u64,
18 inode: u64,
19}
20
21#[derive(Deserialize)]
22#[serde(deny_unknown_fields)]
23struct CustodyFields {
24 version: u16,
25 journal: PathBuf,
26 operation_sequence: u64,
27 device: u64,
28 inode: u64,
29}
30
31impl TryFrom<CustodyFields> for CommandCustodyRecord {
32 type Error = CommandCustodyRecordError;
33 fn try_from(fields: CustodyFields) -> Result<Self, Self::Error> {
34 if fields.version != 1 {
35 return Err(CommandCustodyRecordError::UnsupportedVersion(
36 fields.version,
37 ));
38 }
39 Self::new(
40 fields.journal,
41 fields.operation_sequence,
42 fields.device,
43 fields.inode,
44 )
45 }
46}
47
48impl CommandCustodyRecord {
49 pub(crate) fn new(
50 journal: PathBuf,
51 operation_sequence: u64,
52 device: u64,
53 inode: u64,
54 ) -> Result<Self, CommandCustodyRecordError> {
55 if !super::journal_path::is_canonical(&journal, 4096) {
56 return Err(CommandCustodyRecordError::InvalidJournal { journal });
57 }
58 if inode == 0 {
59 return Err(CommandCustodyRecordError::UnknownFileIdentity);
60 }
61 Ok(Self {
62 version: 1,
63 journal,
64 operation_sequence,
65 device,
66 inode,
67 })
68 }
69
70 #[must_use]
72 pub fn journal(&self) -> &Path {
73 &self.journal
74 }
75
76 #[must_use]
78 pub const fn operation_sequence(&self) -> u64 {
79 self.operation_sequence
80 }
81
82 #[must_use]
84 pub const fn device(&self) -> u64 {
85 self.device
86 }
87
88 #[must_use]
90 pub const fn inode(&self) -> u64 {
91 self.inode
92 }
93
94 pub(crate) const fn matches_file(&self, device: u64, inode: u64) -> bool {
95 self.device == device && self.inode == inode
96 }
97}
98
99#[derive(Debug, Error)]
101pub enum CommandCustodyRecordError {
102 #[error("unsupported command custody version {0}")]
104 UnsupportedVersion(u16),
105 #[error("invalid command journal location: {journal:?}")]
107 InvalidJournal {
108 journal: PathBuf,
110 },
111 #[error("command custody file identity is unknown")]
113 UnknownFileIdentity,
114}
115
116#[cfg(test)]
117mod tests;