添加初始提交
1. 编译已经通过 2. 添加好了rpc客户端的基本实现 3. 添加好了fuser的架子,内容等待实现
This commit is contained in:
parent
71505636ec
commit
24573524a6
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
1233
Cargo.lock
generated
Executable file
1233
Cargo.lock
generated
Executable file
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "lws_client"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]] # Bin to run the HelloWorld gRPC client
|
||||
name = "lws-client"
|
||||
path = "src/client.rs"
|
||||
|
||||
[dependencies]
|
||||
tonic = "0.11"
|
||||
prost = "0.12"
|
||||
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
fuser = "0.14.0"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.11"
|
4
build.rs
Executable file
4
build.rs
Executable file
|
@ -0,0 +1,4 @@
|
|||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
tonic_build::compile_protos("proto/lws.proto")?;
|
||||
Ok(())
|
||||
}
|
211
proto/lws.proto
Normal file
211
proto/lws.proto
Normal file
|
@ -0,0 +1,211 @@
|
|||
// Copyright 2015 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lws_vfs;
|
||||
|
||||
service LwsVfs {
|
||||
// Sends a greeting
|
||||
rpc SayHello(HelloRequest) returns (HelloReply) {}
|
||||
|
||||
rpc fgetattr(getattr) returns (getattr) {}
|
||||
rpc fsetxattr(setxattr) returns (setxattr) {}
|
||||
rpc faccess(access) returns (access) {}
|
||||
rpc freaddir(readdir) returns (readdir) {}
|
||||
rpc fread(read) returns (read) {}
|
||||
rpc fopen(open) returns (open) {}
|
||||
rpc fwrite(write) returns (write) {}
|
||||
rpc fgetxattr(getxattr) returns (getxattr) {}
|
||||
rpc ftruncate(truncate) returns (truncate) {}
|
||||
rpc futimens(utimens) returns (utimens) {}
|
||||
rpc fchown(chown) returns (chown) {}
|
||||
rpc frelease(release) returns (release) {}
|
||||
rpc fmkdir(mkdir) returns (mkdir) {}
|
||||
rpc frmdir(rmdir) returns (rmdir) {}
|
||||
rpc fflush(flush) returns (flush) {}
|
||||
rpc fopendir(opendir) returns (opendir) {}
|
||||
rpc freleasedir(releasedir) returns (releasedir) {}
|
||||
rpc fcreate(create) returns (create) {}
|
||||
rpc funlink(unlink) returns (unlink) {}
|
||||
rpc frename(rename) returns (rename) {}
|
||||
}
|
||||
|
||||
// The request message containing the user's name.
|
||||
message HelloRequest { string name = 1; }
|
||||
|
||||
// The response message containing the greetings
|
||||
message HelloReply { string message = 1; }
|
||||
|
||||
message file_info {
|
||||
int32 flags = 1;
|
||||
uint32 fh_old = 2;
|
||||
bool direct_io = 3;
|
||||
uint64 fh = 10;
|
||||
uint64 lock_owner = 11;
|
||||
}
|
||||
|
||||
message fstat {
|
||||
uint64 fst_mode = 1;
|
||||
uint64 fst_ino = 2;
|
||||
uint64 fst_dev = 3;
|
||||
uint64 fst_rdev = 4;
|
||||
uint64 fst_nlink = 5;
|
||||
uint64 fst_uid = 6;
|
||||
uint64 fst_gid = 7;
|
||||
uint64 fst_size = 8;
|
||||
uint64 fst_atime = 9;
|
||||
uint64 fst_mtime = 10;
|
||||
uint64 fst_ctime = 11;
|
||||
uint64 fst_blksize = 12;
|
||||
uint64 fst_blocks = 13;
|
||||
}
|
||||
|
||||
// fuse api function message define:
|
||||
message getattr {
|
||||
string path = 1;
|
||||
fstat stat = 2;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message setxattr {
|
||||
string path = 1;
|
||||
string name = 2;
|
||||
bytes value = 3;
|
||||
int64 size = 4;
|
||||
uint32 flags = 5;
|
||||
int32 ret = 15;
|
||||
}
|
||||
message getxattr {
|
||||
string path = 1;
|
||||
string name = 2;
|
||||
bytes value = 3;
|
||||
int64 size = 4;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message access {
|
||||
string path = 1;
|
||||
uint32 mask = 2;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message readdir {
|
||||
string path = 1;
|
||||
repeated string dirs = 2;
|
||||
uint32 offset = 3;
|
||||
file_info fi = 4;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message open {
|
||||
string path = 1;
|
||||
file_info fi = 2;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message read {
|
||||
string path = 1;
|
||||
bytes buff = 2;
|
||||
int64 size = 3;
|
||||
int64 offset = 4;
|
||||
file_info fi = 5;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message write {
|
||||
string path = 1;
|
||||
bytes buff = 2;
|
||||
int64 size = 3;
|
||||
int64 offset = 4;
|
||||
file_info fi = 5;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message truncate {
|
||||
string path = 1;
|
||||
int64 size = 3;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message timespec {
|
||||
int32 tv_sec = 1;
|
||||
int64 tv_nsec = 2;
|
||||
}
|
||||
message utimens {
|
||||
string path = 1;
|
||||
repeated timespec ts = 2; // const struct timespec ts[2]
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message chown {
|
||||
string path = 1;
|
||||
int32 uid = 2;
|
||||
int32 gid = 3;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message release {
|
||||
string path = 1;
|
||||
file_info fi = 2;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message mkdir {
|
||||
string path = 1;
|
||||
file_info fi = 2;
|
||||
uint32 mode = 3;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message rmdir {
|
||||
string path = 1;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message flush {
|
||||
string path = 1;
|
||||
file_info fi = 2;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message opendir {
|
||||
string path = 1;
|
||||
file_info fi = 2;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message releasedir {
|
||||
string path = 1;
|
||||
file_info fi = 2;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message create {
|
||||
string path = 1;
|
||||
uint32 mode = 2;
|
||||
file_info fi = 3;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message unlink {
|
||||
string path = 1;
|
||||
int32 ret = 15;
|
||||
}
|
||||
|
||||
message rename {
|
||||
string path = 1;
|
||||
string new = 2;
|
||||
int32 ret = 15;
|
||||
}
|
19
src/client.rs
Executable file
19
src/client.rs
Executable file
|
@ -0,0 +1,19 @@
|
|||
use lws_client::LwsVfsIns;
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut lws_ins = match LwsVfsIns::new("config.json").await{
|
||||
Ok(ins) => ins,
|
||||
Err(e) => {
|
||||
println!("Error creating lws server instance: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
match lws_ins.hello().await{
|
||||
Err(e) => {
|
||||
println!("lws client instance hello err {:?}", e);
|
||||
return Err(e);
|
||||
},
|
||||
_ =>{},
|
||||
}
|
||||
LwsVfsIns::mount(lws_ins)
|
||||
}
|
109
src/lib.rs
Normal file
109
src/lib.rs
Normal file
|
@ -0,0 +1,109 @@
|
|||
use lws_client::HelloRequest;
|
||||
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 fuser::{
|
||||
KernelConfig, FileAttr, FileType, Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry,
|
||||
Request,
|
||||
};
|
||||
|
||||
pub mod lws_client {
|
||||
tonic::include_proto!("lws_vfs"); //导入lws vfs proto buffer
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Config {
|
||||
port: u16,
|
||||
addr: String,
|
||||
mount_map: HashMap<String, String>,
|
||||
}
|
||||
impl Config {
|
||||
pub fn new(json: &str) -> Result<Config, Box<dyn Error>> {
|
||||
let mut file = File::open(json)?;
|
||||
let mut buffer = String::new();
|
||||
file.read_to_string(&mut buffer)?;
|
||||
let json: Value = serde_json::from_str(buffer.as_ref())?;
|
||||
let port: u16 = match json.get("port") {
|
||||
Some(port) => port.as_u64().expect("expect port is a number but its not") as u16,
|
||||
None => 5001,
|
||||
};
|
||||
let addr: String = match json.get("addr") {
|
||||
Some(addr) => addr.as_str().expect("expect addr is a String but its not").to_string(),
|
||||
None => "localhost".to_string(),
|
||||
};
|
||||
let mounts = match json.get("mount") {
|
||||
Some(mounts) => mounts.as_object().unwrap(),
|
||||
None => {
|
||||
return Err(Box::new(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"no mount map",
|
||||
)))
|
||||
}
|
||||
};
|
||||
let mount_map = mounts
|
||||
.iter()
|
||||
.map(|(key, value)| {
|
||||
(
|
||||
key.as_str().to_string(),
|
||||
value.as_str().unwrap().to_string(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
Ok(Config { port, addr, mount_map })
|
||||
}
|
||||
|
||||
pub fn get_port(&self) -> u16 {
|
||||
self.port
|
||||
}
|
||||
|
||||
pub fn get_addr(&self) -> &String {
|
||||
&self.addr
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LwsVfsIns {
|
||||
pub config: Config,
|
||||
rpc: LwsVfsClient<tonic::transport::Channel>
|
||||
}
|
||||
|
||||
impl Filesystem for LwsVfsIns {
|
||||
fn init(&mut self, _req: &Request, #[allow(unused_variables)] config: &mut KernelConfig,
|
||||
) -> Result<(), c_int> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
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?;
|
||||
Ok(LwsVfsIns {
|
||||
config,
|
||||
rpc,
|
||||
})
|
||||
}
|
||||
pub async fn hello(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
let request = tonic::Request::new(HelloRequest {
|
||||
name: "Ekko lws hello".into(),
|
||||
});
|
||||
let response = &self.rpc.say_hello(request).await?;
|
||||
|
||||
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();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
3
src/main.rs
Normal file
3
src/main.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
Loading…
Reference in New Issue
Block a user