Newer
Older
use self::fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyCreate, ReplyDirectory, ReplyEmpty, ReplyStatfs, ReplyWrite};
use self::time::Timespec;
pub use self::fuse::mount;
const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second
const CREATE_TIME: Timespec = Timespec { sec: 0, nsec: 0 };
pub struct Fuse {
pub fs: redoxfs::FileSystem,
fn node_attr(node: &(u64, redoxfs::Node)) -> FileAttr {
FileAttr {
ino: node.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 if node.1.is_symlink() {
FileType::Symlink
} else {
FileType::RegularFile
},
perm: node.1.mode & redoxfs::Node::MODE_PERM,
nlink: 1,
uid: node.1.uid,
gid: node.1.gid,
rdev: 0,
flags: 0,
}
}
impl Filesystem for Fuse {
fn lookup(&mut self, _req: &Request, parent_block: u64, name: &Path, reply: ReplyEntry) {
match self.fs.find_node(name.to_str().unwrap(), parent_block) {
Ok(node) => {
},
Err(err) => {
reply.error(err.errno as i32);
}
}
}
fn getattr(&mut self, _req: &Request, block: u64, reply: ReplyAttr) {
match self.fs.node(block) {
Ok(node) => {
},
Err(err) => {
reply.error(err.errno as i32);
}
}
}
fn setattr(&mut self, _req: &Request, block: u64, mode: Option<u32>,
uid: Option<u32>, gid: Option<u32>, size: Option<u64>,
_atime: Option<Timespec>, _mtime: Option<Timespec>, _fh: Option<u64>,
_crtime: Option<Timespec>, _chgtime: Option<Timespec>, _bkuptime: Option<Timespec>,
_flags: Option<u32>, reply: ReplyAttr) {
if let Some(mode) = mode {
match self.fs.node(block) {
Ok(mut node) => if node.1.mode & redoxfs::Node::MODE_PERM != mode as u16 & redoxfs::Node::MODE_PERM {
// println!("Chmod {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
node.1.mode = (node.1.mode & redoxfs::Node::MODE_TYPE) | (mode as u16 & redoxfs::Node::MODE_PERM);
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
if let Err(err) = self.fs.write_at(node.0, &node.1) {
reply.error(err.errno as i32);
return;
}
},
Err(err) => {
reply.error(err.errno as i32);
return;
}
}
}
if let Some(uid) = uid {
match self.fs.node(block) {
Ok(mut node) => if node.1.uid != uid {
node.1.uid = uid;
if let Err(err) = self.fs.write_at(node.0, &node.1) {
reply.error(err.errno as i32);
return;
}
},
Err(err) => {
reply.error(err.errno as i32);
return;
}
}
}
if let Some(gid) = gid {
match self.fs.node(block) {
Ok(mut node) => if node.1.gid != gid {
node.1.gid = gid;
if let Err(err) = self.fs.write_at(node.0, &node.1) {
reply.error(err.errno as i32);
return;
}
},
Err(err) => {
reply.error(err.errno as i32);
return;
}
}
}
if let Some(size) = size {
if let Err(err) = self.fs.node_set_len(block, size) {
match self.fs.node(block) {
Ok(node) => {
},
Err(err) => {
reply.error(err.errno as i32);
}
}
}
fn read(&mut self, _req: &Request, block: u64, _fh: u64, offset: u64, size: u32, reply: ReplyData) {
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 write(&mut self, _req: &Request, block: u64, _fh: u64, offset: u64, data: &[u8], _flags: u32, reply: ReplyWrite) {
match self.fs.write_node(block, offset, &data) {
Ok(count) => {
reply.written(count as u32);
},
Err(err) => {
reply.error(err.errno as i32);
}
}
}
fn flush(&mut self, _req: &Request, _ino: u64, _fh: u64, _lock_owner: u64, reply: ReplyEmpty) {
reply.ok();
}
fn fsync(&mut self, _req: &Request, _ino: u64, _fh: u64, _datasync: bool, reply: ReplyEmpty) {
reply.ok();
}
fn readdir(&mut self, _req: &Request, parent_block: u64, _fh: u64, offset: u64, mut reply: ReplyDirectory) {
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) => {
reply.error(err.errno as i32);
}
}
}
fn create(&mut self, _req: &Request, parent_block: u64, name: &Path, mode: u32, flags: u32, reply: ReplyCreate) {
match self.fs.create_node(redoxfs::Node::MODE_FILE | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block) {
// println!("Create {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
reply.created(&TTL, &node_attr(&node), 0, 0, flags);
},
Err(error) => {
reply.error(error.errno as i32);
}
}
}
fn mkdir(&mut self, _req: &Request, parent_block: u64, name: &Path, mode: u32, reply: ReplyEntry) {
match self.fs.create_node(redoxfs::Node::MODE_DIR | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block) {
// println!("Mkdir {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
},
Err(error) => {
reply.error(error.errno as i32);
}
}
}
fn rmdir(&mut self, _req: &Request, parent_block: u64, name: &Path, reply: ReplyEmpty) {
match self.fs.remove_node(redoxfs::Node::MODE_DIR, name.to_str().unwrap(), parent_block) {
Ok(()) => {
reply.ok();
},
Err(err) => {
reply.error(err.errno as i32);
}
}
}
fn unlink(&mut self, _req: &Request, parent_block: u64, name: &Path, reply: ReplyEmpty) {
match self.fs.remove_node(redoxfs::Node::MODE_FILE, name.to_str().unwrap(), parent_block) {
Ok(()) => {
reply.ok();
},
Err(err) => {
reply.error(err.errno as i32);
}
}
}
fn statfs(&mut self, _req: &Request, _ino: u64, reply: ReplyStatfs) {
let free = self.fs.header.1.free;
match self.fs.node_len(free) {
Ok(free_size) => {
let bsize = 512;
let blocks = self.fs.header.1.size/bsize;
let bfree = free_size/bsize;
reply.statfs(blocks, bfree, bfree, 0, 0, bsize as u32, 256, 0);
},
Err(err) => {
reply.error(err.errno as i32);
}
}
}
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
fn symlink(&mut self, _req: &Request, parent_block: u64, name: &Path, link: &Path, reply: ReplyEntry) {
match self.fs.create_node(redoxfs::Node::MODE_SYMLINK | 0o777, name.to_str().unwrap(), parent_block) {
Ok(node) => {
match self.fs.write_node(node.0, 0, link.as_os_str().as_bytes()) {
Ok(_count) => {
reply.entry(&TTL, &node_attr(&node), 0);
},
Err(err) => {
reply.error(err.errno as i32);
}
}
},
Err(error) => {
reply.error(error.errno as i32);
}
}
}
fn readlink(&mut self, _req: &Request, ino: u64, reply: ReplyData) {
let mut data = vec![0; 4096];
match self.fs.read_node(ino, 0, &mut data) {
Ok(count) => {
reply.data(&data[..count]);
},
Err(err) => {
reply.error(err.errno as i32);
}
}
}