tor_keymgr/keystore/
fs_utils.rs1use std::io;
9use std::path::{Path, PathBuf};
10use std::sync::Arc;
11
12use fs_mistrust::CheckedDir;
13use tor_error::{ErrorKind, HasKind};
14use tor_key_forge::KeystoreItemType;
15
16use crate::{ArtiPathUnavailableError, KeySpecifier};
17
18#[derive(Debug, Clone)]
22pub(super) struct RelKeyPath<'a> {
23 dir: &'a CheckedDir,
25 path: PathBuf,
27}
28
29impl<'a> RelKeyPath<'a> {
30 pub(super) fn arti(
34 dir: &'a CheckedDir,
35 key_spec: &dyn KeySpecifier,
36 item_type: &KeystoreItemType,
37 ) -> Result<Self, ArtiPathUnavailableError> {
38 let arti_path: String = key_spec.arti_path()?.into();
39 let mut path = PathBuf::from(arti_path);
40 path.set_extension(item_type.arti_extension());
41 Ok(Self { dir, path })
42 }
43
44 #[cfg(feature = "ctor-keystore")]
46 pub(super) fn from_parts(dir: &'a CheckedDir, path: PathBuf) -> Self {
47 Self { dir, path }
48 }
49
50 pub(super) fn checked_path(&self) -> Result<PathBuf, FilesystemError> {
52 let abs_path = self
53 .dir
54 .join(&self.path)
55 .map_err(|err| FilesystemError::FsMistrust {
56 action: FilesystemAction::Read,
57 path: self.path.clone(),
58 err: err.into(),
59 })?;
60
61 Ok(abs_path)
62 }
63
64 pub(super) fn rel_path_unchecked(&self) -> &Path {
66 &self.path
67 }
68
69 pub(super) fn checked_dir(&self) -> &CheckedDir {
71 self.dir
72 }
73}
74
75pub(crate) use internal::checked_op;
76
77mod internal {
79 macro_rules! checked_op {
83 ($op:ident, $relpath:expr $(, $arg:expr)* ) => {{
84 $relpath.checked_dir().$op($relpath.rel_path_unchecked(), $($arg,)* )
85 }}
86 }
87
88 pub(crate) use checked_op;
89}
90
91#[derive(thiserror::Error, Debug, Clone)]
93pub(crate) enum FilesystemError {
94 #[error("IO error on {path} while attempting to {action}")]
96 Io {
97 action: FilesystemAction,
99 path: PathBuf,
101 #[source]
103 err: Arc<io::Error>,
104 },
105
106 #[error("Inaccessible path or bad permissions on {path} while attempting to {action}")]
108 FsMistrust {
109 action: FilesystemAction,
111 path: PathBuf,
113 #[source]
115 err: Arc<fs_mistrust::Error>,
116 },
117
118 #[error("File at {0} is not a regular file")]
120 NotARegularFile(PathBuf),
121}
122
123#[derive(Copy, Clone, Debug, derive_more::Display)]
125pub(crate) enum FilesystemAction {
126 Init,
128 Read,
130 Write,
132 Remove,
134}
135
136impl HasKind for FilesystemError {
137 fn kind(&self) -> ErrorKind {
138 use tor_persist::FsMistrustErrorExt as _;
139 use FilesystemError as FE;
140
141 match self {
142 FE::Io { .. } => ErrorKind::KeystoreAccessFailed,
143 FE::FsMistrust { err, .. } => err.keystore_error_kind(),
144 FE::NotARegularFile(_) => ErrorKind::KeystoreCorrupted,
145 }
146 }
147}