From 6a824fb84434858a0bc362bb7682b996be4e8516 Mon Sep 17 00:00:00 2001 From: Radu Marias Date: Sat, 27 Apr 2024 22:08:23 +0300 Subject: [PATCH] use StirngSecret for all sensitive strings like file names --- src/encryptedfs.rs | 144 ++++---- src/encryptedfs/crypto_util.rs | 33 +- src/encryptedfs/encryptedfs_test.rs | 509 ++++++++++++++-------------- src/encryptedfs_fuse3.rs | 27 +- src/lib.rs | 6 +- 5 files changed, 373 insertions(+), 346 deletions(-) diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index d7ad6ea1..7df87b28 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -6,6 +6,7 @@ use std::fs::{File, OpenOptions, ReadDir}; use std::io::{Read, Write}; use std::os::unix::fs::MetadataExt; use std::path::PathBuf; +use std::str::FromStr; use std::sync::{Arc, Mutex, RwLock, Weak}; use std::sync::atomic::AtomicU64; use std::time::SystemTime; @@ -143,6 +144,7 @@ pub enum Cipher { Aes256Gcm, } +#[derive(Debug)] struct TimeAndSizeFileAttr { ino: u64, atime: SystemTime, @@ -177,22 +179,35 @@ impl TimeAndSizeFileAttr { } } -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub struct DirectoryEntry { pub ino: u64, - pub name: String, + pub name: SecretString, pub kind: FileType, } +impl PartialEq for DirectoryEntry { + fn eq(&self, other: &Self) -> bool { + self.ino == other.ino && self.name.expose_secret() == other.name.expose_secret() && self.kind == other.kind + } + +} + /// Like [`DirectoryEntry`] but with ['FileAttr']. -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub struct DirectoryEntryPlus { pub ino: u64, - pub name: String, + pub name: SecretString, pub kind: FileType, pub attr: FileAttr, } +impl PartialEq for DirectoryEntryPlus { + fn eq(&self, other: &Self) -> bool { + self.ino == other.ino && self.name.expose_secret() == other.name.expose_secret() && self.kind == other.kind && self.attr == other.attr + } +} + pub type FsResult = Result; pub struct DirectoryEntryIterator(ReadDir, Cipher, SecretVec); @@ -211,14 +226,16 @@ impl Iterator for DirectoryEntryIterator { return Some(Err(e.into())); } let file = file.unwrap(); - let mut name = entry.file_name().to_string_lossy().to_string(); - if name == "$." { - name = ".".to_string(); - } else if name == "$.." { - name = "..".to_string(); - } else { - name = crypto_util::decrypt_and_unnormalize_end_file_name(&name, &self.1, &self.2); - } + let name = entry.file_name().to_string_lossy().to_string(); + let name = { + if name == "$." { + SecretString::from_str(".").unwrap() + } else if name == "$.." { + SecretString::from_str("..").unwrap() + } else { + crypto_util::decrypt_and_unnormalize_end_file_name(&name, &self.1, &self.2) + } + }; let res: bincode::Result<(u64, FileType)> = bincode::deserialize_from(crypto_util::create_decryptor(file, &self.1, &self.2)); if let Err(e) = res { return Some(Err(e.into())); @@ -251,14 +268,16 @@ impl Iterator for DirectoryEntryPlusIterator { return Some(Err(e.into())); } let file = file.unwrap(); - let mut name = entry.file_name().to_string_lossy().to_string(); - if name == "$." { - name = ".".to_string(); - } else if name == "$.." { - name = "..".to_string(); - } else { - name = crypto_util::decrypt_and_unnormalize_end_file_name(&name, &self.2, &self.3); - } + let name = entry.file_name().to_string_lossy().to_string(); + let name = { + if name == "$." { + SecretString::from_str(".").unwrap() + } else if name == "$.." { + SecretString::from_str("..").unwrap() + } else { + crypto_util::decrypt_and_unnormalize_end_file_name(&name, &self.2, &self.3) + } + }; let res: bincode::Result<(u64, FileType)> = bincode::deserialize_from(crypto_util::create_decryptor(file, &self.2, &self.3)); if let Err(e) = res { error!(err = %e, "deserializing directory entry"); @@ -347,7 +366,6 @@ impl EncryptedFs { key: Self::read_or_create_key(path.join(SECURITY_DIR).join(KEY_ENC_FILENAME), password, &cipher)?, }; let _ = fs.ensure_root_exists(); - fs.check_password()?; Ok(fs) } @@ -369,7 +387,10 @@ impl EncryptedFs { /// Create a new node in the filesystem /// You don't need to provide `attr.ino`, it will be auto-generated anyway. - pub fn create_nod(&mut self, parent: u64, name: &str, mut attr: FileAttr, read: bool, write: bool) -> FsResult<(u64, FileAttr)> { + pub fn create_nod(&mut self, parent: u64, name: &SecretString, mut attr: FileAttr, read: bool, write: bool) -> FsResult<(u64, FileAttr)> { + if name.expose_secret() == "." || name.expose_secret() == ".." { + return Err(FsError::InvalidInput("name cannot be '.' or '..'".to_string())); + } if !self.node_exists(parent) { return Err(FsError::InodeNotFound); } @@ -400,12 +421,12 @@ impl EncryptedFs { // add "." and ".." entries self.insert_directory_entry(attr.ino, DirectoryEntry { ino: attr.ino, - name: "$.".to_string(), + name: SecretString::from_str("$.").unwrap(), kind: FileType::Directory, })?; self.insert_directory_entry(attr.ino, DirectoryEntry { ino: parent, - name: "$..".to_string(), + name: SecretString::from_str("$..").unwrap(), kind: FileType::Directory, })?; } @@ -414,7 +435,7 @@ impl EncryptedFs { // edd entry in parent directory, used for listing self.insert_directory_entry(parent, DirectoryEntry { ino: attr.ino, - name: name.to_string(), + name: SecretString::new(name.expose_secret().to_owned()), kind: attr.kind, })?; @@ -438,7 +459,7 @@ impl EncryptedFs { Ok((handle, attr)) } - pub fn find_by_name(&mut self, parent: u64, mut name: &str) -> FsResult> { + pub fn find_by_name(&mut self, parent: u64, name: &SecretString) -> FsResult> { if !self.node_exists(parent) { return Err(FsError::InodeNotFound); } @@ -448,12 +469,16 @@ impl EncryptedFs { if !self.is_dir(parent) { return Err(FsError::InvalidInodeType); } - if name == "." { - name = "$."; - } else if name == ".." { - name = "$.."; - } - let name = crypto_util::normalize_end_encrypt_file_name(name, &self.cipher, &self.key); + let name = { + if name.expose_secret() == "." { + SecretString::from_str("$.").unwrap() + } else if name.expose_secret() == ".." { + SecretString::from_str("$..").unwrap() + } else { + SecretString::new(name.expose_secret().to_owned()) + } + }; + let name = crypto_util::normalize_end_encrypt_file_name(&name, &self.cipher, &self.key); let file = File::open(self.data_dir.join(CONTENTS_DIR).join(parent.to_string()).join(name))?; let (inode, _): (u64, FileType) = bincode::deserialize_from(crypto_util::create_decryptor(file, &self.cipher, &self.key))?; Ok(Some(self.get_inode(inode)?)) @@ -465,7 +490,7 @@ impl EncryptedFs { Ok(iter.into_iter().count()) } - pub fn remove_dir(&mut self, parent: u64, name: &str) -> FsResult<()> { + pub fn remove_dir(&mut self, parent: u64, name: &SecretString) -> FsResult<()> { if !self.is_dir(parent) { return Err(FsError::InvalidInodeType); } @@ -502,7 +527,7 @@ impl EncryptedFs { Ok(()) } - pub fn remove_file(&mut self, parent: u64, name: &str) -> FsResult<()> { + pub fn remove_file(&mut self, parent: u64, name: &SecretString) -> FsResult<()> { if !self.is_dir(parent) { return Err(FsError::InvalidInodeType); } @@ -525,20 +550,24 @@ impl EncryptedFs { fs::remove_file(self.data_dir.join(CONTENTS_DIR).join(parent.to_string()).join(name))?; let mut parent_attr = self.get_inode(parent)?; - parent_attr.mtime = std::time::SystemTime::now(); - parent_attr.ctime = std::time::SystemTime::now(); + parent_attr.mtime = SystemTime::now(); + parent_attr.ctime = SystemTime::now(); self.write_inode(&parent_attr)?; Ok(()) } - pub fn exists_by_name(&self, parent: u64, mut name: &str) -> bool { - if name == "." { - name = "$."; - } else if name == ".." { - name = "$.."; - } - let name = crypto_util::normalize_end_encrypt_file_name(name, &self.cipher, &self.key); + pub fn exists_by_name(&self, parent: u64, name: &SecretString) -> bool { + let name = { + if name.expose_secret() == "." { + SecretString::from_str("$.").unwrap() + } else if name.expose_secret() == ".." { + SecretString::from_str("$..").unwrap() + } else { + SecretString::new(name.expose_secret().to_owned()) + } + }; + let name = crypto_util::normalize_end_encrypt_file_name(&name, &self.cipher, &self.key); self.data_dir.join(CONTENTS_DIR).join(parent.to_string()).join(name).exists() } @@ -1072,7 +1101,7 @@ impl EncryptedFs { map_guard.entry(ino).or_insert_with(|| Arc::new(RwLock::new(false))) } - pub fn rename(&mut self, parent: u64, name: &str, new_parent: u64, new_name: &str) -> FsResult<()> { + pub fn rename(&mut self, parent: u64, name: &SecretString, new_parent: u64, new_name: &SecretString) -> FsResult<()> { if !self.node_exists(parent) { return Err(FsError::InodeNotFound); } @@ -1089,7 +1118,7 @@ impl EncryptedFs { return Err(FsError::NotFound("name not found".to_string())); } - if parent == new_parent && name == new_name { + if parent == new_parent && name.expose_secret() == new_name.expose_secret() { // no-op return Ok(()); } @@ -1108,7 +1137,7 @@ impl EncryptedFs { // add to new parent contents self.insert_directory_entry(new_parent, DirectoryEntry { ino: attr.ino, - name: new_name.to_string(), + name: SecretString::new(new_name.expose_secret().to_owned()), kind: attr.kind, })?; @@ -1120,13 +1149,13 @@ impl EncryptedFs { new_parent_attr.mtime = SystemTime::now(); new_parent_attr.ctime = SystemTime::now(); - attr.ctime = std::time::SystemTime::now(); + attr.ctime = SystemTime::now(); if attr.kind == FileType::Directory { // add parent link to new directory self.insert_directory_entry(attr.ino, DirectoryEntry { ino: new_parent, - name: "$..".to_string(), + name: SecretString::from_str("$..").unwrap(), kind: FileType::Directory, })?; } @@ -1156,17 +1185,17 @@ impl EncryptedFs { } /// Encrypts a string using internal encryption info. - pub fn encrypt_string(&self, s: &str) -> String { + pub fn encrypt_string(&self, s: &SecretString) -> String { crypto_util::encrypt_string(s, &self.cipher, &self.key) } /// Decrypts a string using internal encryption info. - pub fn decrypt_string(&self, s: &str) -> String { + pub fn decrypt_string(&self, s: &str) -> SecretString { crypto_util::decrypt_string(s, &self.cipher, &self.key) } /// Normalize and encrypt a file name. - pub fn normalize_end_encrypt_file_name(&self, name: &str) -> String { + pub fn normalize_end_encrypt_file_name(&self, name: &SecretString) -> String { crypto_util::normalize_end_encrypt_file_name(name, &self.cipher, &self.key) } /// Change the password of the filesystem used to access the encryption key. @@ -1234,15 +1263,6 @@ impl EncryptedFs { } } - fn check_password(&mut self) -> FsResult<()> { - self.get_inode(ROOT_INODE).map_err(|err| match err { - FsError::SerializeError(_) => FsError::InvalidPassword, - _ => err - })?; - - Ok(()) - } - fn create_read_handle(&mut self, ino: u64, attr: Option, handle: u64, lock: Arc>) -> FsResult { let path = self.data_dir.join(CONTENTS_DIR).join(ino.to_string()); let file = OpenOptions::new().read(true).write(true).open(path)?; @@ -1304,7 +1324,7 @@ impl EncryptedFs { // add "." entry self.insert_directory_entry(attr.ino, DirectoryEntry { ino: attr.ino, - name: "$.".to_string(), + name: SecretString::from_str("$.").unwrap(), kind: FileType::Directory, })?; } @@ -1329,7 +1349,7 @@ impl EncryptedFs { Ok(()) } - fn remove_directory_entry(&self, parent: u64, name: &str) -> FsResult<()> { + fn remove_directory_entry(&self, parent: u64, name: &SecretString) -> FsResult<()> { let parent_path = self.data_dir.join(CONTENTS_DIR).join(parent.to_string()); let name = crypto_util::normalize_end_encrypt_file_name(name, &self.cipher, &self.key); fs::remove_file(parent_path.join(name))?; diff --git a/src/encryptedfs/crypto_util.rs b/src/encryptedfs/crypto_util.rs index 41e6e890..4d3fda0d 100644 --- a/src/encryptedfs/crypto_util.rs +++ b/src/encryptedfs/crypto_util.rs @@ -43,20 +43,20 @@ pub fn create_decryptor(mut file: File, cipher: &Cipher, key: &SecretVec) -> read::Decryptor::new(file, get_cipher(cipher), &key.expose_secret(), &iv).unwrap() } -pub fn encrypt_string(s: &str, cipher: &Cipher, key: &SecretVec) -> String { +pub fn encrypt_string(s: &SecretString, cipher: &Cipher, key: &SecretVec) -> String { // use the same IV so the same string will be encrypted to the same value let iv: Vec<_> = decode("dB0Ej+7zWZWTS5JUCldWMg==").unwrap(); let mut cursor = io::Cursor::new(vec![]); let mut encryptor = write::Encryptor::new(cursor, get_cipher(cipher), key.expose_secret(), &iv).unwrap(); - encryptor.write_all(s.as_bytes()).unwrap(); + encryptor.write_all(s.expose_secret().as_bytes()).unwrap(); cursor = encryptor.finish().unwrap(); base64::encode(&cursor.into_inner()) } -pub fn decrypt_string(s: &str, cipher: &Cipher, key: &SecretVec) -> String { - // use the same IV so the same string will be encrypted to the same value +pub fn decrypt_string(s: &str, cipher: &Cipher, key: &SecretVec) -> SecretString { + // use the same IV so the same string will be encrypted to the same value&SecretString::from_str( let iv: Vec<_> = decode("dB0Ej+7zWZWTS5JUCldWMg==").unwrap(); let vec = decode(s).unwrap(); @@ -65,16 +65,12 @@ pub fn decrypt_string(s: &str, cipher: &Cipher, key: &SecretVec) -> String { let mut decryptor = read::Decryptor::new(cursor, get_cipher(cipher), &key.expose_secret(), &iv).unwrap(); let mut decrypted = String::new(); decryptor.read_to_string(&mut decrypted).unwrap(); - decrypted + SecretString::new(decrypted) } -pub fn decrypt_and_unnormalize_end_file_name(name: &str, cipher: &Cipher, key: &SecretVec) -> String { - let mut name = String::from(name); - if name != "$." && name != "$.." { - name = name.replace("|", "/"); - name = decrypt_string(&name, cipher, key); - } - name.to_string() +pub fn decrypt_and_unnormalize_end_file_name(name: &str, cipher: &Cipher, key: &SecretVec) -> SecretString { + let name = String::from(name).replace("|", "/"); + decrypt_string(&name, cipher, key) } #[instrument(skip(password, salt))] @@ -90,13 +86,14 @@ pub fn derive_key(password: &SecretString, cipher: &Cipher, salt: SecretVec) Ok(SecretVec::new(dk)) } -pub fn normalize_end_encrypt_file_name(name: &str, cipher: &Cipher, key: &SecretVec) -> String { - let mut normalized_name = name.replace("/", " ").replace("\\", " "); - if normalized_name != "$." && normalized_name != "$.." { - normalized_name = encrypt_string(&normalized_name, cipher, key); - normalized_name = normalized_name.replace("/", "|"); +pub fn normalize_end_encrypt_file_name(name: &SecretString, cipher: &Cipher, key: &SecretVec) -> String { + if name.expose_secret() != "$." && name.expose_secret() != "$.." { + let normalized_name = SecretString::new(name.expose_secret().replace("/", " ").replace("\\", " ")); + let mut encrypted = encrypt_string(&normalized_name, cipher, key); + encrypted = encrypted.replace("/", "|"); + return encrypted } - normalized_name + name.expose_secret().to_owned() } pub fn hash(data: &[u8]) -> [u8; 32] { diff --git a/src/encryptedfs/encryptedfs_test.rs b/src/encryptedfs/encryptedfs_test.rs index 75201dab..b724ef9c 100644 --- a/src/encryptedfs/encryptedfs_test.rs +++ b/src/encryptedfs/encryptedfs_test.rs @@ -4,7 +4,7 @@ use std::io::{Read, Write}; use std::path::PathBuf; use std::str::FromStr; use std::string::String; -use secrecy::SecretString; +use secrecy::{ExposeSecret, SecretString}; use crate::encryptedfs::{CONTENTS_DIR, DirectoryEntry, DirectoryEntryPlus, EncryptedFs, Cipher, FileAttr, FileType, FsError, FsResult, INODES_DIR, ROOT_INODE, SECURITY_DIR}; @@ -134,30 +134,30 @@ fn test_create_nod() { let mut fs = setup.fs.as_mut().unwrap(); // file in root - let test_file = "test-file"; + let test_file = SecretString::from_str("test-file").unwrap(); let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), true, false).unwrap(); assert_ne!(fh, 0); assert_ne!(attr.ino, 0); assert!(fs.data_dir.join(INODES_DIR).join(attr.ino.to_string()).is_file()); assert!(fs.data_dir.join(CONTENTS_DIR).join(attr.ino.to_string()).is_file()); - assert!(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.normalize_end_encrypt_file_name(test_file)).is_file()); + assert!(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.normalize_end_encrypt_file_name(&test_file)).is_file()); assert!(fs.node_exists(attr.ino)); assert_eq!(attr, fs.get_inode(attr.ino).unwrap()); - let entry_in_parent: (u64, FileType) = deserialize_from(File::open(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.normalize_end_encrypt_file_name(test_file))).unwrap(), &mut fs); + let entry_in_parent: (u64, FileType) = deserialize_from(File::open(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.normalize_end_encrypt_file_name(&test_file))).unwrap(), &mut fs); assert_eq!(entry_in_parent, (attr.ino, FileType::RegularFile)); // directory in root - let test_dir = "test-dir"; - let (_fh, attr) = fs.create_nod(ROOT_INODE, test_dir, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let test_dir = SecretString::from_str("test-dir").unwrap(); + let (_fh, attr) = fs.create_nod(ROOT_INODE, &test_dir, create_attr_from_type(FileType::Directory), false, false).unwrap(); assert_ne!(attr.ino, 0); assert!(fs.data_dir.join(INODES_DIR).join(attr.ino.to_string()).is_file()); assert!(fs.data_dir.join(CONTENTS_DIR).join(attr.ino.to_string()).is_dir()); - assert!(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.normalize_end_encrypt_file_name(test_dir)).is_file()); + assert!(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.normalize_end_encrypt_file_name(&test_dir)).is_file()); assert!(fs.node_exists(attr.ino)); assert_eq!(attr, fs.get_inode(attr.ino).unwrap()); assert!(fs.is_dir(attr.ino)); - let entry_in_parent: (u64, FileType) = deserialize_from(File::open(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.normalize_end_encrypt_file_name(test_dir))).unwrap(), &mut fs); + let entry_in_parent: (u64, FileType) = deserialize_from(File::open(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.normalize_end_encrypt_file_name(&test_dir))).unwrap(), &mut fs); assert_eq!(entry_in_parent, (attr.ino, FileType::Directory)); let dot_entry_in_parent: (u64, FileType) = deserialize_from(File::open(fs.data_dir.join(CONTENTS_DIR).join(attr.ino.to_string()).join("$.")).unwrap(), &mut fs); assert_eq!(dot_entry_in_parent, (attr.ino, FileType::Directory)); @@ -166,15 +166,15 @@ fn test_create_nod() { // directory in another directory let parent = attr.ino; - let test_dir_2 = "test-dir-2"; - let (_fh, attr) = fs.create_nod(parent, test_dir_2, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let test_dir_2 = SecretString::from_str("test-dir-2").unwrap(); + let (_fh, attr) = fs.create_nod(parent, &test_dir_2, create_attr_from_type(FileType::Directory), false, false).unwrap(); assert!(fs.data_dir.join(INODES_DIR).join(attr.ino.to_string()).is_file()); assert!(fs.data_dir.join(CONTENTS_DIR).join(attr.ino.to_string()).is_dir()); - assert!(fs.data_dir.join(CONTENTS_DIR).join(parent.to_string()).join(fs.normalize_end_encrypt_file_name(test_dir_2)).is_file()); + assert!(fs.data_dir.join(CONTENTS_DIR).join(parent.to_string()).join(fs.normalize_end_encrypt_file_name(&test_dir_2)).is_file()); assert!(fs.node_exists(attr.ino)); assert_eq!(attr, fs.get_inode(attr.ino).unwrap()); assert!(fs.is_dir(attr.ino)); - let entry_in_parent: (u64, FileType) = deserialize_from(File::open(fs.data_dir.join(CONTENTS_DIR).join(parent.to_string()).join(fs.normalize_end_encrypt_file_name(test_dir_2))).unwrap(), &mut fs); + let entry_in_parent: (u64, FileType) = deserialize_from(File::open(fs.data_dir.join(CONTENTS_DIR).join(parent.to_string()).join(fs.normalize_end_encrypt_file_name(&test_dir_2))).unwrap(), &mut fs); assert_eq!(entry_in_parent, (attr.ino, FileType::Directory)); let dot_entry_in_parent: (u64, FileType) = deserialize_from(File::open(fs.data_dir.join(CONTENTS_DIR).join(attr.ino.to_string()).join("$.")).unwrap(), &mut fs); assert_eq!(dot_entry_in_parent, (attr.ino, FileType::Directory)); @@ -183,14 +183,14 @@ fn test_create_nod() { // existing file assert!(matches!( - fs.create_nod(ROOT_INODE, test_file, create_attr_from_type(FileType::RegularFile), false, false), + fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, false), Err(FsError::AlreadyExists) ) ); // existing directory assert!(matches!( - fs.create_nod(ROOT_INODE, test_dir, create_attr_from_type(FileType::Directory), false, false), + fs.create_nod(ROOT_INODE, &test_dir, create_attr_from_type(FileType::Directory), false, false), Err(FsError::AlreadyExists) ) ); @@ -203,101 +203,101 @@ fn test_read_dir() { let fs = setup.fs.as_mut().unwrap(); // file and directory in root - let test_file = "test-file"; - let (_fh, file_attr) = fs.create_nod(ROOT_INODE, test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let test_file = SecretString::from_str("test-file").unwrap(); + let (_fh, file_attr) = fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let test_dir = "test-dir"; - let (_fh, dir_attr) = fs.create_nod(ROOT_INODE, test_dir, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let test_dir = SecretString::from_str("test-dir").unwrap(); + let (_fh, dir_attr) = fs.create_nod(ROOT_INODE, &test_dir, create_attr_from_type(FileType::Directory), false, false).unwrap(); let mut entries: Vec> = fs.read_dir(dir_attr.ino).unwrap().collect(); - entries.sort_by(|a, b| a.as_ref().unwrap().name.cmp(&b.as_ref().unwrap().name)); + entries.sort_by(|a, b| a.as_ref().unwrap().name.expose_secret().cmp(&b.as_ref().unwrap().name.expose_secret())); let entries: Vec = entries.into_iter().map(|e| e.unwrap()).collect(); assert_eq!(entries.len(), 2); assert_eq!(vec![ DirectoryEntry { ino: dir_attr.ino, - name: ".".to_string(), + name: SecretString::from_str(".").unwrap(), kind: FileType::Directory, }, DirectoryEntry { ino: ROOT_INODE, - name: "..".to_string(), + name: SecretString::from_str("..").unwrap(), kind: FileType::Directory, }, ], entries); let iter = fs.read_dir(ROOT_INODE); let mut entries: Vec> = iter.unwrap().into_iter().collect(); - entries.sort_by(|a, b| a.as_ref().unwrap().name.cmp(&b.as_ref().unwrap().name)); + entries.sort_by(|a, b| a.as_ref().unwrap().name.expose_secret().cmp(&b.as_ref().unwrap().name.expose_secret())); let entries: Vec = entries.into_iter().map(|e| e.unwrap()).collect(); let mut sample = vec![ DirectoryEntry { ino: ROOT_INODE, - name: ".".to_string(), + name: SecretString::from_str(".").unwrap(), kind: FileType::Directory, }, DirectoryEntry { ino: file_attr.ino, - name: test_file.to_string(), + name: SecretString::new(test_file.expose_secret().to_owned()), kind: FileType::RegularFile, }, DirectoryEntry { ino: dir_attr.ino, - name: test_dir.to_string(), + name: SecretString::new(test_dir.expose_secret().to_owned()), kind: FileType::Directory, }]; - sample.sort_by(|a, b| a.name.cmp(&b.name)); + sample.sort_by(|a, b| a.name.expose_secret().cmp(&b.name.expose_secret())); assert_eq!(entries.len(), 3); assert_eq!(sample, entries); // file and directory in another directory let parent = dir_attr.ino; - let test_file_2 = "test-file-2"; - let (_fh, file_attr) = fs.create_nod(parent, test_file_2, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let test_file_2 = SecretString::from_str("test-file-2").unwrap(); + let (_fh, file_attr) = fs.create_nod(parent, &test_file_2, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let test_dir_2 = "test-dir-2"; - let (_fh, dir_attr) = fs.create_nod(parent, test_dir_2, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let test_dir_2 = SecretString::from_str("test-dir-2").unwrap(); + let (_fh, dir_attr) = fs.create_nod(parent, &test_dir_2, create_attr_from_type(FileType::Directory), false, false).unwrap(); let mut entries: Vec> = fs.read_dir(dir_attr.ino).unwrap().collect(); - entries.sort_by(|a, b| a.as_ref().unwrap().name.cmp(&b.as_ref().unwrap().name)); + entries.sort_by(|a, b| a.as_ref().unwrap().name.expose_secret().cmp(&b.as_ref().unwrap().name.expose_secret())); let entries: Vec = entries.into_iter().map(|e| e.unwrap()).collect(); assert_eq!(entries.len(), 2); assert_eq!(vec![ DirectoryEntry { ino: dir_attr.ino, - name: ".".to_string(), + name: SecretString::from_str(".").unwrap(), kind: FileType::Directory, }, DirectoryEntry { ino: parent, - name: "..".to_string(), + name: SecretString::from_str("..").unwrap(), kind: FileType::Directory, }, ], entries); let iter = fs.read_dir(parent); let mut entries: Vec = iter.unwrap().map(|e| e.unwrap()).collect(); - entries.sort_by(|a, b| a.name.cmp(&b.name)); + entries.sort_by(|a, b| a.name.expose_secret().cmp(&b.name.expose_secret())); let mut sample = vec![ DirectoryEntry { ino: parent, - name: ".".to_string(), + name: SecretString::from_str(".").unwrap(), kind: FileType::Directory, }, DirectoryEntry { ino: ROOT_INODE, - name: "..".to_string(), + name: SecretString::from_str("..").unwrap(), kind: FileType::Directory, }, DirectoryEntry { ino: file_attr.ino, - name: test_file_2.to_string(), + name: SecretString::new(test_file_2.expose_secret().to_owned()), kind: FileType::RegularFile, }, DirectoryEntry { ino: dir_attr.ino, - name: test_dir_2.to_string(), + name: SecretString::new(test_dir_2.expose_secret().to_owned()), kind: FileType::Directory, }]; - sample.sort_by(|a, b| a.name.cmp(&b.name)); + sample.sort_by(|a, b| a.name.expose_secret().cmp(&b.name.expose_secret())); assert_eq!(entries.len(), 4); assert_eq!(sample, entries); }); @@ -309,26 +309,26 @@ fn test_read_dir_plus() { let fs = setup.fs.as_mut().unwrap(); // file and directory in root - let test_file = "test-file"; - let (_fh, file_attr) = fs.create_nod(ROOT_INODE, test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let test_file = SecretString::from_str("test-file").unwrap(); + let (_fh, file_attr) = fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let test_dir = "test-dir"; - let (_fh, dir_attr) = fs.create_nod(ROOT_INODE, test_dir, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let test_dir = SecretString::from_str("test-dir").unwrap(); + let (_fh, dir_attr) = fs.create_nod(ROOT_INODE, &test_dir, create_attr_from_type(FileType::Directory), false, false).unwrap(); let mut entries: Vec> = fs.read_dir_plus(dir_attr.ino).unwrap().collect(); - entries.sort_by(|a, b| a.as_ref().unwrap().name.cmp(&b.as_ref().unwrap().name)); + entries.sort_by(|a, b| a.as_ref().unwrap().name.expose_secret().cmp(&b.as_ref().unwrap().name.expose_secret())); let entries: Vec = entries.into_iter().map(|e| e.unwrap()).collect(); assert_eq!(entries.len(), 2); let attr_root = fs.get_inode(ROOT_INODE).unwrap(); assert_eq!(vec![ DirectoryEntryPlus { ino: dir_attr.ino, - name: ".".to_string(), + name: SecretString::from_str(".").unwrap(), kind: FileType::Directory, attr: dir_attr, }, DirectoryEntryPlus { ino: ROOT_INODE, - name: "..".to_string(), + name: SecretString::from_str("..").unwrap(), kind: FileType::Directory, attr: attr_root, }, @@ -336,56 +336,56 @@ fn test_read_dir_plus() { let iter = fs.read_dir_plus(ROOT_INODE); let mut entries: Vec> = iter.unwrap().into_iter().collect(); - entries.sort_by(|a, b| a.as_ref().unwrap().name.cmp(&b.as_ref().unwrap().name)); + entries.sort_by(|a, b| a.as_ref().unwrap().name.expose_secret().cmp(&b.as_ref().unwrap().name.expose_secret())); let entries: Vec = entries.into_iter().map(|e| e.unwrap()).collect(); let mut sample = vec![ DirectoryEntryPlus { ino: ROOT_INODE, - name: ".".to_string(), + name: SecretString::from_str(".").unwrap(), kind: FileType::Directory, attr: attr_root, }, DirectoryEntryPlus { ino: file_attr.ino, - name: test_file.to_string(), + name: SecretString::new(test_file.expose_secret().to_owned()), kind: FileType::RegularFile, attr: file_attr, }, DirectoryEntryPlus { ino: dir_attr.ino, - name: test_dir.to_string(), + name: SecretString::new(test_dir.expose_secret().to_owned()), kind: FileType::Directory, attr: dir_attr, }]; - sample.sort_by(|a, b| a.name.cmp(&b.name)); + sample.sort_by(|a, b| a.name.expose_secret().cmp(&b.name.expose_secret())); assert_eq!(entries.len(), 3); assert_eq!(sample, entries); // file and directory in another directory let parent = dir_attr.ino; let attr_parent = dir_attr; - let test_file_2 = "test-file-2"; - let (_fh, file_attr) = fs.create_nod(parent, test_file_2, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let test_file_2 = SecretString::from_str("test-file-2").unwrap(); + let (_fh, file_attr) = fs.create_nod(parent, &test_file_2, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let test_dir_2 = "test-dir-2"; - let (_fh, dir_attr) = fs.create_nod(parent, test_dir_2, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let test_dir_2 = SecretString::from_str("test-dir-2").unwrap(); + let (_fh, dir_attr) = fs.create_nod(parent, &test_dir_2, create_attr_from_type(FileType::Directory), false, false).unwrap(); // for some reason the tv_nsec is not the same between what create_nod() and read_dir_plus() returns, so we reload it again let dir_attr = fs.get_inode(dir_attr.ino).unwrap(); let attr_parent = fs.get_inode(attr_parent.ino).unwrap(); let mut entries: Vec> = fs.read_dir_plus(dir_attr.ino).unwrap().collect(); - entries.sort_by(|a, b| a.as_ref().unwrap().name.cmp(&b.as_ref().unwrap().name)); + entries.sort_by(|a, b| a.as_ref().unwrap().name.expose_secret().cmp(&b.as_ref().unwrap().name.expose_secret())); let entries: Vec = entries.into_iter().map(|e| e.unwrap()).collect(); assert_eq!(entries.len(), 2); assert_eq!(vec![ DirectoryEntryPlus { ino: dir_attr.ino, - name: ".".to_string(), + name: SecretString::from_str(".").unwrap(), kind: FileType::Directory, attr: dir_attr, }, DirectoryEntryPlus { ino: parent, - name: "..".to_string(), + name: SecretString::from_str("..").unwrap(), kind: FileType::Directory, attr: attr_parent, }, @@ -393,33 +393,33 @@ fn test_read_dir_plus() { let iter = fs.read_dir_plus(parent); let mut entries: Vec = iter.unwrap().map(|e| e.unwrap()).collect(); - entries.sort_by(|a, b| a.name.cmp(&b.name)); + entries.sort_by(|a, b| a.name.expose_secret().cmp(&b.name.expose_secret())); let mut sample = vec![ DirectoryEntryPlus { ino: parent, - name: ".".to_string(), + name: SecretString::from_str(".").unwrap(), kind: FileType::Directory, attr: attr_parent, }, DirectoryEntryPlus { ino: ROOT_INODE, - name: "..".to_string(), + name: SecretString::from_str("..").unwrap(), kind: FileType::Directory, attr: attr_root, }, DirectoryEntryPlus { ino: file_attr.ino, - name: test_file_2.to_string(), + name: SecretString::new(test_file_2.expose_secret().to_owned()), kind: FileType::RegularFile, attr: file_attr, }, DirectoryEntryPlus { ino: dir_attr.ino, - name: test_dir_2.to_string(), + name: SecretString::new(test_dir_2.expose_secret().to_owned()), kind: FileType::Directory, attr: dir_attr, }]; - sample.sort_by(|a, b| a.name.cmp(&b.name)); + sample.sort_by(|a, b| a.name.expose_secret().cmp(&b.name.expose_secret())); assert_eq!(entries.len(), 4); assert_eq!(sample, entries); }); @@ -430,10 +430,10 @@ fn test_find_by_name() { run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_find_by_name") }, |setup| { let fs = setup.fs.as_mut().unwrap(); - let test_file = "test-file"; - fs.create_nod(ROOT_INODE, test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - assert!(fs.find_by_name(ROOT_INODE, test_file).unwrap().is_some()); - assert!(fs.find_by_name(ROOT_INODE, "invalid").unwrap().is_none()); + let test_file = SecretString::from_str("test-file").unwrap(); + fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + assert!(fs.find_by_name(ROOT_INODE, &test_file).unwrap().is_some()); + assert!(fs.find_by_name(ROOT_INODE, &SecretString::from_str("invalid").unwrap()).unwrap().is_none()); }); } @@ -442,22 +442,22 @@ fn test_remove_dir() { run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_remove_dir") }, |setup| { let fs = setup.fs.as_mut().unwrap(); - let test_dir = "test-dir"; - let (_fh, dir_attr) = fs.create_nod(ROOT_INODE, test_dir, create_attr_from_type(FileType::Directory), false, false).unwrap(); - let test_file = "test-file"; - let (_fh, file_attr) = fs.create_nod(dir_attr.ino, test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let test_dir = SecretString::from_str("test-dir").unwrap(); + let (_fh, dir_attr) = fs.create_nod(ROOT_INODE, &test_dir, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let test_file = SecretString::from_str("test-file").unwrap(); + let (_fh, file_attr) = fs.create_nod(dir_attr.ino, &test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - assert!(matches!(fs.remove_dir(ROOT_INODE, test_dir), Err(FsError::NotEmpty))); + assert!(matches!(fs.remove_dir(ROOT_INODE, &test_dir), Err(FsError::NotEmpty))); assert!(fs.data_dir.join(INODES_DIR).join(dir_attr.ino.to_string()).is_file()); assert!(fs.data_dir.join(INODES_DIR).join(file_attr.ino.to_string()).is_file()); - assert!(fs.data_dir.join(CONTENTS_DIR).join(dir_attr.ino.to_string()).join(fs.normalize_end_encrypt_file_name(test_file)).is_file()); + assert!(fs.data_dir.join(CONTENTS_DIR).join(dir_attr.ino.to_string()).join(fs.normalize_end_encrypt_file_name(&test_file)).is_file()); - fs.remove_file(dir_attr.ino, test_file).unwrap(); - assert!(fs.remove_dir(ROOT_INODE, test_dir).is_ok()); + fs.remove_file(dir_attr.ino, &test_file).unwrap(); + assert!(fs.remove_dir(ROOT_INODE, &test_dir).is_ok()); assert_ne!(fs.data_dir.join(INODES_DIR).join(dir_attr.ino.to_string()).exists(), true); assert_ne!(fs.data_dir.join(CONTENTS_DIR).join(dir_attr.ino.to_string()).exists(), true); - assert!(matches!(fs.remove_file(ROOT_INODE, "invalid"), Err(FsError::NotFound(_)))); + assert!(matches!(fs.remove_file(ROOT_INODE, &SecretString::from_str("invalid").unwrap()), Err(FsError::NotFound(_)))); }); } @@ -466,15 +466,15 @@ fn test_remove_file() { run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_remove_file") }, |setup| { let fs = setup.fs.as_mut().unwrap(); - let test_file = "test-file"; - let (_fh, attr) = fs.create_nod(ROOT_INODE, test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - assert!(fs.remove_file(ROOT_INODE, test_file).is_ok()); + let test_file = SecretString::from_str("test-file").unwrap(); + let (_fh, attr) = fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + assert!(fs.remove_file(ROOT_INODE, &test_file).is_ok()); assert_ne!(fs.data_dir.join(INODES_DIR).join(attr.ino.to_string()).is_file(), true); assert_ne!(fs.data_dir.join(CONTENTS_DIR).join(attr.ino.to_string()).is_file(), true); - assert_ne!(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(test_file).is_file(), true); - assert!(fs.find_by_name(ROOT_INODE, test_file).unwrap().is_none()); + assert_ne!(fs.data_dir.join(CONTENTS_DIR).join(ROOT_INODE_STR).join(fs.encrypt_string(&test_file)).is_file(), true); + assert!(fs.find_by_name(ROOT_INODE, &test_file).unwrap().is_none()); - assert!(matches!(fs.remove_file(ROOT_INODE, "invalid"), Err(FsError::NotFound(_)))); + assert!(matches!(fs.remove_file(ROOT_INODE, &SecretString::from_str("invalid").unwrap()), Err(FsError::NotFound(_)))); }); } @@ -483,8 +483,8 @@ fn test_write_all() { run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_write_all") }, |setup| { let mut fs = setup.fs.as_mut().unwrap(); - let test_file = "test-file"; - let (fh, attr) = fs.create_nod(ROOT_INODE, test_file, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); + let test_file = SecretString::from_str("test-file").unwrap(); + let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); let data = "test-42"; fs.write_all(attr.ino, 0, data.as_bytes(), fh).unwrap(); fs.flush(fh).unwrap(); @@ -511,8 +511,8 @@ fn test_write_all() { // offset before current position, several blocks // first write no bytes to the end to move the position - let test_file_2 = "test-file-2"; - let (fh, attr) = fs.create_nod(ROOT_INODE, test_file_2, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); + let test_file_2 = SecretString::from_str("test-file-2").unwrap(); + let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file_2, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); let data = "test-42-37-42"; fs.write_all(attr.ino, 0, data.as_bytes(), fh).unwrap(); fs.write_all(attr.ino, data.len() as u64, &[0_u8; 0], fh).unwrap(); @@ -526,8 +526,8 @@ fn test_write_all() { // write before current position then write to the end, also check it preserves the content from // the first write to offset to end of the file - let test_file_3 = "test-file-3"; - let (fh, attr) = fs.create_nod(ROOT_INODE, test_file_3, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); + let test_file_3 = SecretString::from_str("test-file-3").unwrap(); + let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file_3, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); let data = "test-42-37"; fs.write_all(attr.ino, 0, data.as_bytes(), fh).unwrap(); fs.write_all(attr.ino, 5, b"37", fh).unwrap(); @@ -541,8 +541,8 @@ fn test_write_all() { let fh = fs.open(attr.ino, false, true).unwrap(); assert!(matches!(fs.write_all(ROOT_INODE, 0, &buf, fh), Err(FsError::InvalidInodeType))); assert!(matches!(fs.write_all(0, 0, &buf, fh), Err(FsError::InodeNotFound))); - let test_dir = "test-dir"; - let (fh, dir_attr) = fs.create_nod(ROOT_INODE, test_dir, create_attr_from_type(FileType::Directory), false, true).unwrap(); + let test_dir = SecretString::from_str("test-dir").unwrap(); + let (fh, dir_attr) = fs.create_nod(ROOT_INODE, &test_dir, create_attr_from_type(FileType::Directory), false, true).unwrap(); assert!(matches!(fs.write_all(dir_attr.ino, 0, &buf, fh), Err(FsError::InvalidInodeType))); }); } @@ -552,9 +552,9 @@ fn test_read() { run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_read") }, |setup| { let fs = setup.fs.as_mut().unwrap(); - let test_test_file = "test-file"; + let test_test_file = SecretString::from_str("test-file").unwrap(); let test_file = test_test_file; - let (fh, attr) = fs.create_nod(ROOT_INODE, test_file, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); + let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); let data = b"test-42"; let mut buf = [0; 7]; fs.write_all(attr.ino, 0, data, fh).unwrap(); @@ -586,8 +586,8 @@ fn test_read() { assert_eq!(len, 0); // if it picks up new value after a write after current read position - let test_file_2 = "test-file-2"; - let (fh, attr) = fs.create_nod(ROOT_INODE, test_file_2, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); + let test_file_2 = SecretString::from_str("test-file-2").unwrap(); + let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file_2, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); let data = "test-42"; fs.write_all(attr.ino, 0, data.as_bytes(), fh).unwrap(); fs.flush(fh).unwrap(); @@ -604,8 +604,8 @@ fn test_read() { assert_eq!(new_data, String::from_utf8(buf.to_vec()).unwrap()); // if it picks up new value after a write before current read position - let test_file_3 = "test-file-3"; - let (fh, attr) = fs.create_nod(ROOT_INODE, test_file_3, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); + let test_file_3 = SecretString::from_str("test-file-3").unwrap(); + let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file_3, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); let data = "test-42-37"; fs.write_all(attr.ino, 0, data.as_bytes(), fh).unwrap(); fs.flush(fh).unwrap(); @@ -622,8 +622,8 @@ fn test_read() { assert_eq!(new_data, String::from_utf8(buf.to_vec()).unwrap()); // if it continues to read correctly after a write before current read position - let test_file_4 = "test-file-4"; - let (fh, attr) = fs.create_nod(ROOT_INODE, test_file_4, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); + let test_file_4 = SecretString::from_str("test-file-4").unwrap(); + let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file_4, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); let data = "test-42-37"; fs.write_all(attr.ino, 0, data.as_bytes(), fh).unwrap(); fs.flush(fh).unwrap(); @@ -643,8 +643,8 @@ fn test_read() { let mut buf = [0; 0]; assert!(matches!(fs.read(ROOT_INODE, 0, &mut buf, fh), Err(FsError::InvalidInodeType))); assert!(matches!(fs.read(0, 0,&mut buf, fh), Err(FsError::InodeNotFound))); - let test_dir = "test-dir"; - let (fh, dir_attr) = fs.create_nod(ROOT_INODE, test_dir, create_attr_from_type(FileType::Directory), true, false).unwrap(); + let test_dir = SecretString::from_str("test-dir").unwrap(); + let (fh, dir_attr) = fs.create_nod(ROOT_INODE, &test_dir, create_attr_from_type(FileType::Directory), true, false).unwrap(); assert!(matches!(fs.read(dir_attr.ino, 0, &mut buf, fh), Err(FsError::InvalidInodeType))); }); } @@ -654,7 +654,8 @@ fn test_truncate() { run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_truncate") }, |setup| { let mut fs = setup.fs.as_mut().unwrap(); - let (fh, attr) = fs.create_nod(ROOT_INODE, "test-file", create_attr_from_type(FileType::RegularFile), false, true).unwrap(); + let test_file = SecretString::from_str("test-file").unwrap(); + let (fh, attr) = fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, true).unwrap(); let data = "test-42"; fs.write_all(attr.ino, 0, data.as_bytes(), fh).unwrap(); fs.flush(fh).unwrap(); @@ -695,15 +696,15 @@ fn test_copy_file_range() { run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_copy_file_range") }, |setup| { let fs = setup.fs.as_mut().unwrap(); - let test_file_1 = "test-file-1"; - let (fh, attr_1) = fs.create_nod(ROOT_INODE, test_file_1, create_attr_from_type(FileType::RegularFile), true, true).unwrap(); + let test_file_1 = SecretString::from_str("test-file-1").unwrap(); + let (fh, attr_1) = fs.create_nod(ROOT_INODE, &test_file_1, create_attr_from_type(FileType::RegularFile), true, true).unwrap(); let data = "test-42"; fs.write_all(attr_1.ino, 0, data.as_bytes(), fh).unwrap(); fs.flush(fh).unwrap(); fs.release(fh).unwrap(); let fh = fs.open(attr_1.ino, true, false).unwrap(); - let test_file_2 = "test-file-2"; - let (fh2, attr_2) = fs.create_nod(ROOT_INODE, test_file_2, create_attr_from_type(FileType::RegularFile), true, true).unwrap(); + let test_file_2 = SecretString::from_str("test-file-2").unwrap(); + let (fh2, attr_2) = fs.create_nod(ROOT_INODE, &test_file_2, create_attr_from_type(FileType::RegularFile), true, true).unwrap(); // whole file let len = fs.copy_file_range(attr_1.ino, 0, attr_2.ino, 0, 7, fh, fh2).unwrap(); @@ -749,231 +750,237 @@ fn test_rename() { // new file in same directory let new_parent = ROOT_INODE; - let file_1 = "file-1"; - let (_, attr) = fs.create_nod(ROOT_INODE, file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let file_1_new = "file-1-new"; - fs.rename(ROOT_INODE, file_1, new_parent, file_1_new).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, file_1), true); - assert_eq!(fs.exists_by_name(new_parent, file_1_new), true); - let new_attr = fs.find_by_name(new_parent, file_1_new).unwrap().unwrap(); + let file_1 = SecretString::from_str("file-1").unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let file_1_new = SecretString::from_str("file-1-new").unwrap(); + fs.rename(ROOT_INODE, &file_1, new_parent, &file_1_new).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &file_1), true); + assert_eq!(fs.exists_by_name(new_parent, &file_1_new), true); + let new_attr = fs.find_by_name(new_parent, &file_1_new).unwrap().unwrap(); assert_eq!(fs.is_file(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_1).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_1_new).count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_1_new.expose_secret()).count(), 1); // new directory in same directory let new_parent = ROOT_INODE; - let dir_1 = "dir-1"; - let (_, attr) = fs.create_nod(ROOT_INODE, dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); - let dir_1_new = "dir-1-new"; - fs.rename(ROOT_INODE, dir_1, new_parent, dir_1_new).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, dir_1), true); - assert_eq!(fs.exists_by_name(new_parent, dir_1_new), true); - let new_attr = fs.find_by_name(new_parent, dir_1_new).unwrap().unwrap(); + let dir_1 = SecretString::from_str("dir-1").unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let dir_1_new = SecretString::from_str("dir-1-new").unwrap(); + fs.rename(ROOT_INODE, &dir_1, new_parent, &dir_1_new).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &dir_1), true); + assert_eq!(fs.exists_by_name(new_parent, &dir_1_new), true); + let new_attr = fs.find_by_name(new_parent, &dir_1_new).unwrap().unwrap(); assert_eq!(fs.is_dir(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_1).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_1_new).count(), 1); - assert_eq!(fs.find_by_name(new_attr.ino, "..").unwrap().unwrap().ino, new_parent); - assert_eq!(fs.find_by_name(new_attr.ino, ".").unwrap().unwrap().ino, new_attr.ino); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == "..").count(), 1); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == ".").count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_1_new.expose_secret()).count(), 1); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str("..").unwrap()).unwrap().unwrap().ino, new_parent); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str(".").unwrap()).unwrap().unwrap().ino, new_attr.ino); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..").count(), 1); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".").count(), 1); - let (_, new_parent_attr) = fs.create_nod(ROOT_INODE, "dir-new-parent", create_attr_from_type(FileType::Directory), false, false).unwrap(); + let dir_new_parent = SecretString::from_str("dir-new-parent").unwrap(); + let (_, new_parent_attr) = fs.create_nod(ROOT_INODE, &dir_new_parent, create_attr_from_type(FileType::Directory), false, false).unwrap(); // new file to another directory let new_parent = new_parent_attr.ino; - let (_, attr) = fs.create_nod(ROOT_INODE, file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let file_2 = "file-2"; - fs.rename(ROOT_INODE, file_1, new_parent, file_2).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, file_1), true); - assert_eq!(fs.exists_by_name(new_parent, file_2), true); - let new_attr = fs.find_by_name(new_parent, file_2).unwrap().unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let file_2 = SecretString::from_str("file-2").unwrap(); + fs.rename(ROOT_INODE, &file_1, new_parent, &file_2).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &file_1), true); + assert_eq!(fs.exists_by_name(new_parent, &file_2), true); + let new_attr = fs.find_by_name(new_parent, &file_2).unwrap().unwrap(); assert_eq!(fs.is_file(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_1).count(), 0); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == "file-new").count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_2).count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| { + let file_new = "file-new"; + entry.as_ref().unwrap().name.expose_secret() == file_new + }).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_2.expose_secret()).count(), 1); // new directory to another directory let new_parent = new_parent_attr.ino; - let (_, attr) = fs.create_nod(ROOT_INODE, dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); - let dir_2 = "dir-2"; - fs.rename(ROOT_INODE, dir_1, new_parent, dir_2).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, dir_1), true); - assert_eq!(fs.exists_by_name(new_parent, dir_2), true); - let new_attr = fs.find_by_name(new_parent, dir_2).unwrap().unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let dir_2 = SecretString::from_str("dir-2").unwrap(); + fs.rename(ROOT_INODE, &dir_1, new_parent, &dir_2).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &dir_1), true); + assert_eq!(fs.exists_by_name(new_parent, &dir_2), true); + let new_attr = fs.find_by_name(new_parent, &dir_2).unwrap().unwrap(); assert_eq!(fs.is_dir(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_1).count(), 0); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_2).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_2).count(), 1); - assert_eq!(fs.find_by_name(new_attr.ino, "..").unwrap().unwrap().ino, new_parent); - assert_eq!(fs.find_by_name(new_attr.ino, ".").unwrap().unwrap().ino, new_attr.ino); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == "..").count(), 1); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == ".").count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_2.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_2.expose_secret()).count(), 1); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str("..").unwrap()).unwrap().unwrap().ino, new_parent); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str(".").unwrap()).unwrap().unwrap().ino, new_attr.ino); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..").count(), 1); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".").count(), 1); // file to existing file in same directory let new_parent = ROOT_INODE; - let (_, attr) = fs.create_nod(ROOT_INODE, file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let (_, _attr_2) = fs.create_nod(new_parent, file_2, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - fs.rename(ROOT_INODE, file_1, new_parent, file_2).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, file_1), true); - assert_eq!(fs.exists_by_name(new_parent, file_2), true); - let new_attr = fs.find_by_name(new_parent, file_2).unwrap().unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let (_, _attr_2) = fs.create_nod(new_parent, &file_2, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + fs.rename(ROOT_INODE, &file_1, new_parent, &file_2).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &file_1), true); + assert_eq!(fs.exists_by_name(new_parent, &file_2), true); + let new_attr = fs.find_by_name(new_parent, &file_2).unwrap().unwrap(); assert_eq!(fs.is_file(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_1).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_2).count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_2.expose_secret()).count(), 1); // directory to existing directory in same directory let new_parent = ROOT_INODE; - let (_, attr) = fs.create_nod(ROOT_INODE, dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); - let (_, _attr_2) = fs.create_nod(new_parent, dir_2, create_attr_from_type(FileType::Directory), false, false).unwrap(); - fs.rename(ROOT_INODE, dir_1, new_parent, dir_2).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, dir_1), true); - assert_eq!(fs.exists_by_name(new_parent, dir_2), true); - let new_attr = fs.find_by_name(new_parent, dir_2).unwrap().unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let (_, _attr_2) = fs.create_nod(new_parent, &dir_2, create_attr_from_type(FileType::Directory), false, false).unwrap(); + fs.rename(ROOT_INODE, &dir_1, new_parent, &dir_2).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &dir_1), true); + assert_eq!(fs.exists_by_name(new_parent, &dir_2), true); + let new_attr = fs.find_by_name(new_parent, &dir_2).unwrap().unwrap(); assert_eq!(fs.is_dir(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_1).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_2).count(), 1); - assert_eq!(fs.find_by_name(new_attr.ino, "..").unwrap().unwrap().ino, new_parent); - assert_eq!(fs.find_by_name(new_attr.ino, ".").unwrap().unwrap().ino, new_attr.ino); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == "..").count(), 1); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == ".").count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_2.expose_secret()).count(), 1); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str("..").unwrap()).unwrap().unwrap().ino, new_parent); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str(".").unwrap()).unwrap().unwrap().ino, new_attr.ino); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..").count(), 1); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".").count(), 1); // file to existing file in another directory let new_parent = new_parent_attr.ino; - let (_, attr) = fs.create_nod(ROOT_INODE, file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let (_, _attr_2) = fs.create_nod(new_parent, file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - fs.rename(ROOT_INODE, file_1, new_parent, file_1).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, file_1), true); - assert_eq!(fs.exists_by_name(new_parent, file_1), true); - let new_attr = fs.find_by_name(new_parent, file_1).unwrap().unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let (_, _attr_2) = fs.create_nod(new_parent, &file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + fs.rename(ROOT_INODE, &file_1, new_parent, &file_1).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &file_1), true); + assert_eq!(fs.exists_by_name(new_parent, &file_1), true); + let new_attr = fs.find_by_name(new_parent, &file_1).unwrap().unwrap(); assert_eq!(fs.is_file(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_1).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_1).count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_1.expose_secret()).count(), 1); // directory to existing directory in another directory let new_parent = new_parent_attr.ino; - let (_, attr) = fs.create_nod(ROOT_INODE, dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); - let (_, _attr_2) = fs.create_nod(new_parent, dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); - fs.rename(ROOT_INODE, dir_1, new_parent, dir_1).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, dir_1), true); - assert_eq!(fs.exists_by_name(new_parent, dir_1), true); - let new_attr = fs.find_by_name(new_parent, dir_1).unwrap().unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let (_, _attr_2) = fs.create_nod(new_parent, &dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); + fs.rename(ROOT_INODE, &dir_1, new_parent, &dir_1).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &dir_1), true); + assert_eq!(fs.exists_by_name(new_parent, &dir_1), true); + let new_attr = fs.find_by_name(new_parent, &dir_1).unwrap().unwrap(); assert_eq!(fs.is_dir(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_1).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_1).count(), 1); - assert_eq!(fs.find_by_name(new_attr.ino, "..").unwrap().unwrap().ino, new_parent); - assert_eq!(fs.find_by_name(new_attr.ino, ".").unwrap().unwrap().ino, new_attr.ino); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == "..").count(), 1); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == ".").count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_1.expose_secret()).count(), 1); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str("..").unwrap()).unwrap().unwrap().ino, new_parent); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str(".").unwrap()).unwrap().unwrap().ino, new_attr.ino); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..").count(), 1); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".").count(), 1); // overwriting directory with file let new_parent = ROOT_INODE; - let (_, attr) = fs.create_nod(ROOT_INODE, file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - let (_, _attr_2) = fs.create_nod(new_parent, dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); - fs.rename(ROOT_INODE, file_1, new_parent, dir_1).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, file_1), true); - assert_eq!(fs.exists_by_name(new_parent, dir_1), true); - let new_attr = fs.find_by_name(new_parent, dir_1).unwrap().unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &file_1, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let (_, _attr_2) = fs.create_nod(new_parent, &dir_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); + fs.rename(ROOT_INODE, &file_1, new_parent, &dir_1).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &file_1), true); + assert_eq!(fs.exists_by_name(new_parent, &dir_1), true); + let new_attr = fs.find_by_name(new_parent, &dir_1).unwrap().unwrap(); assert_eq!(fs.is_file(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_1).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_1).count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_1.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_1.expose_secret()).count(), 1); // overwriting file with directory let new_parent = ROOT_INODE; - let dir_3 = "dir-3"; - let (_, attr) = fs.create_nod(ROOT_INODE, dir_3, create_attr_from_type(FileType::Directory), false, false).unwrap(); - let (_, _attr_2) = fs.create_nod(new_parent, file_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); - fs.rename(ROOT_INODE, dir_3, new_parent, file_1).unwrap(); - assert_ne!(fs.exists_by_name(ROOT_INODE, dir_3), true); - assert_eq!(fs.exists_by_name(new_parent, file_1), true); - let new_attr = fs.find_by_name(new_parent, file_1).unwrap().unwrap(); + let dir_3 = SecretString::from_str("dir-3").unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &dir_3, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let (_, _attr_2) = fs.create_nod(new_parent, &file_1, create_attr_from_type(FileType::Directory), false, false).unwrap(); + fs.rename(ROOT_INODE, &dir_3, new_parent, &file_1).unwrap(); + assert_ne!(fs.exists_by_name(ROOT_INODE, &dir_3), true); + assert_eq!(fs.exists_by_name(new_parent, &file_1), true); + let new_attr = fs.find_by_name(new_parent, &file_1).unwrap().unwrap(); assert_eq!(fs.is_dir(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_3).count(), 0); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_1).count(), 1); - assert_eq!(fs.find_by_name(new_attr.ino, "..").unwrap().unwrap().ino, new_parent); - assert_eq!(fs.find_by_name(new_attr.ino, ".").unwrap().unwrap().ino, new_attr.ino); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == "..").count(), 1); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == ".").count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_3.expose_secret()).count(), 0); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_1.expose_secret()).count(), 1); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str("..").unwrap()).unwrap().unwrap().ino, new_parent); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str(".").unwrap()).unwrap().unwrap().ino, new_attr.ino); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..").count(), 1); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".").count(), 1); // overwriting non-empty directory let new_parent = ROOT_INODE; - let (_, attr) = fs.create_nod(ROOT_INODE, dir_3, create_attr_from_type(FileType::Directory), false, false).unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &dir_3, create_attr_from_type(FileType::Directory), false, false).unwrap(); let _attr_2 = new_parent_attr; - let name_2 = "dir-new-parent"; - assert!(matches!(fs.rename(ROOT_INODE, dir_3, new_parent, name_2), Err(FsError::NotEmpty))); - assert_eq!(fs.exists_by_name(ROOT_INODE, dir_3), true); - assert_eq!(fs.exists_by_name(new_parent, name_2), true); - let attr_3 = fs.find_by_name(ROOT_INODE, dir_3).unwrap().unwrap(); + let name_2 = dir_new_parent; + assert!(matches!(fs.rename(ROOT_INODE, &dir_3, new_parent, &name_2), Err(FsError::NotEmpty))); + assert_eq!(fs.exists_by_name(ROOT_INODE, &dir_3), true); + assert_eq!(fs.exists_by_name(new_parent, &name_2), true); + let attr_3 = fs.find_by_name(ROOT_INODE, &dir_3).unwrap().unwrap(); assert_eq!(fs.is_dir(attr_3.ino), true); - let attr_2 = fs.find_by_name(new_parent, name_2).unwrap().unwrap(); + let attr_2 = fs.find_by_name(new_parent, &name_2).unwrap().unwrap(); assert_eq!(fs.is_dir(attr_2.ino), true); - let new_attr = fs.find_by_name(new_parent, dir_3).unwrap().unwrap(); + let new_attr = fs.find_by_name(new_parent, &dir_3).unwrap().unwrap(); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - let new_attr_2 = fs.find_by_name(new_parent, name_2).unwrap().unwrap(); + let new_attr_2 = fs.find_by_name(new_parent, &name_2).unwrap().unwrap(); assert_eq!(new_attr_2.ino, attr_2.ino); assert_eq!(new_attr_2.kind, attr_2.kind); - assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_3).count(), 1); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == name_2).count(), 1); - assert_eq!(fs.find_by_name(new_attr_2.ino, "..").unwrap().unwrap().ino, new_parent); - assert_eq!(fs.find_by_name(new_attr_2.ino, ".").unwrap().unwrap().ino, new_attr_2.ino); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == "..").count(), 1); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == ".").count(), 1); + assert_eq!(fs.read_dir(ROOT_INODE).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_3.expose_secret()).count(), 1); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == name_2.expose_secret()).count(), 1); + assert_eq!(fs.find_by_name(new_attr_2.ino, &SecretString::from_str("..").unwrap()).unwrap().unwrap().ino, new_parent); + assert_eq!(fs.find_by_name(new_attr_2.ino, &SecretString::from_str(".").unwrap()).unwrap().unwrap().ino, new_attr_2.ino); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..").count(), 1); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".").count(), 1); // same file in same directory let new_parent = ROOT_INODE; - let file_3 = "file-3"; - let (_, attr) = fs.create_nod(ROOT_INODE, file_3, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - fs.rename(ROOT_INODE, file_3, new_parent, file_3).unwrap(); - assert_eq!(fs.exists_by_name(new_parent, file_3), true); - let new_attr = fs.find_by_name(new_parent, file_3).unwrap().unwrap(); + let file_3 = SecretString::from_str("file-3").unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &file_3, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + fs.rename(ROOT_INODE, &file_3, new_parent, &file_3).unwrap(); + assert_eq!(fs.exists_by_name(new_parent, &file_3), true); + let new_attr = fs.find_by_name(new_parent, &file_3).unwrap().unwrap(); assert_eq!(fs.is_file(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == file_3).count(), 1); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == file_3.expose_secret()).count(), 1); // same directory in same directory let new_parent = ROOT_INODE; - let dir_5 = "dir-5"; - let (_, attr) = fs.create_nod(ROOT_INODE, dir_5, create_attr_from_type(FileType::Directory), false, false).unwrap(); - fs.rename(ROOT_INODE, dir_5, new_parent, dir_5).unwrap(); - assert_eq!(fs.exists_by_name(new_parent, dir_5), true); - let new_attr = fs.find_by_name(new_parent, dir_5).unwrap().unwrap(); + let dir_5 = SecretString::from_str("dir-5").unwrap(); + let (_, attr) = fs.create_nod(ROOT_INODE, &dir_5, create_attr_from_type(FileType::Directory), false, false).unwrap(); + fs.rename(ROOT_INODE, &dir_5, new_parent, &dir_5).unwrap(); + assert_eq!(fs.exists_by_name(new_parent, &dir_5), true); + let new_attr = fs.find_by_name(new_parent, &dir_5).unwrap().unwrap(); assert_eq!(fs.is_dir(new_attr.ino), true); assert_eq!(new_attr.ino, attr.ino); assert_eq!(new_attr.kind, attr.kind); - assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == dir_5).count(), 1); - assert_eq!(fs.find_by_name(new_attr.ino, "..").unwrap().unwrap().ino, new_parent); - assert_eq!(fs.find_by_name(new_attr.ino, ".").unwrap().unwrap().ino, new_attr.ino); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == "..").count(), 1); - assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name == ".").count(), 1); + assert_eq!(fs.read_dir(new_parent).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == dir_5.expose_secret()).count(), 1); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str("..").unwrap()).unwrap().unwrap().ino, new_parent); + assert_eq!(fs.find_by_name(new_attr.ino, &SecretString::from_str(".").unwrap()).unwrap().unwrap().ino, new_attr.ino); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..").count(), 1); + assert_eq!(fs.read_dir(new_attr.ino).unwrap().into_iter().filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".").count(), 1); // invalid nodes and name - assert!(matches!(fs.rename(0, "invalid", 0, "invalid"), Err(FsError::InodeNotFound))); - let (_, attr_file) = fs.create_nod(ROOT_INODE, "existing-file", create_attr_from_type(FileType::RegularFile), false, false).unwrap(); - assert!(matches!(fs.rename(attr_file.ino, "invalid", 0, "invalid"), Err(FsError::InvalidInodeType))); - assert!(matches!(fs.rename(ROOT_INODE, "invalid", ROOT_INODE, "invalid"), Err(FsError::NotFound(_)))); - assert!(matches!(fs.rename(ROOT_INODE, "existing-file", 0, "invalid"), Err(FsError::InodeNotFound))); - assert!(matches!(fs.rename(ROOT_INODE, "existing-file", attr_file.ino, "invalid"), Err(FsError::InvalidInodeType))); + let invalid = SecretString::from_str("invalid").unwrap(); + assert!(matches!(fs.rename(0, &invalid, 0, &invalid), Err(FsError::InodeNotFound))); + let existing_file = SecretString::from_str("existing-file").unwrap(); + let (_, attr_file) = fs.create_nod(ROOT_INODE, &existing_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + assert!(matches!(fs.rename(attr_file.ino, &invalid, 0, &invalid), Err(FsError::InvalidInodeType))); + assert!(matches!(fs.rename(ROOT_INODE, &invalid, ROOT_INODE, &invalid), Err(FsError::NotFound(_)))); + assert!(matches!(fs.rename(ROOT_INODE, &existing_file, 0, &invalid), Err(FsError::InodeNotFound))); + assert!(matches!(fs.rename(ROOT_INODE, &existing_file, attr_file.ino, &invalid), Err(FsError::InvalidInodeType))); }); } @@ -982,8 +989,8 @@ fn test_open() { run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_open") }, |setup| { let fs = setup.fs.as_mut().unwrap(); - let test_file = "test-file"; - let (_fh, attr) = fs.create_nod(ROOT_INODE, test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); + let test_file = SecretString::from_str("test-file").unwrap(); + let (_fh, attr) = fs.create_nod(ROOT_INODE, &test_file, create_attr_from_type(FileType::RegularFile), false, false).unwrap(); // single read let fh = fs.open(attr.ino, true, false).unwrap(); assert_ne!(fh, 0); diff --git a/src/encryptedfs_fuse3.rs b/src/encryptedfs_fuse3.rs index 8d4cbee0..6ec4a7b6 100644 --- a/src/encryptedfs_fuse3.rs +++ b/src/encryptedfs_fuse3.rs @@ -6,6 +6,7 @@ use std::io::{BufRead, BufReader}; use std::iter::Skip; use std::num::NonZeroU32; use std::os::raw::c_int; +use std::str::FromStr; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use bytes::Bytes; @@ -17,7 +18,7 @@ use futures_util::stream::Iter; use libc::{EACCES, EBADF, EIO, ENOENT, ENOTDIR, ENOTEMPTY, EPERM}; use parking_lot::{const_reentrant_mutex, RawMutex, RawThreadId, ReentrantMutex}; use parking_lot::lock_api::ReentrantMutexGuard; -use secrecy::SecretString; +use secrecy::{ExposeSecret, SecretString}; use tracing::{debug, error, instrument, trace, warn}; use crate::encryptedfs::{EncryptedFs, Cipher, FileAttr, FileType, FsError, FsResult}; @@ -61,7 +62,7 @@ impl Iterator for DirectoryEntryIterator { Some(Ok(DirectoryEntry { inode: entry.ino, kind, - name: OsString::from(entry.name), + name: OsString::from(entry.name.expose_secret()), offset: self.1 as i64, })) } @@ -96,7 +97,7 @@ impl Iterator for DirectoryEntryPlusIterator { inode: entry.ino, generation: 0, kind, - name: OsString::from(entry.name), + name: OsString::from(entry.name.expose_secret()), offset: self.1 as i64, attr: from_attr(entry.attr), entry_ttl: TTL, @@ -188,7 +189,7 @@ impl EncryptedFsFuse3 { attr.uid = req.uid; attr.gid = creation_gid(&parent_attr, req.gid); - match self.get_fs().borrow_mut().create_nod(parent, name.to_str().unwrap(), attr, read, write) { + match self.get_fs().borrow_mut().create_nod(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap(), attr, read, write) { Ok((fh, attr)) => Ok((fh, attr)), Err(err) => { error!(err = %err); @@ -274,7 +275,7 @@ impl Filesystem for EncryptedFsFuse3 { } } - let attr = match self.get_fs().borrow_mut().find_by_name(parent, name.to_str().unwrap()) { + let attr = match self.get_fs().borrow_mut().find_by_name(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap()) { Ok(Some(attr)) => attr, Err(err) => { error!(err = %err); @@ -575,7 +576,7 @@ impl Filesystem for EncryptedFsFuse3 { attr.uid = req.uid; attr.gid = creation_gid(&parent_attr, req.gid); - match self.get_fs().borrow_mut().create_nod(parent, name.to_str().unwrap(), attr, false, false) { + match self.get_fs().borrow_mut().create_nod(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap(), attr, false, false) { Err(err) => { error!(err = %err); return Err(ENOENT.into()); @@ -613,7 +614,7 @@ impl Filesystem for EncryptedFsFuse3 { return Err(EACCES.into()); } - let attr = match self.get_fs().borrow_mut().find_by_name(parent, name.to_str().unwrap()) { + let attr = match self.get_fs().borrow_mut().find_by_name(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap()) { Ok(Some(attr)) => attr, Err(err) => { error!(err = %err); @@ -632,7 +633,7 @@ impl Filesystem for EncryptedFsFuse3 { return Err(EACCES.into()); } - if let Err(err) = self.get_fs().borrow_mut().remove_file(parent, name.to_str().unwrap()) { + if let Err(err) = self.get_fs().borrow_mut().remove_file(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap()) { error!(err = %err); return Err(ENOENT.into()); } @@ -661,7 +662,7 @@ impl Filesystem for EncryptedFsFuse3 { return Err(EACCES.into()); } - let attr = match self.get_fs().borrow_mut().find_by_name(parent, name.to_str().unwrap()) { + let attr = match self.get_fs().borrow_mut().find_by_name(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap()) { Ok(Some(attr)) => attr, _ => { error!(parent, name = name.to_str().unwrap()); @@ -683,7 +684,7 @@ impl Filesystem for EncryptedFsFuse3 { return Err(EACCES.into()); } - if let Err(err) = self.get_fs().borrow_mut().remove_dir(parent, name.to_str().unwrap()) { + if let Err(err) = self.get_fs().borrow_mut().remove_dir(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap()) { error!(err = %err); return Err(EBADF.into()); } @@ -702,7 +703,7 @@ impl Filesystem for EncryptedFsFuse3 { ) -> Result<()> { trace!(""); - let attr = if let Ok(Some(attr)) = self.get_fs().borrow_mut().find_by_name(parent, name.to_str().unwrap()) { + let attr = if let Ok(Some(attr)) = self.get_fs().borrow_mut().find_by_name(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap()) { attr } else { error!(parent, name = name.to_str().unwrap(), new_name = new_name.to_str().unwrap()); @@ -749,7 +750,7 @@ impl Filesystem for EncryptedFsFuse3 { // "Sticky bit" handling in new_parent if new_parent_attr.perm & libc::S_ISVTX as u16 != 0 { - if let Ok(Some(new_attrs)) = self.get_fs().borrow_mut().find_by_name(new_parent, new_name.to_str().unwrap()) { + if let Ok(Some(new_attrs)) = self.get_fs().borrow_mut().find_by_name(new_parent, &SecretString::from_str(new_name.to_str().unwrap()).unwrap()) { if req.uid != 0 && req.uid != new_parent_attr.uid && req.uid != new_attrs.uid @@ -774,7 +775,7 @@ impl Filesystem for EncryptedFsFuse3 { return Err(EACCES.into()); } - match self.get_fs().borrow_mut().rename(parent, name.to_str().unwrap(), new_parent, new_name.to_str().unwrap()) { + match self.get_fs().borrow_mut().rename(parent, &SecretString::from_str(name.to_str().unwrap()).unwrap(), new_parent, &SecretString::from_str(new_name.to_str().unwrap()).unwrap()) { Ok(_) => Ok(()), Err(FsError::NotEmpty) => { Err(ENOTEMPTY.into()) diff --git a/src/lib.rs b/src/lib.rs index b7a908da..367ef8c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,8 @@ //! //! #[tokio::main] //! async fn main() { -//! run_fuse("/tmp/rencfs", "/tmp/rencfs_data", SecretString::new("password".to_string()), Cipher::ChaCha20, false, false, false, false).await.unwrap(); +//! use std::str::FromStr; +//! run_fuse("/tmp/rencfs", "/tmp/rencfs_data", SecretString::from_str("password").unwrap(), Cipher::ChaCha20, false, false, false, false).await.unwrap(); //! } //! ``` //! @@ -89,7 +90,8 @@ //! let cipher = rencfs::encryptedfs::Cipher::ChaCha20; //! let mut fs = EncryptedFs::new(data_dir, password, cipher ).unwrap(); //! -//! let (fh, attr) = fs.create_nod(ROOT_INODE, "file1", create_attr(FileType::RegularFile), false, true).unwrap(); +//! let file1 = SecretString::from_str("file1").unwrap(); +//! let (fh, attr) = fs.create_nod(ROOT_INODE, &file1, create_attr(FileType::RegularFile), false, true).unwrap(); //! let data = "Hello, world!"; //! fs.write_all(attr.ino, 0, data.as_bytes(), fh).unwrap(); //! fs.flush(fh).unwrap();