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 pub(super) fn from_parts(dir: &'a CheckedDir, path: PathBuf) -> Self {
46 Self { dir, path }
47 }
48
49 pub(super) fn checked_path(&self) -> Result<PathBuf, FilesystemError> {
51 let abs_path = self
52 .dir
53 .join(&self.path)
54 .map_err(|err| FilesystemError::FsMistrust {
55 action: FilesystemAction::Read,
56 path: self.path.clone(),
57 err: err.into(),
58 })?;
59
60 Ok(abs_path)
61 }
62
63 pub(super) fn rel_path_unchecked(&self) -> &Path {
65 &self.path
66 }
67
68 pub(super) fn checked_dir(&self) -> &CheckedDir {
70 self.dir
71 }
72}
73
74pub(crate) use internal::checked_op;
75
76mod internal {
78 macro_rules! checked_op {
82 ($op:ident, $relpath:expr $(, $arg:expr)* ) => {{
83 $relpath.checked_dir().$op($relpath.rel_path_unchecked(), $($arg,)* )
84 }}
85 }
86
87 pub(crate) use checked_op;
88}
89
90#[derive(thiserror::Error, Debug, Clone)]
92pub(crate) enum FilesystemError {
93 #[error("IO error on {path} while attempting to {action}")]
95 Io {
96 action: FilesystemAction,
98 path: PathBuf,
100 #[source]
102 err: Arc<io::Error>,
103 },
104
105 #[error("Inaccessible path or bad permissions on {path} while attempting to {action}")]
107 FsMistrust {
108 action: FilesystemAction,
110 path: PathBuf,
112 #[source]
114 err: Arc<fs_mistrust::Error>,
115 },
116
117 #[error("File at {0} is not a regular file")]
119 NotARegularFile(PathBuf),
120}
121
122#[derive(Copy, Clone, Debug, derive_more::Display)]
124pub(crate) enum FilesystemAction {
125 Init,
127 Read,
129 Write,
131 Remove,
133}
134
135impl HasKind for FilesystemError {
136 fn kind(&self) -> ErrorKind {
137 use FilesystemError as FE;
138 use tor_persist::FsMistrustErrorExt as _;
139
140 match self {
141 FE::Io { .. } => ErrorKind::KeystoreAccessFailed,
142 FE::FsMistrust { err, .. } => err.keystore_error_kind(),
143 FE::NotARegularFile(_) => ErrorKind::KeystoreCorrupted,
144 }
145 }
146}