Fix code quality: trailing whitespace, unused imports, clippy warnings
- Fix trailing whitespace in kex.rs and s3.rs - Add missing KexProposal import in kex_complete.rs - Auto-fix clippy warnings across all crates - All 153 tests pass
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
pub mod nfs;
|
||||
|
||||
pub use nfs::markbase_fs::MarkBaseFS;
|
||||
pub use nfs::backend::MarkBaseNFSBackend;
|
||||
pub use nfs::markbase_fs::MarkBaseFS;
|
||||
|
||||
@@ -9,11 +9,11 @@ struct Cli {
|
||||
/// User ID (database name)
|
||||
#[arg(short, long)]
|
||||
user: String,
|
||||
|
||||
|
||||
/// Database path
|
||||
#[arg(short, long, default_value = "data/users")]
|
||||
data_dir: String,
|
||||
|
||||
|
||||
/// NFS server port
|
||||
#[arg(short, long, default_value_t = 11111)]
|
||||
port: u16,
|
||||
@@ -21,19 +21,19 @@ struct Cli {
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
|
||||
let db_path = PathBuf::from(&cli.data_dir).join(format!("{}.sqlite", cli.user));
|
||||
|
||||
|
||||
if !db_path.exists() {
|
||||
eprintln!("Database not found: {}", db_path.display());
|
||||
eprintln!("Please create database first using markbase-core");
|
||||
return Err(anyhow::anyhow!("Database not found"));
|
||||
}
|
||||
|
||||
|
||||
eprintln!("Starting MarkBase NFS server...");
|
||||
eprintln!("User: {}", cli.user);
|
||||
eprintln!("Database: {}", db_path.display());
|
||||
eprintln!("Port: {}", cli.port);
|
||||
|
||||
|
||||
run_nfs_server(cli.user, db_path, cli.port)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,12 @@ use std::time::SystemTime;
|
||||
use async_trait::async_trait;
|
||||
use nfsserve::nfs::*;
|
||||
use nfsserve::vfs::{DirEntry, NFSFileSystem, ReadDirResult, VFSCapabilities};
|
||||
use rusqlite::Connection;
|
||||
|
||||
use crate::nfs::markbase_fs::MarkBaseFS;
|
||||
|
||||
pub struct MarkBaseNFSBackend {
|
||||
fs: MarkBaseFS,
|
||||
id_map: Mutex<HashMap<u64, String>>, // fileid -> node_id
|
||||
id_map: Mutex<HashMap<u64, String>>, // fileid -> node_id
|
||||
reverse_map: Mutex<HashMap<String, u64>>, // node_id -> fileid
|
||||
next_id: Mutex<u64>,
|
||||
}
|
||||
@@ -19,7 +18,7 @@ pub struct MarkBaseNFSBackend {
|
||||
impl MarkBaseNFSBackend {
|
||||
pub fn new(user_id: String, db_path: std::path::PathBuf) -> anyhow::Result<Self> {
|
||||
let fs = MarkBaseFS::new(user_id, db_path)?;
|
||||
|
||||
|
||||
Ok(MarkBaseNFSBackend {
|
||||
fs,
|
||||
id_map: Mutex::new(HashMap::new()),
|
||||
@@ -27,32 +26,35 @@ impl MarkBaseNFSBackend {
|
||||
next_id: Mutex::new(2), // 1 is root
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fn allocate_id(&self, node_id: &str) -> u64 {
|
||||
let mut reverse_map = self.reverse_map.lock().unwrap();
|
||||
|
||||
|
||||
if let Some(id) = reverse_map.get(node_id) {
|
||||
return *id;
|
||||
}
|
||||
|
||||
|
||||
let mut next_id = self.next_id.lock().unwrap();
|
||||
let id = *next_id;
|
||||
*next_id += 1;
|
||||
|
||||
|
||||
reverse_map.insert(node_id.to_string(), id);
|
||||
self.id_map.lock().unwrap().insert(id, node_id.to_string());
|
||||
|
||||
|
||||
id
|
||||
}
|
||||
|
||||
|
||||
fn get_node_id(&self, fileid: u64) -> Option<String> {
|
||||
self.id_map.lock().unwrap().get(&fileid).cloned()
|
||||
}
|
||||
|
||||
|
||||
fn get_fileid_from_node(&self, node_id: &str) -> u64 {
|
||||
self.reverse_map.lock().unwrap().get(node_id).copied().unwrap_or_else(|| {
|
||||
self.allocate_id(node_id)
|
||||
})
|
||||
self.reverse_map
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(node_id)
|
||||
.copied()
|
||||
.unwrap_or_else(|| self.allocate_id(node_id))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,40 +63,43 @@ impl NFSFileSystem for MarkBaseNFSBackend {
|
||||
fn capabilities(&self) -> VFSCapabilities {
|
||||
VFSCapabilities::ReadOnly
|
||||
}
|
||||
|
||||
|
||||
fn root_dir(&self) -> fileid3 {
|
||||
1
|
||||
}
|
||||
|
||||
|
||||
async fn lookup(&self, dirid: fileid3, filename: &filename3) -> Result<fileid3, nfsstat3> {
|
||||
let dir_node_id = if dirid == 1 {
|
||||
"root".to_string()
|
||||
} else {
|
||||
self.get_node_id(dirid)
|
||||
.ok_or(nfsstat3::NFS3ERR_STALE)?
|
||||
self.get_node_id(dirid).ok_or(nfsstat3::NFS3ERR_STALE)?
|
||||
};
|
||||
|
||||
|
||||
let filename_str = String::from_utf8_lossy(filename).to_string();
|
||||
|
||||
let conn = self.fs.conn.lock().map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
|
||||
let conn = self
|
||||
.fs
|
||||
.conn
|
||||
.lock()
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
let query = if dir_node_id == "root" {
|
||||
"SELECT node_id FROM file_nodes WHERE parent_id IS NULL AND label = ?1"
|
||||
} else {
|
||||
"SELECT node_id FROM file_nodes WHERE parent_id = ?1 AND label = ?2"
|
||||
};
|
||||
|
||||
|
||||
let node_id: String = if dir_node_id == "root" {
|
||||
conn.query_row(&query, [&filename_str], |row| row.get(0))
|
||||
conn.query_row(query, [&filename_str], |row| row.get(0))
|
||||
.map_err(|_| nfsstat3::NFS3ERR_NOENT)?
|
||||
} else {
|
||||
conn.query_row(&query, [dir_node_id, filename_str], |row| row.get(0))
|
||||
conn.query_row(query, [dir_node_id, filename_str], |row| row.get(0))
|
||||
.map_err(|_| nfsstat3::NFS3ERR_NOENT)?
|
||||
};
|
||||
|
||||
|
||||
Ok(self.get_fileid_from_node(&node_id))
|
||||
}
|
||||
|
||||
|
||||
async fn getattr(&self, id: fileid3) -> Result<fattr3, nfsstat3> {
|
||||
if id == 1 {
|
||||
return Ok(fattr3 {
|
||||
@@ -105,38 +110,54 @@ impl NFSFileSystem for MarkBaseNFSBackend {
|
||||
gid: 0,
|
||||
size: 0,
|
||||
used: 0,
|
||||
rdev: specdata3 { specdata1: 0, specdata2: 0 },
|
||||
rdev: specdata3 {
|
||||
specdata1: 0,
|
||||
specdata2: 0,
|
||||
},
|
||||
fsid: 0,
|
||||
fileid: 1,
|
||||
atime: nfstime3 { seconds: 0, nseconds: 0 },
|
||||
mtime: nfstime3 { seconds: 0, nseconds: 0 },
|
||||
ctime: nfstime3 { seconds: 0, nseconds: 0 },
|
||||
atime: nfstime3 {
|
||||
seconds: 0,
|
||||
nseconds: 0,
|
||||
},
|
||||
mtime: nfstime3 {
|
||||
seconds: 0,
|
||||
nseconds: 0,
|
||||
},
|
||||
ctime: nfstime3 {
|
||||
seconds: 0,
|
||||
nseconds: 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
let node_id = self.get_node_id(id).ok_or(nfsstat3::NFS3ERR_STALE)?;
|
||||
|
||||
let conn = self.fs.conn.lock().map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
|
||||
let conn = self
|
||||
.fs
|
||||
.conn
|
||||
.lock()
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
let (node_type, file_size): (String, i64) = conn
|
||||
.query_row(
|
||||
"SELECT node_type, file_size FROM file_nodes WHERE node_id = ?1",
|
||||
[&node_id],
|
||||
|row| Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))
|
||||
|row| Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?)),
|
||||
)
|
||||
.map_err(|_| nfsstat3::NFS3ERR_NOENT)?;
|
||||
|
||||
|
||||
let type_ = if node_type == "folder" {
|
||||
ftype3::NF3DIR
|
||||
} else {
|
||||
ftype3::NF3REG
|
||||
};
|
||||
|
||||
|
||||
let now = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
|
||||
|
||||
Ok(fattr3 {
|
||||
ftype: type_,
|
||||
mode: if node_type == "folder" { 0o755 } else { 0o644 },
|
||||
@@ -145,69 +166,103 @@ impl NFSFileSystem for MarkBaseNFSBackend {
|
||||
gid: 0,
|
||||
size: file_size as u64,
|
||||
used: file_size as u64,
|
||||
rdev: specdata3 { specdata1: 0, specdata2: 0 },
|
||||
rdev: specdata3 {
|
||||
specdata1: 0,
|
||||
specdata2: 0,
|
||||
},
|
||||
fsid: 0,
|
||||
fileid: id,
|
||||
atime: nfstime3 { seconds: now as u32, nseconds: 0 },
|
||||
mtime: nfstime3 { seconds: now as u32, nseconds: 0 },
|
||||
ctime: nfstime3 { seconds: now as u32, nseconds: 0 },
|
||||
atime: nfstime3 {
|
||||
seconds: now as u32,
|
||||
nseconds: 0,
|
||||
},
|
||||
mtime: nfstime3 {
|
||||
seconds: now as u32,
|
||||
nseconds: 0,
|
||||
},
|
||||
ctime: nfstime3 {
|
||||
seconds: now as u32,
|
||||
nseconds: 0,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
async fn setattr(&self, _id: fileid3, _setattr: sattr3) -> Result<fattr3, nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_ROFS)
|
||||
}
|
||||
|
||||
async fn read(&self, id: fileid3, offset: u64, count: u32) -> Result<(Vec<u8>, bool), nfsstat3> {
|
||||
|
||||
async fn read(
|
||||
&self,
|
||||
id: fileid3,
|
||||
offset: u64,
|
||||
count: u32,
|
||||
) -> Result<(Vec<u8>, bool), nfsstat3> {
|
||||
let node_id = self.get_node_id(id).ok_or(nfsstat3::NFS3ERR_STALE)?;
|
||||
|
||||
let conn = self.fs.conn.lock().map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
|
||||
let conn = self
|
||||
.fs
|
||||
.conn
|
||||
.lock()
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
let aliases_json: String = conn
|
||||
.query_row(
|
||||
"SELECT aliases_json FROM file_nodes WHERE node_id = ?1",
|
||||
[&node_id],
|
||||
|row| row.get(0)
|
||||
|row| row.get(0),
|
||||
)
|
||||
.map_err(|_| nfsstat3::NFS3ERR_NOENT)?;
|
||||
|
||||
let aliases: serde_json::Value = serde_json::from_str(&aliases_json)
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
|
||||
let aliases: serde_json::Value =
|
||||
serde_json::from_str(&aliases_json).map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
let file_path = aliases["path"].as_str().ok_or(nfsstat3::NFS3ERR_NOENT)?;
|
||||
|
||||
|
||||
let file_data = std::fs::read(file_path).map_err(|_| nfsstat3::NFS3ERR_IO)?;
|
||||
|
||||
|
||||
let file_size = file_data.len() as u64;
|
||||
let start = offset.min(file_size) as usize;
|
||||
let end = (offset + count as u64).min(file_size) as usize;
|
||||
|
||||
|
||||
let data = file_data[start..end].to_vec();
|
||||
let eof = end >= file_size as usize;
|
||||
|
||||
|
||||
Ok((data, eof))
|
||||
}
|
||||
|
||||
|
||||
async fn write(&self, _id: fileid3, _offset: u64, _data: &[u8]) -> Result<fattr3, nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_ROFS)
|
||||
}
|
||||
|
||||
async fn create(&self, _dirid: fileid3, _filename: &filename3, _attr: sattr3) -> Result<(fileid3, fattr3), nfsstat3> {
|
||||
|
||||
async fn create(
|
||||
&self,
|
||||
_dirid: fileid3,
|
||||
_filename: &filename3,
|
||||
_attr: sattr3,
|
||||
) -> Result<(fileid3, fattr3), nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_ROFS)
|
||||
}
|
||||
|
||||
async fn create_exclusive(&self, _dirid: fileid3, _filename: &filename3) -> Result<fileid3, nfsstat3> {
|
||||
|
||||
async fn create_exclusive(
|
||||
&self,
|
||||
_dirid: fileid3,
|
||||
_filename: &filename3,
|
||||
) -> Result<fileid3, nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_ROFS)
|
||||
}
|
||||
|
||||
async fn mkdir(&self, _dirid: fileid3, _dirname: &filename3) -> Result<(fileid3, fattr3), nfsstat3> {
|
||||
|
||||
async fn mkdir(
|
||||
&self,
|
||||
_dirid: fileid3,
|
||||
_dirname: &filename3,
|
||||
) -> Result<(fileid3, fattr3), nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_ROFS)
|
||||
}
|
||||
|
||||
|
||||
async fn remove(&self, _dirid: fileid3, _filename: &filename3) -> Result<(), nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_ROFS)
|
||||
}
|
||||
|
||||
|
||||
async fn rename(
|
||||
&self,
|
||||
_from_dirid: fileid3,
|
||||
@@ -217,7 +272,7 @@ impl NFSFileSystem for MarkBaseNFSBackend {
|
||||
) -> Result<(), nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_ROFS)
|
||||
}
|
||||
|
||||
|
||||
async fn readdir(
|
||||
&self,
|
||||
dirid: fileid3,
|
||||
@@ -227,71 +282,69 @@ impl NFSFileSystem for MarkBaseNFSBackend {
|
||||
let dir_node_id = if dirid == 1 {
|
||||
"root".to_string()
|
||||
} else {
|
||||
self.get_node_id(dirid)
|
||||
.ok_or(nfsstat3::NFS3ERR_STALE)?
|
||||
self.get_node_id(dirid).ok_or(nfsstat3::NFS3ERR_STALE)?
|
||||
};
|
||||
|
||||
let conn = self.fs.conn.lock().map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
|
||||
let conn = self
|
||||
.fs
|
||||
.conn
|
||||
.lock()
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
let query = if dir_node_id == "root" {
|
||||
"SELECT node_id, label, node_type, file_size FROM file_nodes WHERE parent_id IS NULL"
|
||||
} else {
|
||||
"SELECT node_id, label, node_type, file_size FROM file_nodes WHERE parent_id = ?1"
|
||||
};
|
||||
|
||||
let mut stmt = conn.prepare(&query).map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
|
||||
let mut stmt = conn
|
||||
.prepare(query)
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?;
|
||||
|
||||
let rows: Vec<(String, String, String, Option<i64>)> = if dir_node_id == "root" {
|
||||
stmt.query_map([], |row| {
|
||||
row.get::<_, String>(0)
|
||||
.and_then(|node_id| {
|
||||
row.get::<_, String>(1)
|
||||
.and_then(|label| {
|
||||
row.get::<_, String>(2)
|
||||
.and_then(|node_type| {
|
||||
row.get::<_, Option<i64>>(3)
|
||||
.map(|file_size| (node_id, label, node_type, file_size))
|
||||
})
|
||||
})
|
||||
row.get::<_, String>(0).and_then(|node_id| {
|
||||
row.get::<_, String>(1).and_then(|label| {
|
||||
row.get::<_, String>(2).and_then(|node_type| {
|
||||
row.get::<_, Option<i64>>(3)
|
||||
.map(|file_size| (node_id, label, node_type, file_size))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?
|
||||
} else {
|
||||
stmt.query_map([&dir_node_id.as_str()], |row| {
|
||||
row.get::<_, String>(0)
|
||||
.and_then(|node_id| {
|
||||
row.get::<_, String>(1)
|
||||
.and_then(|label| {
|
||||
row.get::<_, String>(2)
|
||||
.and_then(|node_type| {
|
||||
row.get::<_, Option<i64>>(3)
|
||||
.map(|file_size| (node_id, label, node_type, file_size))
|
||||
})
|
||||
})
|
||||
row.get::<_, String>(0).and_then(|node_id| {
|
||||
row.get::<_, String>(1).and_then(|label| {
|
||||
row.get::<_, String>(2).and_then(|node_type| {
|
||||
row.get::<_, Option<i64>>(3)
|
||||
.map(|file_size| (node_id, label, node_type, file_size))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|_| nfsstat3::NFS3ERR_SERVERFAULT)?
|
||||
};
|
||||
|
||||
|
||||
let mut entries: Vec<DirEntry> = Vec::new();
|
||||
let mut started = start_after == 0;
|
||||
|
||||
|
||||
for row in rows {
|
||||
let (node_id, label, node_type, file_size_opt) = row;
|
||||
let file_size = file_size_opt.unwrap_or(0);
|
||||
let fileid = self.get_fileid_from_node(&node_id);
|
||||
|
||||
if !started {
|
||||
if fileid == start_after {
|
||||
|
||||
if !started
|
||||
&& fileid == start_after {
|
||||
started = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if started && entries.len() < max_entries {
|
||||
let attr = fattr3 {
|
||||
ftype: if node_type == "folder" {
|
||||
@@ -305,14 +358,26 @@ impl NFSFileSystem for MarkBaseNFSBackend {
|
||||
gid: 0,
|
||||
size: file_size as u64,
|
||||
used: file_size as u64,
|
||||
rdev: specdata3 { specdata1: 0, specdata2: 0 },
|
||||
rdev: specdata3 {
|
||||
specdata1: 0,
|
||||
specdata2: 0,
|
||||
},
|
||||
fsid: 0,
|
||||
fileid,
|
||||
atime: nfstime3 { seconds: 0, nseconds: 0 },
|
||||
mtime: nfstime3 { seconds: 0, nseconds: 0 },
|
||||
ctime: nfstime3 { seconds: 0, nseconds: 0 },
|
||||
atime: nfstime3 {
|
||||
seconds: 0,
|
||||
nseconds: 0,
|
||||
},
|
||||
mtime: nfstime3 {
|
||||
seconds: 0,
|
||||
nseconds: 0,
|
||||
},
|
||||
ctime: nfstime3 {
|
||||
seconds: 0,
|
||||
nseconds: 0,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
entries.push(DirEntry {
|
||||
fileid,
|
||||
name: nfsserve::nfs::nfsstring(label.into_bytes()),
|
||||
@@ -320,13 +385,10 @@ impl NFSFileSystem for MarkBaseNFSBackend {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ReadDirResult {
|
||||
entries,
|
||||
end: true,
|
||||
})
|
||||
|
||||
Ok(ReadDirResult { entries, end: true })
|
||||
}
|
||||
|
||||
|
||||
async fn symlink(
|
||||
&self,
|
||||
_dirid: fileid3,
|
||||
@@ -336,8 +398,8 @@ impl NFSFileSystem for MarkBaseNFSBackend {
|
||||
) -> Result<(fileid3, fattr3), nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_ROFS)
|
||||
}
|
||||
|
||||
|
||||
async fn readlink(&self, _id: fileid3) -> Result<nfspath3, nfsstat3> {
|
||||
Err(nfsstat3::NFS3ERR_NOTSUPP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use vfs::error::VfsErrorKind;
|
||||
use vfs::{FileSystem, SeekAndRead, SeekAndWrite, VfsFileType, VfsMetadata, VfsResult};
|
||||
|
||||
fn rusqlite_to_io_error(e: rusqlite::Error) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, e.to_string())
|
||||
io::Error::other(e.to_string())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -42,7 +42,7 @@ impl MarkBaseFS {
|
||||
}
|
||||
|
||||
fn resolve_path(&self, path: &str) -> VfsResult<FileNode> {
|
||||
if path == "" || path == "/" {
|
||||
if path.is_empty() || path == "/" {
|
||||
return Ok(FileNode {
|
||||
node_id: "root".to_string(),
|
||||
label: "".to_string(),
|
||||
@@ -89,7 +89,7 @@ impl MarkBaseFS {
|
||||
file_size: row.get(5)?,
|
||||
})
|
||||
})
|
||||
.map_err(|e| rusqlite_to_io_error(e))
|
||||
.map_err(rusqlite_to_io_error)
|
||||
} else {
|
||||
let part_str = part.to_string();
|
||||
stmt.query_row([current_parent.clone().unwrap(), part_str], |row| {
|
||||
@@ -102,7 +102,7 @@ impl MarkBaseFS {
|
||||
file_size: row.get(5)?,
|
||||
})
|
||||
})
|
||||
.map_err(|e| rusqlite_to_io_error(e))
|
||||
.map_err(rusqlite_to_io_error)
|
||||
};
|
||||
|
||||
match node {
|
||||
@@ -125,7 +125,7 @@ impl FileSystem for MarkBaseFS {
|
||||
.lock()
|
||||
.map_err(|_| VfsErrorKind::Other("Failed to lock connection".to_string()))?;
|
||||
|
||||
let parent_id = if path == "" || path == "/" {
|
||||
let parent_id = if path.is_empty() || path == "/" {
|
||||
None
|
||||
} else {
|
||||
let node = self.resolve_path(path)?;
|
||||
@@ -144,14 +144,14 @@ impl FileSystem for MarkBaseFS {
|
||||
|
||||
let children: Vec<String> = if parent_id.is_none() {
|
||||
stmt.query_map([], |row| row.get::<_, String>(0))
|
||||
.map_err(|e| rusqlite_to_io_error(e))?
|
||||
.map_err(rusqlite_to_io_error)?
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| rusqlite_to_io_error(e))?
|
||||
.map_err(rusqlite_to_io_error)?
|
||||
} else {
|
||||
stmt.query_map([parent_id.unwrap()], |row| row.get::<_, String>(0))
|
||||
.map_err(|e| rusqlite_to_io_error(e))?
|
||||
.map_err(rusqlite_to_io_error)?
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| rusqlite_to_io_error(e))?
|
||||
.map_err(rusqlite_to_io_error)?
|
||||
};
|
||||
|
||||
Ok(Box::new(children.into_iter()))
|
||||
@@ -170,7 +170,7 @@ impl FileSystem for MarkBaseFS {
|
||||
|
||||
let aliases_json = node.aliases_json.ok_or(VfsErrorKind::FileNotFound)?;
|
||||
let aliases: serde_json::Value = serde_json::from_str(&aliases_json).map_err(|e| {
|
||||
VfsErrorKind::IoError(io::Error::new(io::ErrorKind::Other, e.to_string()))
|
||||
VfsErrorKind::IoError(io::Error::other(e.to_string()))
|
||||
})?;
|
||||
|
||||
let file_path = aliases["path"].as_str().ok_or(VfsErrorKind::FileNotFound)?;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pub mod markbase_fs;
|
||||
pub mod backend;
|
||||
pub mod markbase_fs;
|
||||
pub mod server;
|
||||
|
||||
pub use markbase_fs::MarkBaseFS;
|
||||
pub use backend::MarkBaseNFSBackend;
|
||||
pub use server::{start_nfs_server, run_nfs_server};
|
||||
pub use markbase_fs::MarkBaseFS;
|
||||
pub use server::{run_nfs_server, start_nfs_server};
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use nfsserve::tcp::{NFSTcpListener, NFSTcp};
|
||||
use nfsserve::tcp::{NFSTcp, NFSTcpListener};
|
||||
use tokio::signal;
|
||||
|
||||
use crate::nfs::backend::MarkBaseNFSBackend;
|
||||
|
||||
pub async fn start_nfs_server(user_id: String, db_path: PathBuf, port: u16) -> anyhow::Result<()> {
|
||||
let backend = MarkBaseNFSBackend::new(user_id, db_path)?;
|
||||
|
||||
|
||||
let bind_addr = format!("127.0.0.1:{}", port);
|
||||
|
||||
|
||||
let mut listener = NFSTcpListener::bind(&bind_addr, backend)
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("Failed to bind NFS server: {}", e))?;
|
||||
|
||||
|
||||
listener.with_export_name("markbase");
|
||||
|
||||
|
||||
let listen_port = listener.get_listen_port();
|
||||
eprintln!("[NFS] MarkBase NFS server started on port {}", listen_port);
|
||||
eprintln!("[NFS] Mount command (Mac):");
|
||||
@@ -25,7 +24,7 @@ pub async fn start_nfs_server(user_id: String, db_path: PathBuf, port: u16) -> a
|
||||
eprintln!("[NFS] Mount command (Linux):");
|
||||
eprintln!("[NFS] mkdir /tmp/markbase_mount");
|
||||
eprintln!("[NFS] mount.nfs -o user,noacl,nolock,vers=3,tcp,port={},mountport={} localhost:/markbase /tmp/markbase_mount", listen_port, listen_port);
|
||||
|
||||
|
||||
tokio::select! {
|
||||
_ = listener.handle_forever() => {
|
||||
eprintln!("[NFS] Server stopped");
|
||||
@@ -34,11 +33,10 @@ pub async fn start_nfs_server(user_id: String, db_path: PathBuf, port: u16) -> a
|
||||
eprintln!("[NFS] Received Ctrl+C, shutting down...");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_nfs_server(user_id: String, db_path: PathBuf, port: u16) -> anyhow::Result<()> {
|
||||
tokio::runtime::Runtime::new()?
|
||||
.block_on(start_nfs_server(user_id, db_path, port))
|
||||
}
|
||||
tokio::runtime::Runtime::new()?.block_on(start_nfs_server(user_id, db_path, port))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user