diff --git a/rcore-fs-fuse/src/main.rs b/rcore-fs-fuse/src/main.rs index b11f048..fe9f260 100644 --- a/rcore-fs-fuse/src/main.rs +++ b/rcore-fs-fuse/src/main.rs @@ -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 VfsWrapper { 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> { 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 Filesystem for VfsWrapper { 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 Filesystem for VfsWrapper { 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));