WebDAV error handling improvements: map_vfs_error helper
Some checks failed
Test / build (push) Has been cancelled
Test / test (push) Has been cancelled

- 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
This commit is contained in:
Warren
2026-06-21 16:50:23 +08:00
parent 43c135e877
commit 0322e2d4b6

View File

@@ -22,6 +22,19 @@ use std::time::SystemTime;
use crate::webdav_locks::PersistedLs; 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 /// Expected credentials for WebDAV Basic Auth validation
#[derive(Clone)] #[derive(Clone)]
pub struct WebdavCredentials { pub struct WebdavCredentials {
@@ -231,6 +244,7 @@ pub struct VfsDavMetaData {
is_dir: bool, is_dir: bool,
modified: SystemTime, modified: SystemTime,
accessed: SystemTime, accessed: SystemTime,
mode: u32,
} }
impl VfsDavMetaData { impl VfsDavMetaData {
@@ -241,6 +255,7 @@ impl VfsDavMetaData {
is_dir, is_dir,
modified: now, modified: now,
accessed: now, accessed: now,
mode: 0o644,
} }
} }
@@ -250,6 +265,7 @@ impl VfsDavMetaData {
is_dir: stat.is_dir, is_dir: stat.is_dir,
modified: stat.mtime, modified: stat.mtime,
accessed: stat.atime, accessed: stat.atime,
mode: stat.mode,
} }
} }
} }
@@ -270,6 +286,10 @@ impl DavMetaData for VfsDavMetaData {
fn accessed(&self) -> Result<SystemTime, FsError> { fn accessed(&self) -> Result<SystemTime, FsError> {
Ok(self.accessed) Ok(self.accessed)
} }
fn executable(&self) -> Result<bool, FsError> {
Ok(!self.is_dir && (self.mode & 0o111 != 0))
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -659,7 +679,7 @@ impl DavFileSystem for VfsDavFs {
} }
match self.vfs.create_dir_all(&full_path, 0o755) { match self.vfs.create_dir_all(&full_path, 0o755) {
Ok(_) => Box::pin(std::future::ready(Ok(()))), 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) { match self.vfs.remove_dir_all(&full_path) {
Ok(_) => Box::pin(std::future::ready(Ok(()))), 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) { match self.vfs.remove_file(&full_path) {
Ok(_) => Box::pin(std::future::ready(Ok(()))), 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(()))) 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) { match self.vfs.set_atime(&resolved, tm) {
Ok(_) => Box::pin(std::future::ready(Ok(()))), 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) { match self.vfs.set_mtime(&resolved, tm) {
Ok(_) => Box::pin(std::future::ready(Ok(()))), 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<u64>)> { fn get_quota(&'_ self) -> FsFuture<'_, (u64, Option<u64>)> {
let used = self.vfs.get_quota_usage(&self.root); let root = self.root.clone();
let total = self.vfs.get_quota(&self.root); let vfs = self.vfs.clone_boxed();
Box::pin(async move { Box::pin(async move {
let used = vfs.get_quota_usage(&root);
let total = vfs.get_quota(&root);
match (used, total) { match (used, total) {
(Ok(usage), Ok(quota)) => { (Ok(usage), Ok(quota)) => {
let limit = if quota.space_limit > 0 { Some(quota.space_limit) } else { None }; let limit = if quota.space_limit > 0 { Some(quota.space_limit) } else { None };
Ok((usage.space_used, limit)) 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),
} }
}) })
} }