1. 完成基本的测试项的构建
- 测试打开文件读取文件 - 测试打开目录读物目录 - 测试文件的读写功能 - 测试目录创建和删除 - 测试目录或者文件的访问 2. 将fd挪到fs impl里面完成!
This commit is contained in:
parent
82960cfe31
commit
017c52ce13
673
src/fs_impl/mod.rs
Normal file → Executable file
673
src/fs_impl/mod.rs
Normal file → Executable file
|
@ -1,7 +1,7 @@
|
||||||
use std::fs;
|
use std::fs::{self, File, ReadDir};
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::{self, ErrorKind, Seek as ioSeek, SeekFrom};
|
use std::io::{self, Seek as ioSeek, SeekFrom, Write};
|
||||||
|
|
||||||
use crate::lws_vfs::{FileInfo, Fstat};
|
use crate::lws_vfs::{FileInfo, Fstat};
|
||||||
|
|
||||||
|
@ -24,11 +24,18 @@ fn from_metadata(sta: &mut Fstat, metadata: &fs::Metadata) -> Result<(), Box<dyn
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
enum FileHandle {
|
||||||
|
#[default]
|
||||||
|
DEFAULT,
|
||||||
|
FILE(File),
|
||||||
|
DIR(ReadDir)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct FileFdMgnt {
|
struct FileFdMgnt {
|
||||||
// key is fd, value is FileHandle
|
// key is fd, value is FileHandle
|
||||||
files: HashMap<u64, File>,
|
files: HashMap<u64, FileHandle>,
|
||||||
curr_fd: u64,
|
curr_fd: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,161 +65,23 @@ impl FileFdMgnt {
|
||||||
}
|
}
|
||||||
Ok(self.curr_fd)
|
Ok(self.curr_fd)
|
||||||
}
|
}
|
||||||
pub fn push(&mut self, handle: File) -> Result<u64, Box<dyn Error>> {
|
pub fn push(&mut self, handle: FileHandle) -> Result<u64, Box<dyn Error>> {
|
||||||
let fd = self.gen_fd()?;
|
let fd = self.gen_fd()?;
|
||||||
|
println!("push a fd: {}", fd);
|
||||||
self.files.insert(fd, handle);
|
self.files.insert(fd, handle);
|
||||||
Ok(fd)
|
Ok(fd)
|
||||||
}
|
}
|
||||||
pub fn pop(&mut self, fd: u64) -> Option<File> {
|
pub fn pop(&mut self, fd: u64) -> Option<FileHandle> {
|
||||||
|
println!("pop a fd: {}", fd);
|
||||||
self.files.remove(&fd)
|
self.files.remove(&fd)
|
||||||
}
|
}
|
||||||
}
|
// pub fn get(&mut self, fd: u64) -> Option<&FileHandle> {
|
||||||
pub struct FSImpl{
|
// self.files.get(&fd)
|
||||||
file_fds: Arc<Mutex<FileFdMgnt>>,
|
// }
|
||||||
}
|
pub fn get_mut(&mut self, fd: u64) -> Option<&mut FileHandle> {
|
||||||
|
println!("get a fd: {}", fd);
|
||||||
impl FSImpl {
|
self.files.get_mut(&fd)
|
||||||
pub fn fgetattr(&self, path: &String, sta: &mut Fstat, _fi: &mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
|
||||||
let metadata = fs::metadata(path)?;
|
|
||||||
from_metadata(sta, &metadata)?;
|
|
||||||
let perm = get_file_mode_mask(path);
|
|
||||||
sta.fst_mode = perm as u64;
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fopen(&self, path: &String, _fi: &mut FileInfo) -> Result<fs::File, Box<dyn Error>> {
|
|
||||||
return Ok(fs::File::open(path)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fread(
|
|
||||||
&self, path: &String,
|
|
||||||
buffer: &mut Vec<u8>,
|
|
||||||
_size: &mut usize,
|
|
||||||
offsize: usize,
|
|
||||||
_fi: &mut FileInfo,
|
|
||||||
) -> Result<i32, Box<dyn Error>> {
|
|
||||||
let mut file = fs::File::open(path)?;
|
|
||||||
match file.seek_read(buffer, offsize as u64) {
|
|
||||||
Ok(size) => {
|
|
||||||
println!(
|
|
||||||
"size is:{}, buffer is {}",
|
|
||||||
size,
|
|
||||||
String::from_utf8(buffer.to_vec()).unwrap()
|
|
||||||
);
|
|
||||||
buffer.resize(size, 0)
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
buffer.resize(file.stream_position()? as usize - offsize, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fwrite(
|
|
||||||
&self, path: &String,
|
|
||||||
buffer: &Vec<u8>,
|
|
||||||
size: &mut usize,
|
|
||||||
offsize: usize,
|
|
||||||
_fi: &mut FileInfo,
|
|
||||||
) -> Result<i32, Box<dyn Error>> {
|
|
||||||
let mut file = fs::File::options().write(true).create(true).open(path)?;
|
|
||||||
match file.seek_write(buffer, offsize as u64) {
|
|
||||||
Ok(written) => {
|
|
||||||
*size = written as usize;
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
*size = file.stream_position()? as usize - offsize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
pub fn freaddir(
|
|
||||||
&self, path: &String,
|
|
||||||
buffer: &mut Vec<String>,
|
|
||||||
_size: usize,
|
|
||||||
_offset: usize,
|
|
||||||
_fi: &mut FileInfo,
|
|
||||||
) -> Result<i32, Box<dyn Error>> {
|
|
||||||
let mut readed = fs::read_dir(path)?;
|
|
||||||
loop {
|
|
||||||
match readed.next() {
|
|
||||||
Some(Ok(entry)) => {
|
|
||||||
let name = entry.file_name().into_string().unwrap();
|
|
||||||
buffer.push(name);
|
|
||||||
}
|
|
||||||
Some(Err(e)) => {
|
|
||||||
return Err(Box::new(e));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
pub fn fmkdir(&self, path: &String, _mode: u32) -> Result<i32, Box<dyn Error>> {
|
|
||||||
fs::create_dir(path)?;
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
pub fn fchown(&self, _path: &String, _uid: u32, _gid: u32) -> Result<i32, Box<dyn Error>> {
|
|
||||||
Ok(-1)
|
|
||||||
}
|
|
||||||
pub fn ftruncate(&self, path: &String, size: u64) -> Result<i32, Box<dyn Error>> {
|
|
||||||
let mut file = fs::File::options().write(true)
|
|
||||||
.truncate(true)
|
|
||||||
.open(path)?;
|
|
||||||
file.seek(SeekFrom::Start(size))?;
|
|
||||||
file.set_len(size)?;
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn futimens(&self, path: &String, a: &Vec<u64>, m: &Vec<u64>) -> Result<i32, Box<dyn Error>> {
|
|
||||||
use std::ptr::null_mut;
|
|
||||||
use winapi::ctypes::c_void;
|
|
||||||
use winapi::shared::minwindef::DWORD;
|
|
||||||
use winapi::shared::minwindef::FILETIME;
|
|
||||||
use winapi::um::fileapi::SetFileTime;
|
|
||||||
fn system_time_to_file_time(seconds: u64, nanoseconds: u32) -> FILETIME {
|
|
||||||
let total_nanoseconds = (seconds * 1_000_000_000) + nanoseconds as u64;
|
|
||||||
let total_100_nanoseconds = total_nanoseconds / 100;
|
|
||||||
FILETIME {
|
|
||||||
dwLowDateTime: total_100_nanoseconds as DWORD,
|
|
||||||
dwHighDateTime: (total_100_nanoseconds >> 32) as DWORD,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let file = fs::File::options().write(true).open(path)?;
|
|
||||||
let handle = file.as_raw_handle();
|
|
||||||
|
|
||||||
let atime = system_time_to_file_time(a[0], a[1] as u32);
|
|
||||||
let mtime = system_time_to_file_time(m[0], m[1] as u32);
|
|
||||||
|
|
||||||
let result = unsafe { SetFileTime(handle as *mut c_void, null_mut(), &atime, &mtime) };
|
|
||||||
|
|
||||||
if result != 0 {
|
|
||||||
Ok(0)
|
|
||||||
} else {
|
|
||||||
Err(Box::new(io::Error::last_os_error()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn frelease(&self, _path: &String, _fi: &mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
|
||||||
if let Some(fh) == self.file_fds.lock().unwrap().pop(fi.fh){
|
|
||||||
drop(fh);
|
|
||||||
Ok(0)
|
|
||||||
} else {
|
|
||||||
Ok(-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn fsetxattr(
|
|
||||||
&self, _path: &String,
|
|
||||||
_name: &str,
|
|
||||||
_value: &Vec<u8>,
|
|
||||||
_size: usize,
|
|
||||||
_flags: u32,
|
|
||||||
) -> Result<i32, Box<dyn Error>> {
|
|
||||||
Ok(-1)
|
|
||||||
}
|
|
||||||
pub fn fgetxattr(&self, _path: &String, _name: &str, _size: usize) -> Result<i32, Box<dyn Error>> {
|
|
||||||
Ok(-1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_file_mode_mask(path: &str) -> u32 {
|
fn get_file_mode_mask(path: &str) -> u32 {
|
||||||
|
@ -236,15 +105,321 @@ fn get_file_mode_mask(path: &str) -> u32 {
|
||||||
}
|
}
|
||||||
permissions
|
permissions
|
||||||
}
|
}
|
||||||
pub fn faccess(&self, path: &String, mask: u32) -> Result<i32, Box<dyn Error>> {
|
#[derive(Debug, Default)]
|
||||||
let permissions = get_file_mode_mask(path);
|
pub struct FSImpl{
|
||||||
Ok(if permissions & mask != 0 { 0 } else { -1 })
|
file_fds: Arc<Mutex<FileFdMgnt>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frmdir(&self, path: &String) -> Result<i32, Box<dyn Error>> {
|
impl FSImpl {
|
||||||
fs::remove_dir(path)?;
|
|
||||||
Ok(0)
|
pub fn new() -> FSImpl {
|
||||||
}
|
FSImpl {
|
||||||
|
file_fds: Arc::new(Mutex::new(FileFdMgnt::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn fgetattr(&self, path: &String, sta: &mut Fstat, _fi: &mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let metadata = fs::metadata(path)?;
|
||||||
|
from_metadata(sta, &metadata)?;
|
||||||
|
let perm = get_file_mode_mask(path);
|
||||||
|
sta.fst_mode = perm as u64;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fopen(&self, path: &String, fi: &mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let f = fs::File::open(path)?;
|
||||||
|
let fd = self.file_fds.lock().unwrap().push(FileHandle::FILE(f))?;
|
||||||
|
fi.fh = fd;
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fread(
|
||||||
|
&self, path: &String,
|
||||||
|
buffer: &mut Vec<u8>,
|
||||||
|
_size: &mut usize,
|
||||||
|
offsize: usize,
|
||||||
|
fi: &mut FileInfo,
|
||||||
|
) -> Result<i32, Box<dyn Error>> {
|
||||||
|
|
||||||
|
let fd = fi.fh;
|
||||||
|
let mut fds = self.file_fds.lock().unwrap();
|
||||||
|
let fh: File;
|
||||||
|
let mut file = if let Some(FileHandle::FILE(f)) = fds.get_mut(fd) {
|
||||||
|
f
|
||||||
|
} else {
|
||||||
|
fh = fs::File::open(path)?;
|
||||||
|
&fh
|
||||||
|
};
|
||||||
|
match file.seek_read(buffer, offsize as u64) {
|
||||||
|
Ok(size) => {
|
||||||
|
println!(
|
||||||
|
"size is:{}, buffer is {}",
|
||||||
|
size,
|
||||||
|
String::from_utf8(buffer.to_vec()).unwrap()
|
||||||
|
);
|
||||||
|
buffer.resize(size, 0);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
buffer.resize(file.stream_position()? as usize - offsize, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fwrite(
|
||||||
|
&self, path: &String,
|
||||||
|
buffer: &Vec<u8>,
|
||||||
|
size: &mut usize,
|
||||||
|
offsize: usize,
|
||||||
|
fi: &mut FileInfo,
|
||||||
|
) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let fd = fi.fh;
|
||||||
|
let mut fds = self.file_fds.lock().unwrap();
|
||||||
|
let fh: File;
|
||||||
|
let mut file = if let Some(FileHandle::FILE(f)) = fds.get_mut(fd) {
|
||||||
|
f
|
||||||
|
} else {
|
||||||
|
fh = fs::File::options().write(true).create(true).open(path)?;
|
||||||
|
&fh
|
||||||
|
};
|
||||||
|
match file.seek_write(buffer, offsize as u64) {
|
||||||
|
Ok(written) => {
|
||||||
|
*size = written as usize;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
*size = file.stream_position()? as usize - offsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
/** Read directory
|
||||||
|
*
|
||||||
|
* This supersedes the old getdir() interface. New applications
|
||||||
|
* should use this.
|
||||||
|
*
|
||||||
|
* The filesystem may choose between two modes of operation:
|
||||||
|
*
|
||||||
|
* 1) The readdir implementation ignores the offset parameter, and
|
||||||
|
* passes zero to the filler function's offset. The filler
|
||||||
|
* function will not return '1' (unless an error happens), so the
|
||||||
|
* whole directory is read in a single readdir operation. This
|
||||||
|
* works just like the old getdir() method.
|
||||||
|
*
|
||||||
|
* 2) The readdir implementation keeps track of the offsets of the
|
||||||
|
* directory entries. It uses the offset parameter and always
|
||||||
|
* passes non-zero offset to the filler function. When the buffer
|
||||||
|
* is full (or an error happens) the filler function will return
|
||||||
|
* '1'.
|
||||||
|
*
|
||||||
|
* Introduced in version 2.3
|
||||||
|
*/
|
||||||
|
pub fn freaddir(&self, path: &String, buffer: &mut Vec<String>, _size: usize, _offset: usize, fi: &mut FileInfo,
|
||||||
|
) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let mut fh = self.file_fds.lock().unwrap();
|
||||||
|
let mut collect = move |entry:&mut ReadDir| -> Result<i32, Box<dyn Error>> {
|
||||||
|
loop {
|
||||||
|
match entry.next() {
|
||||||
|
Some(Ok(entry)) => {
|
||||||
|
let name = entry.file_name().into_string().unwrap();
|
||||||
|
buffer.push(name);
|
||||||
|
}
|
||||||
|
Some(Err(e)) => {
|
||||||
|
return Err(Box::new(e));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(0)
|
||||||
|
};
|
||||||
|
match fh.get_mut(fi.fh){
|
||||||
|
Some(dir) => {
|
||||||
|
if let FileHandle::DIR(entry) = dir {
|
||||||
|
collect(entry)
|
||||||
|
} else {
|
||||||
|
collect( &mut fs::read_dir(path)?)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
collect( &mut fs::read_dir(path)?)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn fmkdir(&self, path: &String, _mode: u32) -> Result<i32, Box<dyn Error>> {
|
||||||
|
fs::create_dir(path)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
pub fn fchown(&self, _path: &String, _uid: u32, _gid: u32) -> Result<i32, Box<dyn Error>> {
|
||||||
|
Ok(-1)
|
||||||
|
}
|
||||||
|
pub fn ftruncate(&self, path: &String, size: u64) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let mut file = fs::File::options().write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(path)?;
|
||||||
|
file.seek(SeekFrom::Start(size))?;
|
||||||
|
file.set_len(size)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn futimens(&self, path: &String, a: &Vec<u64>, m: &Vec<u64>) -> Result<i32, Box<dyn Error>> {
|
||||||
|
use std::ptr::null_mut;
|
||||||
|
use winapi::ctypes::c_void;
|
||||||
|
use winapi::shared::minwindef::DWORD;
|
||||||
|
use winapi::shared::minwindef::FILETIME;
|
||||||
|
use winapi::um::fileapi::SetFileTime;
|
||||||
|
fn system_time_to_file_time(seconds: u64, nanoseconds: u32) -> FILETIME {
|
||||||
|
let total_nanoseconds = (seconds * 1_000_000_000) + nanoseconds as u64;
|
||||||
|
let total_100_nanoseconds = total_nanoseconds / 100;
|
||||||
|
FILETIME {
|
||||||
|
dwLowDateTime: total_100_nanoseconds as DWORD,
|
||||||
|
dwHighDateTime: (total_100_nanoseconds >> 32) as DWORD,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let file = fs::File::options().write(true).open(path)?;
|
||||||
|
let handle = file.as_raw_handle();
|
||||||
|
|
||||||
|
let atime = system_time_to_file_time(a[0], a[1] as u32);
|
||||||
|
let mtime = system_time_to_file_time(m[0], m[1] as u32);
|
||||||
|
|
||||||
|
let result = unsafe { SetFileTime(handle as *mut c_void, null_mut(), &atime, &mtime) };
|
||||||
|
|
||||||
|
if result != 0 {
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
Err(Box::new(io::Error::last_os_error()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn frelease(&self, _path: &String, fi: &mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
||||||
|
if let Some(fh) = self.file_fds.lock().unwrap().pop(fi.fh) {
|
||||||
|
drop(fh);
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
Ok(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn fsetxattr(
|
||||||
|
&self, _path: &String,
|
||||||
|
_name: &str,
|
||||||
|
_value: &Vec<u8>,
|
||||||
|
_size: usize,
|
||||||
|
_flags: u32,
|
||||||
|
) -> Result<i32, Box<dyn Error>> {
|
||||||
|
Ok(-1)
|
||||||
|
}
|
||||||
|
pub fn fgetxattr(&self, _path: &String, _name: &str, _size: usize) -> Result<i32, Box<dyn Error>> {
|
||||||
|
Ok(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn faccess(&self, path: &String, mask: u32) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let permissions = get_file_mode_mask(path);
|
||||||
|
Ok(if permissions & mask != 0 { 0 } else { -1 })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn frmdir(&self, path: &String) -> Result<i32, Box<dyn Error>> {
|
||||||
|
fs::remove_dir(path)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
/** Possibly flush cached data
|
||||||
|
*
|
||||||
|
* BIG NOTE: This is not equivalent to fsync(). It's not a
|
||||||
|
* request to sync dirty data.
|
||||||
|
*
|
||||||
|
* Flush is called on each close() of a file descriptor. So if a
|
||||||
|
* filesystem wants to return write errors in close() and the file
|
||||||
|
* has cached dirty data, this is a good place to write back data
|
||||||
|
* and return any errors. Since many applications ignore close()
|
||||||
|
* errors this is not always useful.
|
||||||
|
*
|
||||||
|
* NOTE: The flush() method may be called more than once for each
|
||||||
|
* open(). This happens if more than one file descriptor refers
|
||||||
|
* to an opened file due to dup(), dup2() or fork() calls. It is
|
||||||
|
* not possible to determine if a flush is final, so each flush
|
||||||
|
* should be treated equally. Multiple write-flush sequences are
|
||||||
|
* relatively rare, so this shouldn't be a problem.
|
||||||
|
*
|
||||||
|
* Filesystems shouldn't assume that flush will always be called
|
||||||
|
* after some writes, or that if will be called at all.
|
||||||
|
*
|
||||||
|
* Changed in version 2.2
|
||||||
|
*/
|
||||||
|
pub fn fflush(&self, _path: &String, fi: &mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let fd = fi.fh;
|
||||||
|
let mut fmap = self.file_fds.lock().unwrap();
|
||||||
|
let file = fmap.get_mut(fd).unwrap();
|
||||||
|
match file {
|
||||||
|
FileHandle::FILE(fh) => {
|
||||||
|
fh.flush()?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Ok(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create and open a file
|
||||||
|
*
|
||||||
|
* If the file does not exist, first create it with the specified
|
||||||
|
* mode, and then open it.
|
||||||
|
*
|
||||||
|
* If this method is not implemented or under Linux kernel
|
||||||
|
* versions earlier than 2.6.15, the mknod() and open() methods
|
||||||
|
* will be called instead.
|
||||||
|
*
|
||||||
|
* Introduced in version 2.5
|
||||||
|
*/
|
||||||
|
pub fn fcreate(&self, path:&String, mode:u32, fi:&mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let file = File::options().write(true).access_mode(mode).create(true).open(path)?;
|
||||||
|
let fd = self.file_fds.lock().unwrap().push(FileHandle::FILE(file))?;
|
||||||
|
fi.fh = fd;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove a file
|
||||||
|
*
|
||||||
|
* If that file was the last link to a file and no processes have
|
||||||
|
* the file open the file is deleted and the space it was using is
|
||||||
|
* made available for reuse.
|
||||||
|
*
|
||||||
|
* If the file is open, the file may remain in existence until the
|
||||||
|
* last file descriptor referring to it is closed.
|
||||||
|
*
|
||||||
|
* Introduced in version 2.2
|
||||||
|
*/
|
||||||
|
pub fn funlink(&self, path: &String) ->Result<i32, Box<dyn Error>>{
|
||||||
|
fs::remove_file(path)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Open directory
|
||||||
|
*
|
||||||
|
* Unless the 'default_permissions' mount option is given,
|
||||||
|
* this method should check if opendir is permitted for this
|
||||||
|
* directory. Optionally opendir may also return an arbitrary
|
||||||
|
* filehandle in the fuse_file_info structure, which will be
|
||||||
|
* passed to readdir, releasedir and fsyncdir.
|
||||||
|
*
|
||||||
|
* Introduced in version 2.3
|
||||||
|
*/
|
||||||
|
pub fn fopendir(&self, path:&String, fi:&mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let entries = fs::read_dir(path)?;
|
||||||
|
let fd = self.file_fds.lock().unwrap().push(FileHandle::DIR(entries))?;
|
||||||
|
fi.fh = fd;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Release directory
|
||||||
|
*
|
||||||
|
* Introduced in version 2.3
|
||||||
|
*/
|
||||||
|
pub fn freleasedir(&self, _path: &String, fi: &mut FileInfo) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let fd = fi.fh;
|
||||||
|
if let Some(FileHandle::DIR(_entries)) = self.file_fds.lock().unwrap().pop(fd) {
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
Ok(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -260,25 +435,26 @@ fn test_fread() {
|
||||||
let ref_buffer = b"This is a test file.";
|
let ref_buffer = b"This is a test file.";
|
||||||
let _ = file.seek_write(ref_buffer, 0);
|
let _ = file.seek_write(ref_buffer, 0);
|
||||||
|
|
||||||
|
let fs = FSImpl::new();
|
||||||
let mut fi = FileInfo::default();
|
let mut fi = FileInfo::default();
|
||||||
|
|
||||||
//read from file middle
|
//read from file middle
|
||||||
let mut size = 4;
|
let mut size = 4;
|
||||||
let mut offsize: usize = 5;
|
let mut offsize: usize = 5;
|
||||||
let mut buffer = vec![0; size];
|
let mut buffer = vec![0; size];
|
||||||
let _ = fread(&path, &mut buffer, &mut size, offsize, &mut fi);
|
let _ = fs.fread(&path, &mut buffer, &mut size, offsize, &mut fi);
|
||||||
assert_eq!(buffer.len(), 4);
|
assert_eq!(buffer.len(), 4);
|
||||||
assert_eq!(buffer, b"is a");
|
assert_eq!(buffer, b"is a");
|
||||||
|
|
||||||
//read from file head
|
//read from file head
|
||||||
offsize = 0;
|
offsize = 0;
|
||||||
let _ = fread(&path, &mut buffer, &mut size, offsize, &mut fi);
|
let _ = fs.fread(&path, &mut buffer, &mut size, offsize, &mut fi);
|
||||||
assert_eq!(buffer.len(), 4);
|
assert_eq!(buffer.len(), 4);
|
||||||
assert_eq!(buffer, b"This");
|
assert_eq!(buffer, b"This");
|
||||||
|
|
||||||
// read from the file tail, read len > file remain
|
// read from the file tail, read len > file remain
|
||||||
offsize = ref_buffer.len() - 2;
|
offsize = ref_buffer.len() - 2;
|
||||||
let _ = fread(&path, &mut buffer, &mut size, offsize, &mut fi);
|
let _ = fs.fread(&path, &mut buffer, &mut size, offsize, &mut fi);
|
||||||
assert_eq!(buffer.len(), 2);
|
assert_eq!(buffer.len(), 2);
|
||||||
assert_eq!(buffer, b"e.");
|
assert_eq!(buffer, b"e.");
|
||||||
|
|
||||||
|
@ -290,18 +466,20 @@ fn test_fwrite() {
|
||||||
use crate::fs_impl::*;
|
use crate::fs_impl::*;
|
||||||
let path = String::from("test_fwrite.txt");
|
let path = String::from("test_fwrite.txt");
|
||||||
let _ = fs::remove_file(&path);
|
let _ = fs::remove_file(&path);
|
||||||
let mut buffer = Vec::from("This is a test file");
|
let buffer = Vec::from("This is a test file");
|
||||||
let mut size = buffer.len();
|
let mut size = buffer.len();
|
||||||
|
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
|
||||||
//write from file head
|
//write from file head
|
||||||
let mut offsize: usize = 0;
|
let mut offsize: usize = 0;
|
||||||
let mut fi = FileInfo::default();
|
let mut fi = FileInfo::default();
|
||||||
let _ = fwrite(&path, &buffer, &mut size, offsize, &mut fi);
|
let _ = fs.fwrite(&path, &buffer, &mut size, offsize, &mut fi);
|
||||||
assert_eq!(size, buffer.len());
|
assert_eq!(size, buffer.len());
|
||||||
|
|
||||||
//write from file middle
|
//write from file middle
|
||||||
offsize = 5;
|
offsize = 5;
|
||||||
let _ = fwrite(&path, &buffer, &mut size, offsize, &mut fi);
|
let _ = fs.fwrite(&path, &buffer, &mut size, offsize, &mut fi);
|
||||||
assert_eq!(size, buffer.len());
|
assert_eq!(size, buffer.len());
|
||||||
let file_metadata = fs::metadata(&path).unwrap();
|
let file_metadata = fs::metadata(&path).unwrap();
|
||||||
let file_size = file_metadata.len();
|
let file_size = file_metadata.len();
|
||||||
|
@ -309,7 +487,7 @@ fn test_fwrite() {
|
||||||
|
|
||||||
//write from file ended
|
//write from file ended
|
||||||
offsize = file_size as usize + 10;
|
offsize = file_size as usize + 10;
|
||||||
let _ = fwrite(&path, &buffer, &mut size, offsize, &mut fi);
|
let _ = fs.fwrite(&path, &buffer, &mut size, offsize, &mut fi);
|
||||||
assert_eq!(size, buffer.len());
|
assert_eq!(size, buffer.len());
|
||||||
let file_metadata = fs::metadata(&path).unwrap();
|
let file_metadata = fs::metadata(&path).unwrap();
|
||||||
let file_size = file_metadata.len();
|
let file_size = file_metadata.len();
|
||||||
|
@ -323,14 +501,17 @@ fn test_dir() {
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
let path = String::from("test_dir");
|
let path = String::from("test_dir");
|
||||||
let sub_path = String::from("test_dir/test_sub_dir");
|
let sub_path = String::from("test_dir/test_sub_dir");
|
||||||
|
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
|
||||||
//创建父目录
|
//创建父目录
|
||||||
let _ = fmkdir(&path, 0);
|
let _ = fs.fmkdir(&path, 0);
|
||||||
//创建子目录
|
//创建子目录
|
||||||
let _ = fmkdir(&sub_path, 0);
|
let _ = fs.fmkdir(&sub_path, 0);
|
||||||
assert_eq!(true, Path::new(&sub_path).is_dir());
|
assert_eq!(true, Path::new(&sub_path).is_dir());
|
||||||
assert_eq!(true, Path::new(&path).is_dir());
|
assert_eq!(true, Path::new(&path).is_dir());
|
||||||
//一次性创建多级目录
|
//一次性创建多级目录
|
||||||
let ret = fmkdir(&String::from("patent/child"), 0);
|
let ret = fs.fmkdir(&String::from("patent/child"), 0);
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
match ret {
|
match ret {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
|
@ -338,28 +519,136 @@ fn test_dir() {
|
||||||
},
|
},
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
fs::remove_dir_all(path);
|
let _ = fs::remove_dir_all(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_access() {
|
||||||
|
let path = String::from("target/debug/build");
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
//access a existed file
|
||||||
|
let ret = fs.faccess(&path, 0o777);
|
||||||
|
assert_eq!(match ret {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(_) => -1,
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_access_ne() {
|
||||||
|
let path = String::from("target/xxx");
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
//acess a not exist file
|
||||||
|
let ret = fs.faccess(&path, 0o777);
|
||||||
|
assert_ne!(match ret {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(_) => -1,
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mkdir_not_existed_multi_level() {
|
||||||
|
let path = String::from("test_mkdir_not_existed_multi_level/sub/sub");
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
//mkdir a multi not existed level dir
|
||||||
|
let ret = fs.fmkdir(&path, 0);
|
||||||
|
assert_ne!(match ret {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(_) => -1,
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
let _ = fs::remove_dir_all(path);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_mkdir_not_existed_level() {
|
||||||
|
let path = String::from("test_mkdir_not_existed_level");
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
//mkdir a not existed single level dir
|
||||||
|
let ret = fs.fmkdir(&path, 0);
|
||||||
|
assert_eq!(match ret {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(_) => -1,
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
let path = String::from("test_mkdir_not_existed_level/sub");
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
//mkdir a existed multi level dir
|
||||||
|
let ret = fs.fmkdir(&path, 0);
|
||||||
|
assert_eq!(match ret {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(_) => -1,
|
||||||
|
}, 0);
|
||||||
|
let _ = fs::remove_dir_all(&String::from("test_mkdir_not_existed_level"));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_mkdir_existed() {
|
||||||
|
let path = String::from("target");
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
//mkdir a existed dir
|
||||||
|
let ret = fs.fmkdir(&path, 0);
|
||||||
|
assert_eq!(match ret {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(_) => -1,
|
||||||
|
}, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_a_file_flow() {
|
||||||
|
let path = String::from("test/pattern/read.txt");
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
let mut size = 5;
|
||||||
|
let mut buffer = vec![0; size];
|
||||||
|
let mut offset = 0;
|
||||||
|
let mut fi = vec![FileInfo::default(), FileInfo::default()];
|
||||||
|
let get_ret = |ret: Result<i32, Box<dyn Error>> | match ret {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(_) => -1,
|
||||||
|
};
|
||||||
|
let ret= fs.fopen(&path, &mut fi[0]);
|
||||||
|
println!("fopen file ok fd = {}", fi[0].fh);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
|
|
||||||
|
let ret = fs.fread(&path, &mut buffer, &mut size,offset, &mut fi[0]);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
|
|
||||||
|
assert_eq!(buffer, Vec::from("12345"));
|
||||||
|
|
||||||
|
let ret= fs.fopen(&path, &mut fi[1]);
|
||||||
|
println!("fopen file ok fd = {}", fi[1].fh);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
|
|
||||||
|
offset = 9;
|
||||||
|
let ret = fs.fread(&path, &mut buffer, &mut size,offset, &mut fi[1]);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
|
assert_eq!(buffer, Vec::from("abcde"));
|
||||||
|
|
||||||
|
let ret = fs.frelease(&path, &mut fi[0]);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
|
let ret = fs.frelease(&path, &mut fi[1]);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_a_dir_flow() {
|
||||||
|
let path = String::from("./src");
|
||||||
|
let fs = FSImpl::new();
|
||||||
|
let size = 0;
|
||||||
|
let mut buffer: Vec<String> = vec![];
|
||||||
|
let offset = 0;
|
||||||
|
let mut fi = vec![FileInfo::default(), FileInfo::default()];
|
||||||
|
let get_ret = |ret: Result<i32, Box<dyn Error>> | match ret {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(_) => -1,
|
||||||
|
};
|
||||||
|
let ret= fs.fopendir(&path, &mut fi[0]);
|
||||||
|
println!("fopen dir ok fd = {}", fi[0].fh);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
|
|
||||||
|
let ret = fs.freaddir(&path, &mut buffer, size, offset, &mut fi[0]);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
|
|
||||||
|
println!("buffer = {:?}", buffer);
|
||||||
|
|
||||||
|
let ret = fs.freleasedir(&path, &mut fi[0]);
|
||||||
|
assert_eq!(get_ret(ret), 0);
|
||||||
}
|
}
|
||||||
// let result = fwrite(&path, &buffer, &mut size, offsize, &mut fi);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// println!("size: {:?}", size);
|
|
||||||
// println!("buffer: {:?}", buffer);
|
|
||||||
// let result = freaddir(&path, &mut vec![], 0, 0, &mut fi);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// println!("buffer: {:?}", buffer);
|
|
||||||
// let result = fmkdir(&path, 0);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// let result = fchown(&path, 0, 0);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// let result = ftruncate(&path, 100);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// let result = futimens(&path, &vec![100, 0], &vec![100, 0]);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// let result = frelease(&path, &mut fi);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// let result = fsetxattr(&path, "test", &vec![1,2,3], 3, 0);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// let result = fgetxattr(&path, "test", 100);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
// let result = faccess(&path, 0o777);
|
|
||||||
// println!("result: {:?}", result);
|
|
||||||
|
|
133
src/lib.rs
Normal file → Executable file
133
src/lib.rs
Normal file → Executable file
|
@ -1,13 +1,16 @@
|
||||||
|
|
||||||
use lws_vfs::lws_vfs_server::LwsVfs;
|
use lws_vfs::lws_vfs_server::LwsVfs;
|
||||||
use lws_vfs::{
|
use lws_vfs::{
|
||||||
Access, Chown, FileInfo, Flush, Fstat, Getattr, Getxattr, HelloReply, HelloRequest, Mkdir,
|
Access, Chown, FileInfo, Flush, Fstat, Getattr, Getxattr, HelloReply, HelloRequest, Mkdir,
|
||||||
Open, Read, Readdir, Release, Rmdir, Setxattr, Truncate, Utimens, Write, Flush,
|
Open, Read, Readdir, Release, Rmdir, Setxattr, Truncate, Utimens, Write, Create, Unlink, Opendir, Releasedir
|
||||||
};
|
};
|
||||||
|
use self::fs_impl::FSImpl;
|
||||||
use serde_json::{self, Value};
|
use serde_json::{self, Value};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufReader, Read as _};
|
use std::io::Read as _;
|
||||||
use tonic::{Request, Response, Status};
|
use tonic::{Request, Response, Status};
|
||||||
|
use std::collections::HashMap;
|
||||||
mod fs_impl;
|
mod fs_impl;
|
||||||
pub mod lws_vfs {
|
pub mod lws_vfs {
|
||||||
tonic::include_proto!("lws_vfs");
|
tonic::include_proto!("lws_vfs");
|
||||||
|
@ -69,14 +72,14 @@ impl Config {
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct LwsVfsIns {
|
pub struct LwsVfsIns {
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
file_fds: Arc<Mutex<FileFdMgnt>>,
|
pub fs: FSImpl,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LwsVfsIns {
|
impl LwsVfsIns {
|
||||||
pub fn new(json: &str) -> Result<LwsVfsIns, Box<dyn Error>> {
|
pub fn new(json: &str) -> Result<LwsVfsIns, Box<dyn Error>> {
|
||||||
Ok(LwsVfsIns {
|
Ok(LwsVfsIns {
|
||||||
config: Config::new(json)?,
|
config: Config::new(json)?,
|
||||||
file_fds: Arc::new(Mutex::new(FileFdMgnt::new())),
|
fs: FSImpl::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn lpath(&self, path: &String) -> String {
|
fn lpath(&self, path: &String) -> String {
|
||||||
|
@ -112,7 +115,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let mut fstat = Fstat::default();
|
let mut fstat = Fstat::default();
|
||||||
let mut fi = FileInfo::default();
|
let mut fi = FileInfo::default();
|
||||||
let ret = match fs_impl::fgetattr(path, &mut fstat, &mut fi) {
|
let ret = match self.fs.fgetattr(path, &mut fstat, &mut fi) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error getting file metadata: {:?}", e);
|
println!("Error getting file metadata: {:?}", e);
|
||||||
|
@ -131,14 +134,8 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let request = request.into_inner();
|
let request = request.into_inner();
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let mut fi = request.fi.unwrap();
|
let mut fi = request.fi.unwrap();
|
||||||
let ret = match fs_impl::fopen(path, &mut fi) {
|
let ret = match self.fs.fopen(path, &mut fi) {
|
||||||
Ok(file) => {
|
Ok(_) => {
|
||||||
match self.file_fds.lock().unwrap().push(file) {
|
|
||||||
Ok(fd) => fi.fh = fd,
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error pushing file[{}]: {:?}", path, e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -164,7 +161,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
unsafe {
|
unsafe {
|
||||||
buff.set_len(size);
|
buff.set_len(size);
|
||||||
}
|
}
|
||||||
match fs_impl::fread(path, &mut buff, &mut size, offset, &mut fi) {
|
match self.fs.fread(path, &mut buff, &mut size, offset, &mut fi) {
|
||||||
Ok(ret) => {
|
Ok(ret) => {
|
||||||
let reply = Read {
|
let reply = Read {
|
||||||
path: request.path,
|
path: request.path,
|
||||||
|
@ -197,7 +194,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let buff = request.buff;
|
let buff = request.buff;
|
||||||
let mut size = request.size as usize;
|
let mut size = request.size as usize;
|
||||||
let offset = request.offset as usize;
|
let offset = request.offset as usize;
|
||||||
let ret = match fs_impl::fwrite(path, &buff, &mut size, offset, &mut fi) {
|
let ret = match self.fs.fwrite(path, &buff, &mut size, offset, &mut fi) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error fwrite file[{}]: {:?}", path, e);
|
println!("Error fwrite file[{}]: {:?}", path, e);
|
||||||
|
@ -215,7 +212,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let request = request.into_inner();
|
let request = request.into_inner();
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let mask = request.mask;
|
let mask = request.mask;
|
||||||
let ret = match fs_impl::faccess(path, mask) {
|
let ret = match self.fs.faccess(path, mask) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error access file[{}]: {:?}", path, e);
|
println!("Error access file[{}]: {:?}", path, e);
|
||||||
|
@ -237,7 +234,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let value = req.value;
|
let value = req.value;
|
||||||
let size = req.size as usize;
|
let size = req.size as usize;
|
||||||
let flags = req.flags;
|
let flags = req.flags;
|
||||||
let ret = match fs_impl::fsetxattr(path, name, &value, size, flags) {
|
let ret = match self.fs.fsetxattr(path, name, &value, size, flags) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: setxattr file[{}]: {:?}", path, e);
|
println!("Error: setxattr file[{}]: {:?}", path, e);
|
||||||
|
@ -255,7 +252,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let path = &self.lpath(&req.path);
|
let path = &self.lpath(&req.path);
|
||||||
let name = req.name.as_ref();
|
let name = req.name.as_ref();
|
||||||
let size = req.size as usize;
|
let size = req.size as usize;
|
||||||
let ret = match fs_impl::fgetxattr(path, name, size) {
|
let ret = match self.fs.fgetxattr(path, name, size) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: getxattr file[{}]: {:?}", path, e);
|
println!("Error: getxattr file[{}]: {:?}", path, e);
|
||||||
|
@ -276,7 +273,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let offset = request.offset as usize;
|
let offset = request.offset as usize;
|
||||||
let mut dirs: Vec<String> = Vec::new();
|
let mut dirs: Vec<String> = Vec::new();
|
||||||
let size = 0;
|
let size = 0;
|
||||||
let ret = match fs_impl::freaddir(path, &mut dirs, size, offset, &mut fi) {
|
let ret = match self.fs.freaddir(path, &mut dirs, size, offset, &mut fi) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: readdir file[{}]: {:?}", path, e);
|
println!("Error: readdir file[{}]: {:?}", path, e);
|
||||||
|
@ -294,7 +291,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let request = request.into_inner();
|
let request = request.into_inner();
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let mode = request.mode;
|
let mode = request.mode;
|
||||||
let ret = match fs_impl::fmkdir(&path, mode) {
|
let ret = match self.fs.fmkdir(&path, mode) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: mkdir [{}]: {:?}", path, e);
|
println!("Error: mkdir [{}]: {:?}", path, e);
|
||||||
|
@ -311,7 +308,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let request = request.into_inner();
|
let request = request.into_inner();
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let size = request.size as u64;
|
let size = request.size as u64;
|
||||||
let ret = match fs_impl::ftruncate(path, size) {
|
let ret = match self.fs.ftruncate(path, size) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: truncate file[{}]: {:?}", path, e);
|
println!("Error: truncate file[{}]: {:?}", path, e);
|
||||||
|
@ -330,7 +327,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let a_time = vec![request.ts[0].tv_sec as u64, request.ts[0].tv_nsec as u64];
|
let a_time = vec![request.ts[0].tv_sec as u64, request.ts[0].tv_nsec as u64];
|
||||||
let m_time = vec![request.ts[1].tv_sec as u64, request.ts[1].tv_nsec as u64];
|
let m_time = vec![request.ts[1].tv_sec as u64, request.ts[1].tv_nsec as u64];
|
||||||
let ret = match fs_impl::futimens(path, &a_time, &m_time) {
|
let ret = match self.fs.futimens(path, &a_time, &m_time) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: futimens file[{}]: {:?}", path, e);
|
println!("Error: futimens file[{}]: {:?}", path, e);
|
||||||
|
@ -349,7 +346,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let uid = request.uid as u32;
|
let uid = request.uid as u32;
|
||||||
let gid = request.gid as u32;
|
let gid = request.gid as u32;
|
||||||
let ret = match fs_impl::fchown(path, uid, gid) {
|
let ret = match self.fs.fchown(path, uid, gid) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: chown file[{}]: {:?}", path, e);
|
println!("Error: chown file[{}]: {:?}", path, e);
|
||||||
|
@ -366,8 +363,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let request = request.into_inner();
|
let request = request.into_inner();
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let mut fi = request.fi.unwrap();
|
let mut fi = request.fi.unwrap();
|
||||||
self.file_fds.lock().unwrap().pop(fi.fh);
|
let ret = match self.fs.frelease(path, &mut fi) {
|
||||||
let ret = match fs_impl::frelease(path, &mut fi) {
|
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: release file[{}]: {:?}", path, e);
|
println!("Error: release file[{}]: {:?}", path, e);
|
||||||
|
@ -383,7 +379,7 @@ impl LwsVfs for LwsVfsIns {
|
||||||
async fn frmdir(&self, request: Request<Rmdir>) -> Result<Response<Rmdir>, Status> {
|
async fn frmdir(&self, request: Request<Rmdir>) -> Result<Response<Rmdir>, Status> {
|
||||||
let request = request.into_inner();
|
let request = request.into_inner();
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let ret = match fs_impl::frmdir(path) {
|
let ret = match self.fs.frmdir(path) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: rmdir [{}]: {:?}", path, e);
|
println!("Error: rmdir [{}]: {:?}", path, e);
|
||||||
|
@ -401,6 +397,89 @@ impl LwsVfs for LwsVfsIns {
|
||||||
let request = request.into_inner();
|
let request = request.into_inner();
|
||||||
let path = &self.lpath(&request.path);
|
let path = &self.lpath(&request.path);
|
||||||
let mut fi = request.fi.unwrap();
|
let mut fi = request.fi.unwrap();
|
||||||
self.file_fds.lock().unwrap().pop(fi.fh);
|
let ret = match self.fs.fflush(path, &mut fi) {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error: flush file[{}]: {:?}", path, e);
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let reply = Flush {
|
||||||
|
ret,
|
||||||
|
..Flush::default()
|
||||||
|
};
|
||||||
|
Ok(Response::new(reply))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fcreate(&self, request: Request<Create>) -> Result<Response<Create>, Status> {
|
||||||
|
let request = request.into_inner();
|
||||||
|
let path = &self.lpath(&request.path);
|
||||||
|
let mode = request.mode as u32;
|
||||||
|
let mut fi = request.fi.unwrap();
|
||||||
|
let ret = match self.fs.fcreate(path, mode, &mut fi) {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error: create file[{}]: {:?}", path, e);
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let reply = Create {
|
||||||
|
ret,
|
||||||
|
..Create::default()
|
||||||
|
};
|
||||||
|
Ok(Response::new(reply))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn funlink(&self, request: Request<Unlink>) -> Result<Response<Unlink>, Status> {
|
||||||
|
let request = request.into_inner();
|
||||||
|
let path = &self.lpath(&request.path);
|
||||||
|
let ret = match self.fs.funlink(path) {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error: unlink file[{}]: {:?}", path, e);
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let reply = Unlink {
|
||||||
|
ret,
|
||||||
|
path: request.path,
|
||||||
|
};
|
||||||
|
Ok(Response::new(reply))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fopendir(&self,request: Request<Opendir>) -> Result<Response<Opendir>, Status> {
|
||||||
|
let request = request.into_inner();
|
||||||
|
let path = &self.lpath(&request.path);
|
||||||
|
let mut fi = request.fi.unwrap();
|
||||||
|
let ret = match self.fs.fopendir(path, &mut fi) {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error: opendir file[{}]: {:?}", path, e);
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let reply = Opendir {
|
||||||
|
ret,
|
||||||
|
..Opendir::default()
|
||||||
|
};
|
||||||
|
Ok(Response::new(reply))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn freleasedir(&self, request: Request<Releasedir>) -> Result<Response<Releasedir>, Status> {
|
||||||
|
let request = request.into_inner();
|
||||||
|
let path = &self.lpath(&request.path);
|
||||||
|
let mut fi = request.fi.unwrap();
|
||||||
|
let ret = match self.fs.freleasedir(path, &mut fi) {
|
||||||
|
Ok(ret) => ret,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error: releasedir file[{}]: {:?}", path, e);
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let reply = Releasedir {
|
||||||
|
ret,
|
||||||
|
..Releasedir::default()
|
||||||
|
};
|
||||||
|
Ok(Response::new(reply))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
test/pattern/read.txt
Executable file
2
test/pattern/read.txt
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
1234567
|
||||||
|
abcdefg
|
Loading…
Reference in New Issue
Block a user