System Extension注册完成 + FSKit Driver待办事项
已完成: ✅ App ID(6770506571) ✅ Bundle ID(com.momentry.markbase.fskit) ✅ Developer ID Application证书导入 ✅ .app Bundle创建(build/MarkBaseFSKit.app) ✅ entitlements.plist配置 限制: - binary未实现FSKit driver(占位符) - 无法通过systemextensionsctl install安装 - 需要完整FSKit接口实现 策略: - 短期:WebDAV(500 MB/s) - 长期:FSKit Driver完整实现(650 MB/s) 文档: - SYSTEM_EXTENSION_MANUAL_INSTALL.md - FSKIT_DRIVER_TODO.md(未来待办)
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
use clap::Parser;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use axum::{Extension, Router, routing::any};
|
||||
use tokio::net::TcpListener;
|
||||
use dav_server::{DavHandler, localfs::LocalFs, fakels::FakeLs};
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
#[arg(short, long, default_value = "4932")]
|
||||
port: u16,
|
||||
|
||||
#[arg(long, default_value = "data/raid_simple.sparseimage")]
|
||||
vdisk_path: PathBuf,
|
||||
|
||||
#[arg(long, default_value = "RAID_AUTO")]
|
||||
mount_name: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async_main());
|
||||
}
|
||||
|
||||
async fn async_main() {
|
||||
let args = Args::parse();
|
||||
|
||||
println!("=== RAID WebDAV Server (Auto-Mount) ===");
|
||||
println!("Port: {}", args.port);
|
||||
println!("VDisk: {}", args.vdisk_path.display());
|
||||
println!("Mount Name: {}", args.mount_name);
|
||||
println!("");
|
||||
|
||||
if !args.vdisk_path.exists() {
|
||||
eprintln!("Error: Virtual disk not found at {}", args.vdisk_path.display());
|
||||
return;
|
||||
}
|
||||
|
||||
println!("Step 1: Check if already mounted...");
|
||||
let mount_point = check_or_mount(&args.vdisk_path, &args.mount_name);
|
||||
|
||||
println!("Step 2: Verify mount point...");
|
||||
if !mount_point.exists() {
|
||||
eprintln!("Error: Mount point does not exist: {}", mount_point.display());
|
||||
return;
|
||||
}
|
||||
|
||||
println!("✅ Mounted at: {}", mount_point.display());
|
||||
println!("");
|
||||
|
||||
println!("Step 3: Starting WebDAV server...");
|
||||
let dav = DavHandler::builder()
|
||||
.filesystem(LocalFs::new(mount_point.to_string_lossy().to_string(), false, false, false))
|
||||
.locksystem(FakeLs::new())
|
||||
.strip_prefix("/webdav")
|
||||
.build_handler();
|
||||
|
||||
let addr = format!("127.0.0.1:{}", args.port);
|
||||
let listener = TcpListener::bind(&addr).await.unwrap();
|
||||
|
||||
let router = Router::new()
|
||||
.route("/webdav", any(handle_dav))
|
||||
.route("/webdav/", any(handle_dav))
|
||||
.route("/webdav/{*path}", any(handle_dav))
|
||||
.layer(Extension(dav));
|
||||
|
||||
println!("Listening on: http://{}", addr);
|
||||
println!("Mount with Finder:");
|
||||
println!(" Cmd+K → http://localhost:{}/webdav", args.port);
|
||||
println!(" Guest/Guest or blank password");
|
||||
println!("");
|
||||
println!("Press Ctrl+C to stop...");
|
||||
|
||||
axum::serve(listener, router).await.unwrap();
|
||||
}
|
||||
|
||||
fn check_or_mount(vdisk_path: &PathBuf, mount_name: &str) -> PathBuf {
|
||||
let expected_mount = PathBuf::from("/Volumes").join(mount_name);
|
||||
|
||||
if expected_mount.exists() {
|
||||
println!("✅ Already mounted at: {}", expected_mount.display());
|
||||
return expected_mount;
|
||||
}
|
||||
|
||||
println!("Mounting sparseimage...");
|
||||
let output = Command::new("hdiutil")
|
||||
.args(&["attach", "-nobrowse"])
|
||||
.arg(vdisk_path)
|
||||
.output()
|
||||
.expect("Failed to mount sparseimage");
|
||||
|
||||
if !output.status.success() {
|
||||
eprintln!("Mount failed: {}", String::from_utf8_lossy(&output.stderr));
|
||||
return expected_mount;
|
||||
}
|
||||
|
||||
println!("Mount output: {}", String::from_utf8_lossy(&output.stdout));
|
||||
|
||||
let mount_output = String::from_utf8_lossy(&output.stdout);
|
||||
for line in mount_output.lines() {
|
||||
if line.contains("/Volumes/") {
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
if let Some(mount_path) = parts.last() {
|
||||
println!("✅ Mounted at: {}", mount_path);
|
||||
return PathBuf::from(mount_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expected_mount
|
||||
}
|
||||
|
||||
async fn handle_dav(Extension(dav): Extension<dav_server::DavHandler>, req: axum::extract::Request) -> impl axum::response::IntoResponse {
|
||||
dav.handle(req).await
|
||||
}
|
||||
Reference in New Issue
Block a user