diff --git a/clients/filesystem-fuse/src/default_raw_filesystem.rs b/clients/filesystem-fuse/src/default_raw_filesystem.rs index be0be830588..634d506d6df 100644 --- a/clients/filesystem-fuse/src/default_raw_filesystem.rs +++ b/clients/filesystem-fuse/src/default_raw_filesystem.rs @@ -18,10 +18,11 @@ */ use crate::config::AppConfig; use crate::filesystem::{ - FileStat, FileSystemContext, PathFileSystem, RawFileSystem, Result, INITIAL_FILE_ID, - ROOT_DIR_FILE_ID, ROOT_DIR_PARENT_FILE_ID, ROOT_DIR_PATH, + FileStat, FileSystemContext, PathFileSystem, RawFileSystem, Result, FS_META_FILE_ID, + FS_META_FILE_NAME, FS_META_FILE_PATH, INITIAL_FILE_ID, ROOT_DIR_FILE_ID, + ROOT_DIR_PARENT_FILE_ID, ROOT_DIR_PATH, }; -use crate::opened_file::{FileHandle, OpenFileFlags}; +use crate::opened_file::{FileHandle, OpenFileFlags, OpenedFile}; use crate::opened_file_manager::OpenedFileManager; use async_trait::async_trait; use bytes::Bytes; @@ -133,6 +134,19 @@ impl DefaultRawFileSystem { let mut file_manager = self.file_entry_manager.write().await; file_manager.insert(parent_file_id, file_id, path); } + + fn meta_file_stat(&self) -> FileStat { + let mut meta_file_stat = + FileStat::new_file_filestat_with_path(Path::new(FS_META_FILE_PATH), 0); + meta_file_stat.set_file_id(ROOT_DIR_FILE_ID, FS_META_FILE_ID); + meta_file_stat + } + + fn root_file_stat(&self) -> FileStat { + let mut root_file_stat = FileStat::new_dir_filestat_with_path(Path::new(ROOT_DIR_PATH)); + root_file_stat.set_file_id(ROOT_DIR_PARENT_FILE_ID, ROOT_DIR_FILE_ID); + root_file_stat + } } #[async_trait] @@ -145,6 +159,13 @@ impl RawFileSystem for DefaultRawFileSystem { Path::new(ROOT_DIR_PATH), ) .await; + + self.insert_file_entry_locked( + ROOT_DIR_FILE_ID, + FS_META_FILE_ID, + Path::new(FS_META_FILE_PATH), + ) + .await; self.fs.init().await } @@ -169,6 +190,13 @@ impl RawFileSystem for DefaultRawFileSystem { } async fn stat(&self, file_id: u64) -> Result { + if file_id == ROOT_DIR_FILE_ID { + return Ok(self.root_file_stat()); + } + if file_id == FS_META_FILE_ID { + return Ok(self.meta_file_stat()); + } + let file_entry = self.get_file_entry(file_id).await?; let mut file_stat = self.fs.stat(&file_entry.path).await?; file_stat.set_file_id(file_entry.parent_file_id, file_entry.file_id); @@ -176,8 +204,11 @@ impl RawFileSystem for DefaultRawFileSystem { } async fn lookup(&self, parent_file_id: u64, name: &OsStr) -> Result { - let parent_file_entry = self.get_file_entry(parent_file_id).await?; + if parent_file_id == ROOT_DIR_FILE_ID && name == OsStr::new(FS_META_FILE_NAME) { + return Ok(self.meta_file_stat()); + } + let parent_file_entry = self.get_file_entry(parent_file_id).await?; let path = parent_file_entry.path.join(name); let mut file_stat = self.fs.stat(&path).await?; // fill the file id to file stat @@ -193,10 +224,21 @@ impl RawFileSystem for DefaultRawFileSystem { for file_stat in child_filestats.iter_mut() { self.resolve_file_id_to_filestat(file_stat, file_id).await; } + + if file_id == ROOT_DIR_FILE_ID { + child_filestats.push(self.meta_file_stat()); + } Ok(child_filestats) } async fn open_file(&self, file_id: u64, flags: u32) -> Result { + if file_id == FS_META_FILE_ID { + let meta_file = OpenedFile::new(self.meta_file_stat()); + let resutl = self.opened_file_manager.put(meta_file); + let file = resutl.lock().await; + return Ok(file.file_handle()); + } + self.open_file_internal(file_id, flags, FileType::RegularFile) .await } @@ -212,6 +254,10 @@ impl RawFileSystem for DefaultRawFileSystem { name: &OsStr, flags: u32, ) -> Result { + if parent_file_id == ROOT_DIR_FILE_ID && name == OsStr::new(FS_META_FILE_NAME) { + return Err(Errno::from(libc::EEXIST)); + } + let parent_file_entry = self.get_file_entry(parent_file_id).await?; let mut file_without_id = self .fs @@ -248,11 +294,19 @@ impl RawFileSystem for DefaultRawFileSystem { } async fn set_attr(&self, file_id: u64, file_stat: &FileStat) -> Result<()> { + if file_id == ROOT_DIR_FILE_ID || file_id == FS_META_FILE_ID { + return Ok(()); + } + let file_entry = self.get_file_entry(file_id).await?; self.fs.set_attr(&file_entry.path, file_stat, true).await } async fn remove_file(&self, parent_file_id: u64, name: &OsStr) -> Result<()> { + if parent_file_id == ROOT_DIR_FILE_ID && name == OsStr::new(FS_META_FILE_NAME) { + return Err(Errno::from(libc::EPERM)); + } + let parent_file_entry = self.get_file_entry(parent_file_id).await?; let path = parent_file_entry.path.join(name); self.fs.remove_file(&path).await?; @@ -281,7 +335,11 @@ impl RawFileSystem for DefaultRawFileSystem { file.close().await } - async fn read(&self, _file_id: u64, fh: u64, offset: u64, size: u32) -> Result { + async fn read(&self, file_id: u64, fh: u64, offset: u64, size: u32) -> Result { + if file_id == FS_META_FILE_ID { + return Ok(Bytes::new()); + } + let (data, file_stat) = { let opened_file = self .opened_file_manager @@ -298,7 +356,11 @@ impl RawFileSystem for DefaultRawFileSystem { data } - async fn write(&self, _file_id: u64, fh: u64, offset: u64, data: &[u8]) -> Result { + async fn write(&self, file_id: u64, fh: u64, offset: u64, data: &[u8]) -> Result { + if file_id == FS_META_FILE_ID { + return Err(Errno::from(libc::EPERM)); + } + let (len, file_stat) = { let opened_file = self .opened_file_manager diff --git a/clients/filesystem-fuse/src/filesystem.rs b/clients/filesystem-fuse/src/filesystem.rs index 742cdd4c879..21c1a05aeae 100644 --- a/clients/filesystem-fuse/src/filesystem.rs +++ b/clients/filesystem-fuse/src/filesystem.rs @@ -35,6 +35,9 @@ pub(crate) const ROOT_DIR_FILE_ID: u64 = 1; pub(crate) const ROOT_DIR_NAME: &str = ""; pub(crate) const ROOT_DIR_PATH: &str = "/"; pub(crate) const INITIAL_FILE_ID: u64 = 10000; +pub(crate) const FS_META_FILE_PATH: &str = "/.gvfs_meta"; +pub(crate) const FS_META_FILE_NAME: &str = ".gvfs_meta"; +pub(crate) const FS_META_FILE_ID: u64 = 10; /// RawFileSystem interface for the file system implementation. it use by FuseApiHandle, /// it ues the file id to operate the file system apis @@ -305,13 +308,6 @@ pub(crate) mod tests { } pub(crate) async fn test_path_file_system(&mut self) { - // Test root dir - self.test_root_dir().await; - - // Test stat file - self.test_stat_file(Path::new("/.gvfs_meta"), RegularFile, 0) - .await; - // Test create file self.test_create_file(Path::new("/file1.txt")).await; @@ -334,14 +330,6 @@ pub(crate) mod tests { self.test_list_dir(Path::new("/")).await; } - async fn test_root_dir(&mut self) { - let root_dir_path = Path::new("/"); - let root_file_stat = self.fs.stat(root_dir_path).await; - assert!(root_file_stat.is_ok()); - let root_file_stat = root_file_stat.unwrap(); - self.assert_file_stat(&root_file_stat, root_dir_path, Directory, 0); - } - async fn test_stat_file(&mut self, path: &Path, expect_kind: FileType, expect_size: u64) { let file_stat = self.fs.stat(path).await; assert!(file_stat.is_ok()); @@ -652,7 +640,7 @@ pub(crate) mod tests { assert_eq!(file_stat.path, path); assert_eq!(file_stat.kind, kind); assert_eq!(file_stat.size, size); - if file_stat.file_id == 1 { + if file_stat.file_id == ROOT_DIR_FILE_ID || file_stat.file_id == FS_META_FILE_ID { assert_eq!(file_stat.parent_file_id, 1); } else { assert!(file_stat.file_id >= INITIAL_FILE_ID); diff --git a/clients/filesystem-fuse/src/memory_filesystem.rs b/clients/filesystem-fuse/src/memory_filesystem.rs index b94d16b8d39..1967e09fd4c 100644 --- a/clients/filesystem-fuse/src/memory_filesystem.rs +++ b/clients/filesystem-fuse/src/memory_filesystem.rs @@ -42,8 +42,6 @@ pub struct MemoryFileSystem { } impl MemoryFileSystem { - const FS_META_FILE_NAME: &'static str = "/.gvfs_meta"; - pub(crate) async fn new() -> Self { Self { file_map: RwLock::new(Default::default()), @@ -63,22 +61,6 @@ impl MemoryFileSystem { #[async_trait] impl PathFileSystem for MemoryFileSystem { async fn init(&self) -> Result<()> { - let root_file = MemoryFile { - kind: Directory, - data: Arc::new(Mutex::new(Vec::new())), - }; - let root_path = PathBuf::from("/"); - self.file_map.write().unwrap().insert(root_path, root_file); - - let meta_file = MemoryFile { - kind: RegularFile, - data: Arc::new(Mutex::new(Vec::new())), - }; - let meta_file_path = Path::new(Self::FS_META_FILE_NAME).to_path_buf(); - self.file_map - .write() - .unwrap() - .insert(meta_file_path, meta_file); Ok(()) }