替换为fuser_mt 使用high——level的接口进行实现。
处理好了同步和异步的code
This commit is contained in:
@ -8,7 +8,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
match lws_ins.hello().await{
|
||||
match lws_ins.hello(){
|
||||
Err(e) => {
|
||||
println!("lws client instance hello err {:?}", e);
|
||||
return Err(e);
|
||||
|
396
src/lib.rs
396
src/lib.rs
@ -1,16 +1,14 @@
|
||||
use lws_client::HelloRequest;
|
||||
use lws_client::{Getattr, HelloRequest, FileInfo};
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::RefCell;
|
||||
use std::{io::Read as _};
|
||||
use std::fs::File;
|
||||
use std::error::Error;
|
||||
use std::collections::HashMap;
|
||||
use serde_json::{self, Value};
|
||||
use lws_client::lws_vfs_client::LwsVfsClient;
|
||||
use std::os::raw::c_int;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
||||
use fuser::{
|
||||
KernelConfig, FileAttr, FileType, Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry,
|
||||
Request,
|
||||
};
|
||||
|
||||
pub mod lws_client {
|
||||
tonic::include_proto!("lws_vfs"); //导入lws vfs proto buffer
|
||||
@ -66,43 +64,399 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
struct vir_fs {
|
||||
name: String,
|
||||
}
|
||||
|
||||
pub struct LwsVfsIns {
|
||||
pub config: Config,
|
||||
rpc: LwsVfsClient<tonic::transport::Channel>
|
||||
rpc: RefCell<LwsVfsClient<tonic::transport::Channel>>,
|
||||
async_rt: tokio::runtime::Runtime,
|
||||
}
|
||||
|
||||
impl Filesystem for LwsVfsIns {
|
||||
fn init(&mut self, _req: &Request, #[allow(unused_variables)] config: &mut KernelConfig,
|
||||
) -> Result<(), c_int> {
|
||||
|
||||
Ok(())
|
||||
use fuse_mt::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::{Duration, SystemTime};
|
||||
impl FilesystemMT for LwsVfsIns {
|
||||
/// Called on mount, before any other function.
|
||||
fn init(&self, _req: RequestInfo) -> ResultEmpty {
|
||||
match self.hello() {
|
||||
Ok(()) => {
|
||||
Ok(())
|
||||
},
|
||||
Err(e) =>{
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Called on filesystem unmount.
|
||||
fn destroy(&self) {
|
||||
// Nothing.
|
||||
}
|
||||
|
||||
/// Get the attributes of a filesystem entry.
|
||||
///
|
||||
/// * `fh`: a file handle if this is called on an open file.
|
||||
fn getattr(&self, _req: RequestInfo, path: &Path, _fh: Option<u64>) -> ResultEntry {
|
||||
let request = tonic::Request::new(Getattr {
|
||||
path : path.to_str().unwrap().into(),
|
||||
fi : FileInfo {
|
||||
|
||||
},
|
||||
..Getattr::default()
|
||||
});
|
||||
let response = self.async_rt.block_on(self.rpc.borrow_mut().fgetattr(request));
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
// The following operations in the FUSE C API are all one kernel call: setattr
|
||||
// We split them out to match the C API's behavior.
|
||||
|
||||
/// Change the mode of a filesystem entry.
|
||||
///
|
||||
/// * `fh`: a file handle if this is called on an open file.
|
||||
/// * `mode`: the mode to change the file to.
|
||||
fn chmod(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _mode: u32) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Change the owner UID and/or group GID of a filesystem entry.
|
||||
///
|
||||
/// * `fh`: a file handle if this is called on an open file.
|
||||
/// * `uid`: user ID to change the file's owner to. If `None`, leave the UID unchanged.
|
||||
/// * `gid`: group ID to change the file's group to. If `None`, leave the GID unchanged.
|
||||
fn chown(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _uid: Option<u32>, _gid: Option<u32>) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Set the length of a file.
|
||||
///
|
||||
/// * `fh`: a file handle if this is called on an open file.
|
||||
/// * `size`: size in bytes to set as the file's length.
|
||||
fn truncate(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _size: u64) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Set timestamps of a filesystem entry.
|
||||
///
|
||||
/// * `fh`: a file handle if this is called on an open file.
|
||||
/// * `atime`: the time of last access.
|
||||
/// * `mtime`: the time of last modification.
|
||||
fn utimens(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _atime: Option<SystemTime>, _mtime: Option<SystemTime>) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Set timestamps of a filesystem entry (with extra options only used on MacOS).
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn utimens_macos(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _crtime: Option<SystemTime>, _chgtime: Option<SystemTime>, _bkuptime: Option<SystemTime>, _flags: Option<u32>) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
// END OF SETATTR FUNCTIONS
|
||||
|
||||
/// Read a symbolic link.
|
||||
fn readlink(&self, _req: RequestInfo, _path: &Path) -> ResultData {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Create a special file.
|
||||
///
|
||||
/// * `parent`: path to the directory to make the entry under.
|
||||
/// * `name`: name of the entry.
|
||||
/// * `mode`: mode for the new entry.
|
||||
/// * `rdev`: if mode has the bits `S_IFCHR` or `S_IFBLK` set, this is the major and minor numbers for the device file. Otherwise it should be ignored.
|
||||
fn mknod(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _rdev: u32) -> ResultEntry {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Create a directory.
|
||||
///
|
||||
/// * `parent`: path to the directory to make the directory under.
|
||||
/// * `name`: name of the directory.
|
||||
/// * `mode`: permissions for the new directory.
|
||||
fn mkdir(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32) -> ResultEntry {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Remove a file.
|
||||
///
|
||||
/// * `parent`: path to the directory containing the file to delete.
|
||||
/// * `name`: name of the file to delete.
|
||||
fn unlink(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Remove a directory.
|
||||
///
|
||||
/// * `parent`: path to the directory containing the directory to delete.
|
||||
/// * `name`: name of the directory to delete.
|
||||
fn rmdir(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Create a symbolic link.
|
||||
///
|
||||
/// * `parent`: path to the directory to make the link in.
|
||||
/// * `name`: name of the symbolic link.
|
||||
/// * `target`: path (may be relative or absolute) to the target of the link.
|
||||
fn symlink(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _target: &Path) -> ResultEntry {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Rename a filesystem entry.
|
||||
///
|
||||
/// * `parent`: path to the directory containing the existing entry.
|
||||
/// * `name`: name of the existing entry.
|
||||
/// * `newparent`: path to the directory it should be renamed into (may be the same as `parent`).
|
||||
/// * `newname`: name of the new entry.
|
||||
fn rename(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _newparent: &Path, _newname: &OsStr) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Create a hard link.
|
||||
///
|
||||
/// * `path`: path to an existing file.
|
||||
/// * `newparent`: path to the directory for the new link.
|
||||
/// * `newname`: name for the new link.
|
||||
fn link(&self, _req: RequestInfo, _path: &Path, _newparent: &Path, _newname: &OsStr) -> ResultEntry {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Open a file.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `flags`: one of `O_RDONLY`, `O_WRONLY`, or `O_RDWR`, plus maybe additional flags.
|
||||
///
|
||||
/// Return a tuple of (file handle, flags). The file handle will be passed to any subsequent
|
||||
/// calls that operate on the file, and can be any value you choose, though it should allow
|
||||
/// your filesystem to identify the file opened even without any path info.
|
||||
fn open(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpen {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Read from a file.
|
||||
///
|
||||
/// Note that it is not an error for this call to request to read past the end of the file, and
|
||||
/// you should only return data up to the end of the file (i.e. the number of bytes returned
|
||||
/// will be fewer than requested; possibly even zero). Do not extend the file in this case.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `fh`: file handle returned from the `open` call.
|
||||
/// * `offset`: offset into the file to stasync_rt reading.
|
||||
/// * `size`: number of bytes to read.
|
||||
/// * `callback`: a callback that must be invoked to return the result of the operation: either
|
||||
/// the result data as a slice, or an error code.
|
||||
///
|
||||
/// Return the return value from the `callback` function.
|
||||
fn read(&self, _req: RequestInfo, _path: &Path, _fh: u64, _offset: u64, _size: u32, callback: impl FnOnce(ResultSlice<'_>) -> CallbackResult) -> CallbackResult {
|
||||
callback(Err(libc::ENOSYS))
|
||||
}
|
||||
|
||||
/// Write to a file.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `fh`: file handle returned from the `open` call.
|
||||
/// * `offset`: offset into the file to stasync_rt writing.
|
||||
/// * `data`: the data to write
|
||||
/// * `flags`:
|
||||
///
|
||||
/// Return the number of bytes written.
|
||||
fn write(&self, _req: RequestInfo, _path: &Path, _fh: u64, _offset: u64, _data: Vec<u8>, _flags: u32) -> ResultWrite {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Called each time a program calls `close` on an open file.
|
||||
///
|
||||
/// Note that because file descriptors can be duplicated (by `dup`, `dup2`, `fork`) this may be
|
||||
/// called multiple times for a given file handle. The main use of this function is if the
|
||||
/// filesystem would like to return an error to the `close` call. Note that most programs
|
||||
/// ignore the return value of `close`, though.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `fh`: file handle returned from the `open` call.
|
||||
/// * `lock_owner`: if the filesystem supports locking (`setlk`, `getlk`), remove all locks
|
||||
/// belonging to this lock owner.
|
||||
fn flush(&self, _req: RequestInfo, _path: &Path, _fh: u64, _lock_owner: u64) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Called when an open file is closed.
|
||||
///
|
||||
/// There will be one of these for each `open` call. After `release`, no more calls will be
|
||||
/// made with the given file handle.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `fh`: file handle returned from the `open` call.
|
||||
/// * `flags`: the flags passed when the file was opened.
|
||||
/// * `lock_owner`: if the filesystem supports locking (`setlk`, `getlk`), remove all locks
|
||||
/// belonging to this lock owner.
|
||||
/// * `flush`: whether pending data must be flushed or not.
|
||||
fn release(&self, _req: RequestInfo, _path: &Path, _fh: u64, _flags: u32, _lock_owner: u64, _flush: bool) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Write out any pending changes of a file.
|
||||
///
|
||||
/// When this returns, data should be written to persistent storage.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `fh`: file handle returned from the `open` call.
|
||||
/// * `datasync`: if `false`, also write metadata, otherwise just write file data.
|
||||
fn fsync(&self, _req: RequestInfo, _path: &Path, _fh: u64, _datasync: bool) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Open a directory.
|
||||
///
|
||||
/// Analogous to the `opend` call.
|
||||
///
|
||||
/// * `path`: path to the directory.
|
||||
/// * `flags`: file access flags. Will contain `O_DIRECTORY` at least.
|
||||
///
|
||||
/// Return a tuple of (file handle, flags). The file handle will be passed to any subsequent
|
||||
/// calls that operate on the directory, and can be any value you choose, though it should
|
||||
/// allow your filesystem to identify the directory opened even without any path info.
|
||||
fn opendir(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpen {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Get the entries of a directory.
|
||||
///
|
||||
/// * `path`: path to the directory.
|
||||
/// * `fh`: file handle returned from the `opendir` call.
|
||||
///
|
||||
/// Return all the entries of the directory.
|
||||
fn readdir(&self, _req: RequestInfo, _path: &Path, _fh: u64) -> ResultReaddir {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Close an open directory.
|
||||
///
|
||||
/// This will be called exactly once for each `opendir` call.
|
||||
///
|
||||
/// * `path`: path to the directory.
|
||||
/// * `fh`: file handle returned from the `opendir` call.
|
||||
/// * `flags`: the file access flags passed to the `opendir` call.
|
||||
fn releasedir(&self, _req: RequestInfo, _path: &Path, _fh: u64, _flags: u32) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Write out any pending changes to a directory.
|
||||
///
|
||||
/// Analogous to the `fsync` call.
|
||||
fn fsyncdir(&self, _req: RequestInfo, _path: &Path, _fh: u64, _datasync: bool) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Get filesystem statistics.
|
||||
///
|
||||
/// * `path`: path to some folder in the filesystem.
|
||||
///
|
||||
/// See the `Statfs` struct for more details.
|
||||
fn statfs(&self, _req: RequestInfo, _path: &Path) -> ResultStatfs {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Set a file extended attribute.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `name`: attribute name.
|
||||
/// * `value`: the data to set the value to.
|
||||
/// * `flags`: can be either `XATTR_CREATE` or `XATTR_REPLACE`.
|
||||
/// * `position`: offset into the attribute value to write data.
|
||||
fn setxattr(&self, _req: RequestInfo, _path: &Path, _name: &OsStr, _value: &[u8], _flags: u32, _position: u32) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Get a file extended attribute.
|
||||
///
|
||||
/// * `path`: path to the file
|
||||
/// * `name`: attribute name.
|
||||
/// * `size`: the maximum number of bytes to read.
|
||||
///
|
||||
/// If `size` is 0, return `Xattr::Size(n)` where `n` is the size of the attribute data.
|
||||
/// Otherwise, return `Xattr::Data(data)` with the requested data.
|
||||
fn getxattr(&self, _req: RequestInfo, _path: &Path, _name: &OsStr, _size: u32) -> ResultXattr {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// List extended attributes for a file.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `size`: maximum number of bytes to return.
|
||||
///
|
||||
/// If `size` is 0, return `Xattr::Size(n)` where `n` is the size required for the list of
|
||||
/// attribute names.
|
||||
/// Otherwise, return `Xattr::Data(data)` where `data` is all the null-terminated attribute
|
||||
/// names.
|
||||
fn listxattr(&self, _req: RequestInfo, _path: &Path, _size: u32) -> ResultXattr {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Remove an extended attribute for a file.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `name`: name of the attribute to remove.
|
||||
fn removexattr(&self, _req: RequestInfo, _path: &Path, _name: &OsStr) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Check for access to a file.
|
||||
///
|
||||
/// * `path`: path to the file.
|
||||
/// * `mask`: mode bits to check for access to.
|
||||
///
|
||||
/// Return `Ok(())` if all requested permissions are allowed, otherwise return `Err(EACCES)`
|
||||
/// or other error code as appropriate (e.g. `ENOENT` if the file doesn't exist).
|
||||
fn access(&self, _req: RequestInfo, _path: &Path, _mask: u32) -> ResultEmpty {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
/// Create and open a new file.
|
||||
///
|
||||
/// * `parent`: path to the directory to create the file in.
|
||||
/// * `name`: name of the file to be created.
|
||||
/// * `mode`: the mode to set on the new file.
|
||||
/// * `flags`: flags like would be passed to `open`.
|
||||
///
|
||||
/// Return a `CreatedEntry` (which contains the new file's attributes as well as a file handle
|
||||
/// -- see documentation on `open` for more info on that).
|
||||
fn create(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreate {
|
||||
Err(libc::ENOSYS)
|
||||
}
|
||||
|
||||
}
|
||||
use std::env;
|
||||
impl LwsVfsIns {
|
||||
pub async fn new(json: &str) -> Result<LwsVfsIns, Box<dyn Error>> {
|
||||
let config = Config::new(json)?;
|
||||
let addr = format!("http://{}:{}", config.get_addr(), config.get_port());
|
||||
//connect to server
|
||||
let rpc = LwsVfsClient::connect(addr).await?;
|
||||
let rpc = RefCell::new(LwsVfsClient::connect(addr).await?);
|
||||
let async_rt = tokio::runtime::Runtime::new().unwrap();
|
||||
Ok(LwsVfsIns {
|
||||
config,
|
||||
rpc,
|
||||
async_rt,
|
||||
})
|
||||
}
|
||||
pub async fn hello(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
pub fn hello(&self) -> Result<(), Box<dyn Error>> {
|
||||
let request = tonic::Request::new(HelloRequest {
|
||||
name: "Ekko lws hello".into(),
|
||||
});
|
||||
let response = &self.rpc.say_hello(request).await?;
|
||||
|
||||
let response = self.async_rt.block_on(self.rpc.borrow_mut().say_hello(request))?;
|
||||
println!("RESPONSE={:?}", response);
|
||||
Ok(())
|
||||
}
|
||||
pub fn mount<FS:Filesystem>(file_system:FS) -> Result<(), Box<dyn Error>> {
|
||||
let mountpoint = "/mnt";
|
||||
let options = vec![MountOption::RO, MountOption::FSName("lws_fs".to_string())];
|
||||
fuser::mount2(file_system, mountpoint, &options).unwrap();
|
||||
|
||||
pub fn mount<F>(file_system:F) -> Result<(), Box<dyn Error>>
|
||||
where
|
||||
F: FilesystemMT + Sync + Send + 'static
|
||||
{
|
||||
let args: Vec<OsString> = env::args_os().collect();
|
||||
let fuse_args = [OsStr::new("-o"), OsStr::new("fsname=passthrufs")];
|
||||
fuse_mt::mount(fuse_mt::FuseMT::new(file_system, 1), &args[2], &fuse_args[..])?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user