From 0322e2d4b6a6ea1d5def1b9a35ff2a528631ee6e Mon Sep 17 00:00:00 2001 From: Warren Date: Sun, 21 Jun 2026 16:50:23 +0800 Subject: [PATCH] WebDAV error handling improvements: map_vfs_error helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add map_vfs_error() to map VfsError to FsError properly - NotFound → NotFound, PermissionDenied → Forbidden, etc. - Update create_dir/remove_dir/remove_file/rename/set_atime/set_mtime/get_quota - Add executable() method to VfsDavMetaData (mode & 0o111) Tests: 288 passed, 0 failed --- markbase-core/src/webdav.rs | 46 +++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/markbase-core/src/webdav.rs b/markbase-core/src/webdav.rs index 7601e52..28927ec 100644 --- a/markbase-core/src/webdav.rs +++ b/markbase-core/src/webdav.rs @@ -22,6 +22,19 @@ use std::time::SystemTime; use crate::webdav_locks::PersistedLs; +fn map_vfs_error(e: VfsError) -> FsError { + match e { + VfsError::NotFound(_) => FsError::NotFound, + VfsError::PermissionDenied(_) => FsError::Forbidden, + VfsError::Unsupported(_) => FsError::NotImplemented, + VfsError::AlreadyExists(_) => FsError::Exists, + VfsError::NotEmpty(_) => FsError::Forbidden, + VfsError::NotADirectory(_) => FsError::Forbidden, + VfsError::IsADirectory(_) => FsError::Forbidden, + VfsError::Io(_) | VfsError::UnexpectedEof => FsError::GeneralFailure, + } +} + /// Expected credentials for WebDAV Basic Auth validation #[derive(Clone)] pub struct WebdavCredentials { @@ -231,6 +244,7 @@ pub struct VfsDavMetaData { is_dir: bool, modified: SystemTime, accessed: SystemTime, + mode: u32, } impl VfsDavMetaData { @@ -241,6 +255,7 @@ impl VfsDavMetaData { is_dir, modified: now, accessed: now, + mode: 0o644, } } @@ -250,6 +265,7 @@ impl VfsDavMetaData { is_dir: stat.is_dir, modified: stat.mtime, accessed: stat.atime, + mode: stat.mode, } } } @@ -270,6 +286,10 @@ impl DavMetaData for VfsDavMetaData { fn accessed(&self) -> Result { Ok(self.accessed) } + + fn executable(&self) -> Result { + Ok(!self.is_dir && (self.mode & 0o111 != 0)) + } } #[derive(Debug, Clone)] @@ -659,7 +679,7 @@ impl DavFileSystem for VfsDavFs { } match self.vfs.create_dir_all(&full_path, 0o755) { Ok(_) => Box::pin(std::future::ready(Ok(()))), - Err(_) => Box::pin(std::future::ready(Err(FsError::NotImplemented))), + Err(e) => Box::pin(std::future::ready(Err(map_vfs_error(e)))), } } @@ -670,7 +690,7 @@ impl DavFileSystem for VfsDavFs { }; match self.vfs.remove_dir_all(&full_path) { Ok(_) => Box::pin(std::future::ready(Ok(()))), - Err(_) => Box::pin(std::future::ready(Err(FsError::NotImplemented))), + Err(e) => Box::pin(std::future::ready(Err(map_vfs_error(e)))), } } @@ -681,7 +701,7 @@ impl DavFileSystem for VfsDavFs { }; match self.vfs.remove_file(&full_path) { Ok(_) => Box::pin(std::future::ready(Ok(()))), - Err(_) => Box::pin(std::future::ready(Err(FsError::NotImplemented))), + Err(e) => Box::pin(std::future::ready(Err(map_vfs_error(e)))), } } @@ -706,7 +726,7 @@ impl DavFileSystem for VfsDavFs { } Box::pin(std::future::ready(Ok(()))) } - Err(_) => Box::pin(std::future::ready(Err(FsError::NotImplemented))), + Err(e) => Box::pin(std::future::ready(Err(map_vfs_error(e)))), } } @@ -717,7 +737,7 @@ impl DavFileSystem for VfsDavFs { }; match self.vfs.set_atime(&resolved, tm) { Ok(_) => Box::pin(std::future::ready(Ok(()))), - Err(_) => Box::pin(std::future::ready(Err(FsError::NotImplemented))), + Err(e) => Box::pin(std::future::ready(Err(map_vfs_error(e)))), } } @@ -728,7 +748,7 @@ impl DavFileSystem for VfsDavFs { }; match self.vfs.set_mtime(&resolved, tm) { Ok(_) => Box::pin(std::future::ready(Ok(()))), - Err(_) => Box::pin(std::future::ready(Err(FsError::NotImplemented))), + Err(e) => Box::pin(std::future::ready(Err(map_vfs_error(e)))), } } @@ -855,15 +875,23 @@ impl DavFileSystem for VfsDavFs { } fn get_quota(&'_ self) -> FsFuture<'_, (u64, Option)> { - let used = self.vfs.get_quota_usage(&self.root); - let total = self.vfs.get_quota(&self.root); + let root = self.root.clone(); + let vfs = self.vfs.clone_boxed(); Box::pin(async move { + let used = vfs.get_quota_usage(&root); + let total = vfs.get_quota(&root); match (used, total) { (Ok(usage), Ok(quota)) => { let limit = if quota.space_limit > 0 { Some(quota.space_limit) } else { None }; Ok((usage.space_used, limit)) } - _ => Err(FsError::NotImplemented), + (Err(VfsError::NotFound(_)), _) | (_, Err(VfsError::NotFound(_))) => { + Err(FsError::NotFound) + } + (Err(VfsError::Unsupported(_)), _) | (_, Err(VfsError::Unsupported(_))) => { + Err(FsError::NotImplemented) + } + _ => Err(FsError::GeneralFailure), } }) }