From ffa42fcc55c02b5b73757bef1e255199bb4e51a7 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Mon, 4 Mar 2019 16:38:46 +0800 Subject: [PATCH] merge mksfs to fuse binutil --- Cargo.toml | 3 +- rcore-fs-fuse/Cargo.toml | 2 +- rcore-fs-fuse/src/fuse.rs | 222 +++++++++++++++++ rcore-fs-fuse/src/lib.rs | 224 +----------------- rcore-fs-fuse/src/main.rs | 100 ++++++-- .../bin/mksfs.rs => rcore-fs-fuse/src/zip.rs | 48 +--- rcore-fs-sfs/Cargo.toml | 8 - rcore-fs-sfs/src/lib.rs | 1 - sefs-fuse/app/src/main.rs | 74 ++++-- 9 files changed, 376 insertions(+), 306 deletions(-) create mode 100644 rcore-fs-fuse/src/fuse.rs rename rcore-fs-sfs/src/bin/mksfs.rs => rcore-fs-fuse/src/zip.rs (63%) diff --git a/Cargo.toml b/Cargo.toml index f71ba8b..e9c3fe3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ members = [ "rcore-fs-sfs", "rcore-fs-sefs", "rcore-fs-fuse" -] \ No newline at end of file +] +exclude = ["sefs-fuse"] \ No newline at end of file diff --git a/rcore-fs-fuse/Cargo.toml b/rcore-fs-fuse/Cargo.toml index 870fe3f..126c86b 100644 --- a/rcore-fs-fuse/Cargo.toml +++ b/rcore-fs-fuse/Cargo.toml @@ -12,5 +12,5 @@ fuse = "0.3" structopt = "0.2" env_logger = "0.3" rcore-fs = { path = "../rcore-fs", features = ["std"] } -rcore-fs-sfs = { path = "../rcore-fs-sfs", features = ["std"] } +rcore-fs-sfs = { path = "../rcore-fs-sfs" } rcore-fs-sefs = { path = "../rcore-fs-sefs", features = ["std"] } diff --git a/rcore-fs-fuse/src/fuse.rs b/rcore-fs-fuse/src/fuse.rs new file mode 100644 index 0000000..165dfad --- /dev/null +++ b/rcore-fs-fuse/src/fuse.rs @@ -0,0 +1,222 @@ +use fuse::{FileAttr, Filesystem, FileType, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyWrite, ReplyStatfs, Request}; +use rcore_fs::vfs; +use std::collections::btree_map::BTreeMap; +use std::ffi::OsStr; +use std::sync::Arc; +//use log::*; +use time::Timespec; + +const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second + +pub struct VfsFuse { + fs: Arc, + inodes: BTreeMap>, +} + +impl VfsFuse { + pub fn new(fs: Arc) -> Self { + let mut inodes = BTreeMap::new(); + inodes.insert(1, fs.root_inode()); + VfsFuse { fs, inodes } + } + fn trans_time(time: vfs::Timespec) -> Timespec { + Timespec { + sec: time.sec, + nsec: time.nsec, + } + } + fn trans_attr(info: vfs::Metadata) -> FileAttr { + FileAttr { + ino: info.inode as u64, + size: info.size as u64, + blocks: info.blocks as u64, + atime: Self::trans_time(info.atime), + mtime: Self::trans_time(info.mtime), + ctime: Self::trans_time(info.ctime), + crtime: Timespec { sec: 0, nsec: 0 }, + kind: Self::trans_type(info.type_), + perm: info.mode, + nlink: info.nlinks as u32, + uid: info.uid as u32, + gid: info.gid as u32, + rdev: 0, + flags: 0, + } + } + fn trans_type(type_: vfs::FileType) -> FileType { + match type_ { + vfs::FileType::File => FileType::RegularFile, + vfs::FileType::Dir => FileType::Directory, + vfs::FileType::SymLink => FileType::Symlink, + vfs::FileType::CharDevice => FileType::CharDevice, + vfs::FileType::BlockDevice => FileType::BlockDevice, + vfs::FileType::NamedPipe => FileType::NamedPipe, + vfs::FileType::Socket => FileType::Socket, + } + } + 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) + } +} + +/// Helper macro to reply error when VFS operation fails +macro_rules! try_vfs { + ($reply:expr, $expr:expr) => (match $expr { + Ok(val) => val, + Err(err) => { + $reply.error(Self::trans_error(err)); + return; + } + }); +} + +impl Filesystem for VfsFuse { + fn destroy(&mut self, _req: &Request) { + self.inodes.clear(); + self.fs.sync().unwrap(); + } + + fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { + let inode = try_vfs!(reply, self.get_inode(parent)); + let target = try_vfs!(reply, inode.lookup(name.to_str().unwrap())); + let info = try_vfs!(reply, target.metadata()); + self.inodes.insert(info.inode, target); + let attr = Self::trans_attr(info); + reply.entry(&TTL, &attr, 0); + } + + fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) { + let inode = try_vfs!(reply, self.get_inode(ino)); + let info = try_vfs!(reply, inode.metadata()); + let attr = Self::trans_attr(info); + 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(); + let inode = try_vfs!(reply, self.get_inode(parent)); + let target = try_vfs!(reply, inode.create(name, vfs::FileType::File, mode)); + let info = try_vfs!(reply, target.metadata()); + 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(); + let inode = try_vfs!(reply, self.get_inode(parent)); + let target = try_vfs!(reply, inode.create(name, vfs::FileType::Dir, mode)); + let info = try_vfs!(reply, target.metadata()); + 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(); + 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) { + 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(); + 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(); + 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.metadata()); + 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) { + let inode = try_vfs!(reply, self.get_inode(ino)); + let mut data = Vec::::new(); + data.resize(size as usize, 0); + try_vfs!(reply, inode.read_at(offset as usize, data.as_mut_slice())); + reply.data(data.as_slice()); + } + + fn write(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, data: &[u8], _flags: u32, reply: ReplyWrite) { + let inode = try_vfs!(reply, self.get_inode(ino)); + let info = try_vfs!(reply, inode.metadata()); + let end = offset as usize + data.len(); + if end > info.size { + try_vfs!(reply, inode.resize(end)); + } + 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) { + 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) { + 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) { + let inode = try_vfs!(reply, self.get_inode(ino)); + let info = try_vfs!(reply, inode.metadata()); + let count = info.size; + for i in offset as usize..count { + let name = inode.get_entry(i).unwrap(); + let inode = try_vfs!(reply, inode.find(name.as_str())); + let info = try_vfs!(reply, inode.metadata()); + let kind = Self::trans_type(info.type_); + let full = reply.add(info.inode as u64, i as i64 + 1, kind, name); + if full { + break; + } + } + reply.ok(); + } + + fn statfs(&mut self, _req: &Request, _ino: u64, reply: ReplyStatfs) { + let info = self.fs.info(); + reply.statfs(info.blocks as u64, info.bfree as u64, info.bavail as u64, + info.files as u64, info.ffree as u64, info.bsize as u32, + info.namemax as u32, info.frsize as u32); + } +} diff --git a/rcore-fs-fuse/src/lib.rs b/rcore-fs-fuse/src/lib.rs index b7f1a0f..90511ac 100644 --- a/rcore-fs-fuse/src/lib.rs +++ b/rcore-fs-fuse/src/lib.rs @@ -1,222 +1,2 @@ -use fuse::{FileAttr, Filesystem, FileType, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyWrite, ReplyStatfs, Request}; -use rcore_fs::vfs; -use std::collections::btree_map::BTreeMap; -use std::ffi::OsStr; -use std::sync::Arc; -//use log::*; -use time::Timespec; - -const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second - -pub struct VfsFuse { - fs: Arc, - inodes: BTreeMap>, -} - -impl VfsFuse { - pub fn new(fs: Arc) -> Self { - let mut inodes = BTreeMap::new(); - inodes.insert(1, fs.root_inode()); - VfsFuse { fs, inodes } - } - fn trans_time(time: vfs::Timespec) -> Timespec { - Timespec { - sec: time.sec, - nsec: time.nsec, - } - } - fn trans_attr(info: vfs::Metadata) -> FileAttr { - FileAttr { - ino: info.inode as u64, - size: info.size as u64, - blocks: info.blocks as u64, - atime: Self::trans_time(info.atime), - mtime: Self::trans_time(info.mtime), - ctime: Self::trans_time(info.ctime), - crtime: Timespec { sec: 0, nsec: 0 }, - kind: Self::trans_type(info.type_), - perm: info.mode, - nlink: info.nlinks as u32, - uid: info.uid as u32, - gid: info.gid as u32, - rdev: 0, - flags: 0, - } - } - fn trans_type(type_: vfs::FileType) -> FileType { - match type_ { - vfs::FileType::File => FileType::RegularFile, - vfs::FileType::Dir => FileType::Directory, - vfs::FileType::SymLink => FileType::Symlink, - vfs::FileType::CharDevice => FileType::CharDevice, - vfs::FileType::BlockDevice => FileType::BlockDevice, - vfs::FileType::NamedPipe => FileType::NamedPipe, - vfs::FileType::Socket => FileType::Socket, - } - } - 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) - } -} - -/// Helper macro to reply error when VFS operation fails -macro_rules! try_vfs { - ($reply:expr, $expr:expr) => (match $expr { - Ok(val) => val, - Err(err) => { - $reply.error(Self::trans_error(err)); - return; - } - }); -} - -impl Filesystem for VfsFuse { - fn destroy(&mut self, _req: &Request) { - self.inodes.clear(); - self.fs.sync().unwrap(); - } - - fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { - let inode = try_vfs!(reply, self.get_inode(parent)); - let target = try_vfs!(reply, inode.lookup(name.to_str().unwrap())); - let info = try_vfs!(reply, target.metadata()); - self.inodes.insert(info.inode, target); - let attr = Self::trans_attr(info); - reply.entry(&TTL, &attr, 0); - } - - fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) { - let inode = try_vfs!(reply, self.get_inode(ino)); - let info = try_vfs!(reply, inode.metadata()); - let attr = Self::trans_attr(info); - 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(); - let inode = try_vfs!(reply, self.get_inode(parent)); - let target = try_vfs!(reply, inode.create(name, vfs::FileType::File, mode)); - let info = try_vfs!(reply, target.metadata()); - 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(); - let inode = try_vfs!(reply, self.get_inode(parent)); - let target = try_vfs!(reply, inode.create(name, vfs::FileType::Dir, mode)); - let info = try_vfs!(reply, target.metadata()); - 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(); - 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) { - 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(); - 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(); - 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.metadata()); - 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) { - let inode = try_vfs!(reply, self.get_inode(ino)); - let mut data = Vec::::new(); - data.resize(size as usize, 0); - try_vfs!(reply, inode.read_at(offset as usize, data.as_mut_slice())); - reply.data(data.as_slice()); - } - - fn write(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, data: &[u8], _flags: u32, reply: ReplyWrite) { - let inode = try_vfs!(reply, self.get_inode(ino)); - let info = try_vfs!(reply, inode.metadata()); - let end = offset as usize + data.len(); - if end > info.size { - try_vfs!(reply, inode.resize(end)); - } - 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) { - 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) { - 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) { - let inode = try_vfs!(reply, self.get_inode(ino)); - let info = try_vfs!(reply, inode.metadata()); - let count = info.size; - for i in offset as usize..count { - let name = inode.get_entry(i).unwrap(); - let inode = try_vfs!(reply, inode.find(name.as_str())); - let info = try_vfs!(reply, inode.metadata()); - let kind = Self::trans_type(info.type_); - let full = reply.add(info.inode as u64, i as i64 + 1, kind, name); - if full { - break; - } - } - reply.ok(); - } - - fn statfs(&mut self, _req: &Request, _ino: u64, reply: ReplyStatfs) { - let info = self.fs.info(); - reply.statfs(info.blocks as u64, info.bfree as u64, info.bavail as u64, - info.files as u64, info.ffree as u64, info.bsize as u32, - info.namemax as u32, info.frsize as u32); - } -} +pub mod fuse; +pub mod zip; \ No newline at end of file diff --git a/rcore-fs-fuse/src/main.rs b/rcore-fs-fuse/src/main.rs index d96dd9d..019139e 100644 --- a/rcore-fs-fuse/src/main.rs +++ b/rcore-fs-fuse/src/main.rs @@ -1,38 +1,104 @@ use std::fs::OpenOptions; use std::path::PathBuf; +use std::sync::{Arc, Mutex}; use structopt::StructOpt; +use rcore_fs::dev::std_impl::StdTimeProvider; +use rcore_fs::vfs::FileSystem; +use rcore_fs_fuse::fuse::VfsFuse; +use rcore_fs_fuse::zip::{unzip_dir, zip_dir}; use rcore_fs_sefs as sefs; use rcore_fs_sfs as sfs; -use rcore_fs_fuse::VfsFuse; -use rcore_fs::dev::std_impl::StdTimeProvider; #[derive(Debug, StructOpt)] struct Opt { + /// Command + #[structopt(subcommand)] + cmd: Cmd, + /// Image file #[structopt(parse(from_os_str))] image: PathBuf, - /// Mount point + + /// Target directory #[structopt(parse(from_os_str))] - mount_point: PathBuf, + dir: PathBuf, + + /// File system: [sfs | sefs] + #[structopt(short = "f", long = "fs", default_value = "sfs")] + fs: String, +} + +#[derive(Debug, StructOpt)] +enum Cmd { + /// Create a new for + #[structopt(name = "zip")] + Zip, + + /// Unzip data from given to + #[structopt(name = "unzip")] + Unzip, + + /// Mount to + #[structopt(name = "mount")] + Mount, } fn main() { env_logger::init().unwrap(); let opt = Opt::from_args(); -// let img = OpenOptions::new().read(true).write(true).open(&opt.image) -// .expect("failed to open image"); - let sfs = if opt.image.is_dir() { - let img = sefs::dev::StdStorage::new(&opt.image); - sefs::SEFS::open(Box::new(img), &StdTimeProvider) - .expect("failed to open sefs") - } else { - std::fs::create_dir_all(&opt.image).unwrap(); - let img = sefs::dev::StdStorage::new(&opt.image); - sefs::SEFS::create(Box::new(img), &StdTimeProvider) - .expect("failed to create sefs") + + // open or create + let create = match opt.cmd { + Cmd::Mount => !opt.image.is_dir() && !opt.image.is_file(), + Cmd::Zip => true, + Cmd::Unzip => false, + }; + + let fs: Arc = match opt.fs.as_str() { + "sfs" => { + let file = OpenOptions::new().read(true).write(true).create(true) + .open(&opt.image) + .expect("failed to open image"); + let device = Mutex::new(file); + const MAX_SPACE: usize = 0x1000 * 0x1000 * 8; // 128MB (4K bitmap) + match create { + true => sfs::SimpleFileSystem::create(Box::new(device), MAX_SPACE), + false => sfs::SimpleFileSystem::open(Box::new(device)) + .expect("failed to open sfs"), + } + } + "sefs" => { + std::fs::create_dir_all(&opt.image).unwrap(); + let device = sefs::dev::StdStorage::new(&opt.image); + match create { + true => { + sefs::SEFS::create(Box::new(device), &StdTimeProvider) + .expect("failed to create sefs") + } + false => { + sefs::SEFS::open(Box::new(device), &StdTimeProvider) + .expect("failed to open sefs") + } + } + } + _ => panic!("unsupported file system"), }; - fuse::mount(VfsFuse::new(sfs), &opt.mount_point, &[]) - .expect("failed to mount fs"); + match opt.cmd { + Cmd::Mount => { + fuse::mount(VfsFuse::new(fs), &opt.dir, &[]) + .expect("failed to mount fs"); + } + Cmd::Zip => { + zip_dir(&opt.dir, fs.root_inode()) + .expect("failed to zip fs"); + } + Cmd::Unzip => { + std::fs::create_dir(&opt.dir) + .expect("failed to create dir"); + unzip_dir(&opt.dir, fs.root_inode()) + .expect("failed to unzip fs"); + } + } } diff --git a/rcore-fs-sfs/src/bin/mksfs.rs b/rcore-fs-fuse/src/zip.rs similarity index 63% rename from rcore-fs-sfs/src/bin/mksfs.rs rename to rcore-fs-fuse/src/zip.rs index 3ad633e..10a3888 100644 --- a/rcore-fs-sfs/src/bin/mksfs.rs +++ b/rcore-fs-fuse/src/zip.rs @@ -1,41 +1,14 @@ -use std::env; use std::fs; -use std::io::{Read, Write, Result}; -use std::path::Path; +use std::io::{Read, Result, Write}; use std::mem::uninitialized; -use std::sync::{Arc, Mutex}; +use std::path::Path; +use std::sync::Arc; use rcore_fs::vfs::*; -use rcore_fs_sfs::SimpleFileSystem; const DEFAULT_MODE: u32 = 0o664; -fn main() -> Result<()> { - let args: Vec<_> = env::args().collect(); - let cmd = &args[1]; - let dir_path = Path::new(&args[2]); - let img_path = Path::new(&args[3]); - match cmd.as_str() { - "zip" => zip(dir_path, img_path), - "unzip" => unzip(dir_path, img_path), - _ => { - println!("USAGE: "); - panic!("Invalid command: {}", cmd); - } - } -} - -fn zip(path: &Path, img_path: &Path) -> Result<()> { - let img = fs::OpenOptions::new().read(true).write(true).create(true).open(img_path)?; - let img = Mutex::new(img); - let sfs = SimpleFileSystem::create(Box::new(img), 0x1000000); - let inode = sfs.root_inode(); - zip_dir(path, inode)?; - sfs.sync().expect("Failed to sync"); - Ok(()) -} - -fn zip_dir(path: &Path, inode: Arc) -> Result<()> { +pub fn zip_dir(path: &Path, inode: Arc) -> Result<()> { let dir = fs::read_dir(path).expect("Failed to open dir"); for entry in dir { let entry = entry?; @@ -62,16 +35,7 @@ fn zip_dir(path: &Path, inode: Arc) -> Result<()> { Ok(()) } -fn unzip(path: &Path, img_path: &Path) -> Result<()> { - let img = fs::File::open(img_path)?; - let img = Mutex::new(img); - let sfs = SimpleFileSystem::open(Box::new(img)).expect("Failed to open sfs"); - let inode = sfs.root_inode(); - fs::create_dir(&path)?; - unzip_dir(path, inode) -} - -fn unzip_dir(path: &Path, inode: Arc) -> Result<()> { +pub fn unzip_dir(path: &Path, inode: Arc) -> Result<()> { let files = inode.list().expect("Failed to list files from INode"); for name in files.iter().skip(2) { let inode = inode.lookup(name.as_str()).expect("Failed to lookup"); @@ -98,4 +62,4 @@ fn unzip_dir(path: &Path, inode: Arc) -> Result<()> { } } Ok(()) -} \ No newline at end of file +} diff --git a/rcore-fs-sfs/Cargo.toml b/rcore-fs-sfs/Cargo.toml index eefe8bf..83f65ae 100644 --- a/rcore-fs-sfs/Cargo.toml +++ b/rcore-fs-sfs/Cargo.toml @@ -4,11 +4,6 @@ version = "0.1.0" authors = ["WangRunji "] edition = "2018" -[[bin]] -name = "mksfs" -path = "src/bin/mksfs.rs" -required-features = ["std"] - [dependencies] rcore-fs = { path = "../rcore-fs" } static_assertions = "0.3" @@ -19,6 +14,3 @@ log = "0.4" version = "0.9" default-features = false features = ["alloc"] - -[features] -std = ["rcore-fs/std"] diff --git a/rcore-fs-sfs/src/lib.rs b/rcore-fs-sfs/src/lib.rs index dcfe424..786ad92 100644 --- a/rcore-fs-sfs/src/lib.rs +++ b/rcore-fs-sfs/src/lib.rs @@ -1,4 +1,3 @@ -#![cfg_attr(not(any(test, feature = "std")), no_std)] #![feature(alloc)] #![feature(const_str_len)] diff --git a/sefs-fuse/app/src/main.rs b/sefs-fuse/app/src/main.rs index a789f8a..a2cede8 100644 --- a/sefs-fuse/app/src/main.rs +++ b/sefs-fuse/app/src/main.rs @@ -30,21 +30,43 @@ use std::path::PathBuf; use structopt::StructOpt; -use rcore_fs_fuse::VfsFuse; +use rcore_fs_fuse::fuse::VfsFuse; +use rcore_fs_fuse::zip::{zip_dir, unzip_dir}; use rcore_fs_sefs as sefs; use rcore_fs::dev::std_impl::StdTimeProvider; +use rcore_fs::vfs::FileSystem; mod sgx_dev; mod enclave; #[derive(Debug, StructOpt)] struct Opt { + /// Command + #[structopt(subcommand)] + cmd: Cmd, + /// Image file #[structopt(parse(from_os_str))] image: PathBuf, - /// Mount point + + /// Target directory #[structopt(parse(from_os_str))] - mount_point: PathBuf, + dir: PathBuf, +} + +#[derive(Debug, StructOpt)] +enum Cmd { + /// Create a new for + #[structopt(name = "zip")] + Zip, + + /// Unzip data from given to + #[structopt(name = "unzip")] + Unzip, + + /// Mount to + #[structopt(name = "mount")] + Mount, } fn main() { @@ -63,16 +85,40 @@ fn main() { }, }; - let sfs = if opt.image.is_dir() { - let img = sgx_dev::SgxStorage::new(enclave.geteid(), &opt.image); - sefs::SEFS::open(Box::new(img), &StdTimeProvider) - .expect("failed to open sefs") - } else { - std::fs::create_dir_all(&opt.image).unwrap(); - let img = sgx_dev::SgxStorage::new(enclave.geteid(), &opt.image); - sefs::SEFS::create(Box::new(img), &StdTimeProvider) - .expect("failed to create sefs") + // open or create + let create = match opt.cmd { + Cmd::Mount => !opt.image.is_dir(), + Cmd::Zip => true, + Cmd::Unzip => false, + }; + + let device = sgx_dev::SgxStorage::new(enclave.geteid(), &opt.image); + let fs = match create { + true => { + std::fs::create_dir(&opt.image) + .expect("failed to create dir for SEFS"); + sefs::SEFS::create(Box::new(device), &StdTimeProvider) + .expect("failed to create sefs") + } + false => { + sefs::SEFS::open(Box::new(device), &StdTimeProvider) + .expect("failed to open sefs") + } }; - fuse::mount(VfsFuse::new(sfs), &opt.mount_point, &[]) - .expect("failed to mount fs"); + match opt.cmd { + Cmd::Mount => { + fuse::mount(VfsFuse::new(fs), &opt.dir, &[]) + .expect("failed to mount fs"); + } + Cmd::Zip => { + zip_dir(&opt.dir, fs.root_inode()) + .expect("failed to zip fs"); + } + Cmd::Unzip => { + std::fs::create_dir(&opt.dir) + .expect("failed to create dir"); + unzip_dir(&opt.dir, fs.root_inode()) + .expect("failed to unzip fs"); + } + } }