Add SMB AAPL Extensions Phase 1-6 + VFS xattr support

Phase 1: AAPL Create Context negotiation
Phase 2: AFP_AfpInfo Stream structure (Finder info + creation time)
Phase 2.5: SMB Named Stream Backend (NamedStreamPath)
Phase 2.6: Backend Named Stream Support in handlers
Phase 2.7: VFS Extended Attributes (get/set/remove/list_xattr)
Phase 4: Time Machine share config (time_machine field)
Phase 5: Server/Volume Capabilities
Phase 6: macOS Unicode mapping (private range ↔ ASCII)

Tests: 174 smb-server tests pass, 52 VFS tests pass
This commit is contained in:
Warren
2026-06-22 14:21:53 +08:00
parent 64709ec529
commit 866d0536c8
14 changed files with 906 additions and 5 deletions

View File

@@ -74,6 +74,7 @@ ureq = "2.12" # 輕量同步 HTTP 客戶端
reqwest = { version = "0.12", optional = true } # Async HTTP client for AsyncS3Vfs
rayon = "1.10" # Phase 4: 并行加密
url = "2" # URL 解析rusty-s3 依賴)
xattr = "1.0" # Extended attributes support (AFP_AfpInfo, Time Machine)
# === SMB/CIFS Client (Phase 1) ===
smb2 = { path = "../vendor/smb2" } # Pure-Rust SMB2/3 client library with pipelined I/O

View File

@@ -5,6 +5,7 @@ pub mod audit;
pub mod auth;
pub mod category_view;
pub mod cli;
pub mod ctdb;
pub mod command;
pub mod config;
pub mod download;

View File

@@ -582,6 +582,65 @@ impl VfsBackend for LocalFs {
acl.aces.remove(ace_index);
self.set_acl(path, &acl)
}
// ===== Extended Attributes (xattr) support =====
fn get_xattr(&self, path: &Path, name: &str) -> Result<Vec<u8>, VfsError> {
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt;
let _meta = path.metadata().map_err(|e| util::map_io_error(path, e))?;
xattr::get(path, name)
.map_err(|e| VfsError::Io(e.to_string()))?
.map(|v| v.to_vec())
.ok_or_else(|| VfsError::NotFound(format!("xattr {} not found", name)))
}
#[cfg(not(unix))]
{
Err(VfsError::Unsupported("get_xattr on non-Unix".to_string()))
}
}
fn set_xattr(&self, path: &Path, name: &str, value: &[u8]) -> Result<(), VfsError> {
#[cfg(unix)]
{
xattr::set(path, name, value)
.map_err(|e| VfsError::Io(e.to_string()))
}
#[cfg(not(unix))]
{
Err(VfsError::Unsupported("set_xattr on non-Unix".to_string()))
}
}
fn remove_xattr(&self, path: &Path, name: &str) -> Result<(), VfsError> {
#[cfg(unix)]
{
xattr::remove(path, name)
.map_err(|e| VfsError::Io(e.to_string()))
}
#[cfg(not(unix))]
{
Err(VfsError::Unsupported("remove_xattr on non-Unix".to_string()))
}
}
fn list_xattrs(&self, path: &Path) -> Result<Vec<String>, VfsError> {
#[cfg(unix)]
{
xattr::list(path)
.map_err(|e| VfsError::Io(e.to_string()))?
.map(|s| s.to_string_lossy().into_owned())
.collect::<Vec<_>>()
.into_iter()
.map(Result::Ok)
.collect()
}
#[cfg(not(unix))]
{
Err(VfsError::Unsupported("list_xattrs on non-Unix".to_string()))
}
}
}
impl LocalFs {

View File

@@ -327,6 +327,28 @@ pub trait VfsBackend: Send + Sync {
fn remove_ace(&self, _path: &Path, _ace_index: usize) -> Result<(), VfsError> {
Err(VfsError::Unsupported("remove_ace".to_string()))
}
// ===== Extended Attributes (xattr) support =====
/// 获取扩展属性
fn get_xattr(&self, _path: &Path, _name: &str) -> Result<Vec<u8>, VfsError> {
Err(VfsError::Unsupported("get_xattr".to_string()))
}
/// 设置扩展属性
fn set_xattr(&self, _path: &Path, _name: &str, _value: &[u8]) -> Result<(), VfsError> {
Err(VfsError::Unsupported("set_xattr".to_string()))
}
/// 删除扩展属性
fn remove_xattr(&self, _path: &Path, _name: &str) -> Result<(), VfsError> {
Err(VfsError::Unsupported("remove_xattr".to_string()))
}
/// 列出扩展属性名称
fn list_xattrs(&self, _path: &Path) -> Result<Vec<String>, VfsError> {
Err(VfsError::Unsupported("list_xattrs".to_string()))
}
}
/// 快照信息