|
|
|
@ -4,11 +4,11 @@ use std::fs::OpenOptions;
|
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
|
|
use fuse::{FileAttr, Filesystem, FileType, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, Request};
|
|
|
|
|
use fuse::{FileAttr, Filesystem, FileType, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyWrite, Request};
|
|
|
|
|
use libc;
|
|
|
|
|
use log::*;
|
|
|
|
|
use structopt::StructOpt;
|
|
|
|
|
use time::Timespec;
|
|
|
|
|
use log::*;
|
|
|
|
|
|
|
|
|
|
use simple_filesystem::{sfs, vfs};
|
|
|
|
|
|
|
|
|
@ -49,6 +49,25 @@ impl<T: vfs::FileSystem> VfsWrapper<T> {
|
|
|
|
|
vfs::FileType::Dir => FileType::Directory,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn trans_error(err: vfs::FsError) -> i32 {
|
|
|
|
|
use vfs::FsError::*;
|
|
|
|
|
use libc::*;
|
|
|
|
|
match err {
|
|
|
|
|
NotSupported => ENOSYS,
|
|
|
|
|
EntryNotFound => ENOENT,
|
|
|
|
|
EntryExist => EEXIST,
|
|
|
|
|
IsDir => EISDIR,
|
|
|
|
|
NotFile => EISDIR,
|
|
|
|
|
NotDir => ENOTDIR,
|
|
|
|
|
NotSameFs => EXDEV,
|
|
|
|
|
InvalidParam => EINVAL,
|
|
|
|
|
NoDeviceSpace => ENOSPC,
|
|
|
|
|
DirRemoved => ENOENT,
|
|
|
|
|
DirNotEmpty => ENOTEMPTY,
|
|
|
|
|
WrongFs => EINVAL,
|
|
|
|
|
_ => EINVAL,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn get_inode(&self, ino: u64) -> vfs::Result<&Arc<vfs::INode>> {
|
|
|
|
|
self.inodes.get(&(ino as usize)).ok_or(vfs::FsError::EntryNotFound)
|
|
|
|
|
}
|
|
|
|
@ -58,11 +77,7 @@ macro_rules! try_vfs {
|
|
|
|
|
($reply:expr, $expr:expr) => (match $expr {
|
|
|
|
|
Ok(val) => val,
|
|
|
|
|
Err(err) => {
|
|
|
|
|
let error_code = match err {
|
|
|
|
|
vfs::FsError::EntryNotFound => libc::ENOENT,
|
|
|
|
|
_ => libc::EINVAL,
|
|
|
|
|
};
|
|
|
|
|
$reply.error(error_code);
|
|
|
|
|
$reply.error(Self::trans_error(err));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
@ -87,6 +102,66 @@ impl<T: vfs::FileSystem> Filesystem for VfsWrapper<T> {
|
|
|
|
|
reply.attr(&TTL, &attr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mknod(&mut self, _req: &Request, parent: u64, name: &OsStr, mode: u32, _rdev: u32, reply: ReplyEntry) {
|
|
|
|
|
let name = name.to_str().unwrap();
|
|
|
|
|
info!("mknod parent={} name={} mode={}", parent, name, mode);
|
|
|
|
|
let inode = try_vfs!(reply, self.get_inode(parent));
|
|
|
|
|
let target = try_vfs!(reply, inode.create(name, vfs::FileType::File));
|
|
|
|
|
let info = try_vfs!(reply, target.info());
|
|
|
|
|
self.inodes.insert(info.inode, target);
|
|
|
|
|
let attr = Self::trans_attr(info);
|
|
|
|
|
reply.entry(&TTL, &attr, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mkdir(&mut self, _req: &Request, parent: u64, name: &OsStr, mode: u32, reply: ReplyEntry) {
|
|
|
|
|
let name = name.to_str().unwrap();
|
|
|
|
|
info!("mkdir parent={} name={} mode={}", parent, name, mode);
|
|
|
|
|
let inode = try_vfs!(reply, self.get_inode(parent));
|
|
|
|
|
let target = try_vfs!(reply, inode.create(name, vfs::FileType::Dir));
|
|
|
|
|
let info = try_vfs!(reply, target.info());
|
|
|
|
|
let attr = Self::trans_attr(info);
|
|
|
|
|
reply.entry(&TTL, &attr, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn unlink(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEmpty) {
|
|
|
|
|
let name = name.to_str().unwrap();
|
|
|
|
|
info!("unlink parent={} name={}", parent, name);
|
|
|
|
|
let parent = try_vfs!(reply, self.get_inode(parent));
|
|
|
|
|
try_vfs!(reply, parent.unlink(name));
|
|
|
|
|
reply.ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn rmdir(&mut self, req: &Request, parent: u64, name: &OsStr, reply: ReplyEmpty) {
|
|
|
|
|
info!("rmdir -> unlink");
|
|
|
|
|
self.unlink(req, parent, name, reply);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn rename(&mut self, _req: &Request, parent: u64, name: &OsStr, newparent: u64, newname: &OsStr, reply: ReplyEmpty) {
|
|
|
|
|
let name = name.to_str().unwrap();
|
|
|
|
|
let newname = newname.to_str().unwrap();
|
|
|
|
|
info!("rename parent={} name={} newparent={} newname={}", parent, name, newparent, newname);
|
|
|
|
|
if parent == newparent {
|
|
|
|
|
let parent = try_vfs!(reply, self.get_inode(parent));
|
|
|
|
|
try_vfs!(reply, parent.rename(name, newname));
|
|
|
|
|
} else {
|
|
|
|
|
let parent = try_vfs!(reply, self.get_inode(parent));
|
|
|
|
|
let newparent = try_vfs!(reply, self.get_inode(newparent));
|
|
|
|
|
try_vfs!(reply, parent.move_(name, newparent, newname));
|
|
|
|
|
}
|
|
|
|
|
reply.ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn link(&mut self, _req: &Request, ino: u64, newparent: u64, newname: &OsStr, reply: ReplyEntry) {
|
|
|
|
|
let newname = newname.to_str().unwrap();
|
|
|
|
|
info!("link ino={} newparent={} newname={}", ino, newparent, newname);
|
|
|
|
|
let inode = try_vfs!(reply, self.get_inode(ino));
|
|
|
|
|
let newparent = try_vfs!(reply, self.get_inode(newparent));
|
|
|
|
|
try_vfs!(reply, newparent.link(newname, inode));
|
|
|
|
|
let info = try_vfs!(reply, inode.info());
|
|
|
|
|
let attr = Self::trans_attr(info);
|
|
|
|
|
reply.entry(&TTL, &attr, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn read(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, size: u32, reply: ReplyData) {
|
|
|
|
|
info!("read ino={} offset={} size={}", ino, offset, size);
|
|
|
|
|
let inode = try_vfs!(reply, self.get_inode(ino));
|
|
|
|
@ -96,6 +171,27 @@ impl<T: vfs::FileSystem> Filesystem for VfsWrapper<T> {
|
|
|
|
|
reply.data(data.as_slice());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn write(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, data: &[u8], flags: u32, reply: ReplyWrite) {
|
|
|
|
|
info!("write ino={} offset={} size={} flags={}", ino, offset, data.len(), flags);
|
|
|
|
|
let inode = try_vfs!(reply, self.get_inode(ino));
|
|
|
|
|
let len = try_vfs!(reply, inode.write_at(offset as usize, data));
|
|
|
|
|
reply.written(len as u32);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn flush(&mut self, _req: &Request, ino: u64, _fh: u64, _lock_owner: u64, reply: ReplyEmpty) {
|
|
|
|
|
info!("flush ino={}", ino);
|
|
|
|
|
let inode = try_vfs!(reply, self.get_inode(ino));
|
|
|
|
|
try_vfs!(reply, inode.sync());
|
|
|
|
|
reply.ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fsync(&mut self, _req: &Request, ino: u64, _fh: u64, _datasync: bool, reply: ReplyEmpty) {
|
|
|
|
|
info!("fsync ino={}", ino);
|
|
|
|
|
let inode = try_vfs!(reply, self.get_inode(ino));
|
|
|
|
|
try_vfs!(reply, inode.sync());
|
|
|
|
|
reply.ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn readdir(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, mut reply: ReplyDirectory) {
|
|
|
|
|
info!("readdir ino={}, offset={}", ino, offset);
|
|
|
|
|
let inode = try_vfs!(reply, self.get_inode(ino));
|
|
|
|
|