pub struct FileBackend { /* private fields */ }Expand description
Filesystem-backed keychain.
Thread-safe — KeychainBackend is Send + Sync, and all operations use
OS-level atomic primitives (rename, unlink). Multiple FileBackend
instances pointing at the same root directory coexist without mutual
serialization; the tmp-file names include a random suffix so concurrent
writes to the same BackendKey do not step on each other’s tmp files.
§Example
use std::sync::Arc;
use dig_keystore::{
backend::{FileBackend, BackendKey, KeychainBackend},
};
let backend: Arc<dyn KeychainBackend> = Arc::new(
FileBackend::new("/var/lib/dig/keys")
);
backend.write(&BackendKey::new("v1"), b"...").unwrap();Implementations§
Source§impl FileBackend
impl FileBackend
Sourcepub fn new(root: impl Into<PathBuf>) -> Self
pub fn new(root: impl Into<PathBuf>) -> Self
Create a new file backend rooted at root.
The directory is not created immediately — it is lazily created on
the first write call (with mode 0700 on Unix). This lets callers
construct a FileBackend in tests without side effects; no files are
written until the first write.
§Example
use dig_keystore::backend::FileBackend;
let be = FileBackend::new("/var/lib/dig/keys");
let _ = be; // directory not created yetTrait Implementations§
Source§impl KeychainBackend for FileBackend
impl KeychainBackend for FileBackend
Source§fn read(&self, key: &BackendKey) -> Result<Vec<u8>>
fn read(&self, key: &BackendKey) -> Result<Vec<u8>>
Read the entire file at <root>/<key>.dks.
Returns KeystoreError::Backend wrapping an io::Error with
ErrorKind::NotFound if the file does not exist.
Source§fn write(&self, key: &BackendKey, data: &[u8]) -> Result<()>
fn write(&self, key: &BackendKey, data: &[u8]) -> Result<()>
Atomically write data to <root>/<key>.dks.
Steps:
- Ensure
rootexists. - Create sibling
<key>.dks.tmp.<random>file, mode0600on Unix. - Write
data,fsyncthe file handle. renamethe tmp file onto the final name.- On Unix,
fsyncthe containing directory so the rename is durable. - On error in step 4, best-effort unlink the tmp file.
The random suffix in step 2 is not cryptographic — it exists only
to disambiguate two concurrent writes to the same key from the same
process. Uses a hash of (nanoseconds_since_epoch, pid).
Source§fn delete(&self, key: &BackendKey) -> Result<()>
fn delete(&self, key: &BackendKey) -> Result<()>
Best-effort secure delete, then unlink.
Steps:
- No-op if file does not exist (idempotent).
- Open the file for writing; overwrite with zeros in 4 KiB chunks.
fsyncthe overwritten file so zeros hit storage.unlinkthe file.
Step 2 is best-effort. On SSDs with flash translation layer or on copy-on-write filesystems (btrfs, ZFS), the zero pass may not reach the sectors that held the ciphertext. Use full-disk encryption for stronger guarantees.
Auto Trait Implementations§
impl Freeze for FileBackend
impl RefUnwindSafe for FileBackend
impl Send for FileBackend
impl Sync for FileBackend
impl Unpin for FileBackend
impl UnsafeUnpin for FileBackend
impl UnwindSafe for FileBackend
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more