163 lines
5.5 KiB
Rust
163 lines
5.5 KiB
Rust
//#![deny(warnings)]
|
|
|
|
extern crate fuse;
|
|
extern crate redoxfs;
|
|
extern crate system;
|
|
extern crate time;
|
|
|
|
use image::Image;
|
|
use std::env;
|
|
use std::path::Path;
|
|
use time::Timespec;
|
|
use fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyDirectory};
|
|
use system::error::ENOENT;
|
|
|
|
pub mod image;
|
|
|
|
const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second
|
|
|
|
const CREATE_TIME: Timespec = Timespec { sec: 0, nsec: 0 };
|
|
|
|
struct RedoxFS {
|
|
fs: redoxfs::FileSystem,
|
|
}
|
|
|
|
impl Filesystem for RedoxFS {
|
|
fn lookup (&mut self, _req: &Request, ino: u64, name: &Path, reply: ReplyEntry) {
|
|
let parent_block = self.fs.header.0 + ino;
|
|
println!("lookup: {} {:?}", parent_block, name);
|
|
match self.fs.find_node(name.to_str().unwrap(), parent_block) {
|
|
Ok(node) => {
|
|
println!("lookup: {:?}", node);
|
|
reply.entry(&TTL, &FileAttr {
|
|
ino: node.0 - self.fs.header.0,
|
|
size: node.1.extents[0].length,
|
|
blocks: (node.1.extents[0].length + 511)/512,
|
|
atime: CREATE_TIME,
|
|
mtime: CREATE_TIME,
|
|
ctime: CREATE_TIME,
|
|
crtime: CREATE_TIME,
|
|
kind: if node.1.is_dir() {
|
|
FileType::Directory
|
|
} else {
|
|
FileType::RegularFile
|
|
},
|
|
perm: 0o777,
|
|
nlink: 1,
|
|
uid: 0,
|
|
gid: 0,
|
|
rdev: 0,
|
|
flags: 0,
|
|
}, 0)
|
|
},
|
|
Err(err) => {
|
|
println!("lookup: {}", err);
|
|
reply.error(err.errno as i32);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn getattr (&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
|
|
let block = self.fs.header.0 + ino;
|
|
println!("getattr: {}", block);
|
|
match self.fs.node(block) {
|
|
Ok(node) => {
|
|
println!("getattr: {:?}", node);
|
|
reply.attr(&TTL, &FileAttr {
|
|
ino: node.0 - self.fs.header.0,
|
|
size: node.1.extents[0].length,
|
|
blocks: (node.1.extents[0].length + 511)/512,
|
|
atime: CREATE_TIME,
|
|
mtime: CREATE_TIME,
|
|
ctime: CREATE_TIME,
|
|
crtime: CREATE_TIME,
|
|
kind: if node.1.is_dir() {
|
|
FileType::Directory
|
|
} else {
|
|
FileType::RegularFile
|
|
},
|
|
perm: 0o777,
|
|
nlink: 1,
|
|
uid: 0,
|
|
gid: 0,
|
|
rdev: 0,
|
|
flags: 0,
|
|
});
|
|
},
|
|
Err(err) => {
|
|
println!("getattr: {}", err);
|
|
reply.error(err.errno as i32);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn read (&mut self, _req: &Request, ino: u64, _fh: u64, offset: u64, size: u32, reply: ReplyData) {
|
|
let block = self.fs.header.0 + ino;
|
|
println!("read: {} at {}, size {}", block, offset, size);
|
|
let mut data = vec![0; size as usize];
|
|
match self.fs.read_node(block, offset, &mut data) {
|
|
Ok(count) => {
|
|
reply.data(&data[..count]);
|
|
},
|
|
Err(err) => {
|
|
reply.error(err.errno as i32);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn readdir (&mut self, _req: &Request, ino: u64, _fh: u64, offset: u64, mut reply: ReplyDirectory) {
|
|
let parent_block = self.fs.header.0 + ino;
|
|
println!("readdir: {}", parent_block);
|
|
let mut children = Vec::new();
|
|
match self.fs.child_nodes(&mut children, parent_block) {
|
|
Ok(()) => {
|
|
if offset == 0 {
|
|
let mut i = 0;
|
|
reply.add(parent_block - self.fs.header.0, i, FileType::Directory, ".");
|
|
i += 1;
|
|
reply.add(parent_block - self.fs.header.0, i, FileType::Directory, "..");
|
|
i += 1;
|
|
for child in children.iter() {
|
|
reply.add(child.0 - self.fs.header.0, i, if child.1.is_dir() {
|
|
FileType::Directory
|
|
} else {
|
|
FileType::RegularFile
|
|
}, child.1.name().unwrap());
|
|
i += 1;
|
|
}
|
|
}
|
|
reply.ok();
|
|
},
|
|
Err(err) => {
|
|
println!("readdir: {}", err);
|
|
reply.error(err.errno as i32);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main () {
|
|
if let Some(path) = env::args().nth(1) {
|
|
//Open an existing image
|
|
match Image::open(&path) {
|
|
Ok(disk) => match redoxfs::FileSystem::open(Box::new(disk)) {
|
|
Ok(filesystem) => {
|
|
println!("redoxfs: opened filesystem {}", path);
|
|
|
|
if let Some(mountpoint) = env::args_os().nth(2) {
|
|
fuse::mount(RedoxFS {
|
|
fs: filesystem
|
|
}, &mountpoint, &[]);
|
|
} else {
|
|
println!("redoxfs: no mount point provided");
|
|
}
|
|
},
|
|
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
|
|
},
|
|
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
|
|
}
|
|
} else {
|
|
println!("redoxfs: no disk image provided");
|
|
}
|
|
}
|