From 18356737dad14c7c2485108c83630b156c2e944e Mon Sep 17 00:00:00 2001 From: "chr.m" Date: Fri, 4 Oct 2024 17:33:35 +0300 Subject: [PATCH] Add more examples --- Cargo.lock | 4 +- examples/file_handling.rs | 85 +++++++++++++++++++++++++++++++++++++++ src/crypto.rs | 1 - src/fs_util.rs | 38 +---------------- src/keyring.rs | 5 --- 5 files changed, 89 insertions(+), 44 deletions(-) create mode 100644 examples/file_handling.rs diff --git a/Cargo.lock b/Cargo.lock index 032a4fdd..c4670387 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2070,9 +2070,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if 1.0.0", "fastrand 2.1.1", diff --git a/examples/file_handling.rs b/examples/file_handling.rs new file mode 100644 index 00000000..1fd7446d --- /dev/null +++ b/examples/file_handling.rs @@ -0,0 +1,85 @@ +use core::str::FromStr; + +use anyhow::Result; +use rencfs::{ + crypto::Cipher, + encryptedfs::{ + write_all_string_to_fs, CreateFileAttr, EncryptedFs, FileType, PasswordProvider, + }, +}; +use shush_rs::SecretString; +use std::{ + fs, + path::{Path, PathBuf}, +}; + +const ROOT_INODE: u64 = 1; + +struct PasswordProviderImpl; + +impl PasswordProvider for PasswordProviderImpl { + fn get_password(&self) -> Option { + Some(SecretString::from_str("password").unwrap()) + } +} + +#[tokio::main] +async fn main() -> Result<()> { + tracing_subscriber::fmt().init(); + + let data_dir = Path::new("/tmp/data_test").to_path_buf(); + clean_up_directory(&data_dir)?; + + let cipher = Cipher::ChaCha20Poly1305; + let fs = EncryptedFs::new( + data_dir.clone(), + Box::new(PasswordProviderImpl), + cipher, + false, + ) + .await?; + + let file_name = SecretString::from_str("file1").unwrap(); + let (file_handle, attr) = fs + .create(ROOT_INODE, &file_name, file_attributes(), false, true) + .await?; + + let data = "Hello, world!"; + write_all_string_to_fs(&fs, attr.ino, 0, data, file_handle).await?; + + fs.flush(file_handle).await?; + fs.release(file_handle).await?; + + let file_handle = fs.open(attr.ino, true, false).await?; + let mut buffer = vec![0; data.len()]; + fs.read(attr.ino, 0, &mut buffer, file_handle).await?; + fs.release(file_handle).await?; + + assert_eq!(data, String::from_utf8(buffer)?); + + assert!(fs.exists_by_name(ROOT_INODE, &file_name)?); + fs.remove_file(ROOT_INODE, &file_name).await?; + assert!(!fs.exists_by_name(ROOT_INODE, &file_name)?); + + Ok(()) +} + +const fn file_attributes() -> CreateFileAttr { + CreateFileAttr { + kind: FileType::RegularFile, + perm: 0o644, // Permissions + uid: 0, // User ID + gid: 0, // Group ID + rdev: 0, // Device ID + flags: 0, // File flags + } +} + +fn clean_up_directory(dir: &PathBuf) -> Result<()> { + if dir.exists() { + fs::remove_dir_all(dir)?; + } + + fs::create_dir_all(dir)?; + Ok(()) +} diff --git a/src/crypto.rs b/src/crypto.rs index a1e8f8f4..df0f0d35 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -374,7 +374,6 @@ where { let parent = file.parent().ok_or(Error::Generic("file has no parent"))?; let mut file = fs_util::open_atomic_write(file)?; - // println!("file: {:#?}", file.as_file_mut().metadata()?); file = serialize_encrypt_into(file, value, cipher, key)?; file.commit()?; File::open(parent)?.sync_all()?; diff --git a/src/fs_util.rs b/src/fs_util.rs index 5a27d427..13f20807 100644 --- a/src/fs_util.rs +++ b/src/fs_util.rs @@ -1,40 +1,6 @@ #[cfg(unix)] -use atomic_write_file::unix::OpenOptionsExt; -use atomic_write_file::AtomicWriteFile; -use futures_util::TryStreamExt; -use std::path::Path; -use std::{fs, io}; -use tokio_stream::wrappers::ReadDirStream; - -/// Recursively moves the content of a directory to another. -/// It will create destination directory if it doesn't exist. It will delete the source directory after the move. -pub async fn rename_dir_content(src: &Path, dst: &Path) -> io::Result<()> { - if !src.is_dir() { - return Err(io::Error::new( - io::ErrorKind::NotFound, - "source directory does not exist", - )); - } - if !dst.exists() { - fs::create_dir_all(dst)?; - } - let read_dir = tokio::fs::read_dir(src).await?; - let read_dir_stream = ReadDirStream::new(read_dir); - let vec = read_dir_stream.try_collect::>().await?; - let entries = vec.iter().collect::>(); - for entry in entries { - let dst = dst.join(entry.file_name()); - if entry.path().is_dir() { - fs::create_dir_all(&dst)?; - Box::pin(rename_dir_content(&entry.path(), &dst)).await?; - fs::remove_dir(entry.path())?; - } else { - fs::rename(entry.path(), dst)?; - } - } - fs::remove_dir(src)?; - Ok(()) -} +use atomic_write_file::{unix::OpenOptionsExt, AtomicWriteFile}; +use std::{io, path::Path}; pub fn open_atomic_write(file: &Path) -> io::Result { let mut opt = AtomicWriteFile::options(); diff --git a/src/keyring.rs b/src/keyring.rs index b2fb96e2..fa0751f6 100644 --- a/src/keyring.rs +++ b/src/keyring.rs @@ -3,24 +3,19 @@ use std::str::FromStr; use keyring::Entry; use shush_rs::{ExposeSecret, SecretString}; -#[allow(dead_code)] const KEYRING_SERVICE: &str = "rencfs"; -#[allow(dead_code)] const KEYRING_USER: &str = "encrypted_fs"; -#[allow(dead_code)] pub(crate) fn save(password: &SecretString, suffix: &str) -> Result<(), keyring::Error> { let entry = Entry::new(KEYRING_SERVICE, &format!("{KEYRING_USER}.{suffix}"))?; entry.set_password(&password.expose_secret()) } -#[allow(dead_code)] pub(crate) fn remove(suffix: &str) -> Result<(), keyring::Error> { let entry = Entry::new(KEYRING_SERVICE, &format!("{KEYRING_USER}.{suffix}"))?; entry.delete_password() } -#[allow(dead_code)] pub(crate) fn get(suffix: &str) -> Result { let entry = Entry::new(KEYRING_SERVICE, &format!("{KEYRING_USER}.{suffix}"))?; Ok(SecretString::from_str(&entry.get_password()?).unwrap())