extern crate env_logger; extern crate fuse; extern crate libc; extern crate time; use std::env; use std::ffi::OsStr; use libc::ENOENT; use time::Timespec; use fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyDirectory}; const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second const CREATE_TIME: Timespec = Timespec { sec: 1381237736, nsec: 0 }; // 2013-10-08 08:56 const HELLO_DIR_ATTR: FileAttr = FileAttr { ino: 1, size: 0, blocks: 0, atime: CREATE_TIME, mtime: CREATE_TIME, ctime: CREATE_TIME, crtime: CREATE_TIME, kind: FileType::Directory, perm: 0o755, nlink: 2, uid: 501, gid: 20, rdev: 0, flags: 0, }; const HELLO_TXT_CONTENT: &'static str = "Hello World!\n"; const HELLO_TXT_ATTR: FileAttr = FileAttr { ino: 2, size: 13, blocks: 1, atime: CREATE_TIME, mtime: CREATE_TIME, ctime: CREATE_TIME, crtime: CREATE_TIME, kind: FileType::RegularFile, perm: 0o644, nlink: 1, uid: 501, gid: 20, rdev: 0, flags: 0, }; struct HelloFS; impl Filesystem for HelloFS { fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { if parent == 1 && name.to_str() == Some("hello.txt") { reply.entry(&TTL, &HELLO_TXT_ATTR, 0); } else { reply.error(ENOENT); } } fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) { match ino { 1 => reply.attr(&TTL, &HELLO_DIR_ATTR), 2 => reply.attr(&TTL, &HELLO_TXT_ATTR), _ => reply.error(ENOENT), } } fn read(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, _size: u32, reply: ReplyData) { if ino == 2 { reply.data(&HELLO_TXT_CONTENT.as_bytes()[offset as usize..]); } else { reply.error(ENOENT); } } fn readdir(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, mut reply: ReplyDirectory) { if ino != 1 { reply.error(ENOENT); return; } let entries = vec![ (1, FileType::Directory, "."), (1, FileType::Directory, ".."), (2, FileType::RegularFile, "hello.txt"), ]; // Offset of 0 means no offset. // Non-zero offset means the passed offset has already been seen, and we should start after // it. let to_skip = if offset == 0 { offset } else { offset + 1 } as usize; for (i, entry) in entries.into_iter().enumerate().skip(to_skip) { reply.add(entry.0, i as i64, entry.1, entry.2); } reply.ok(); } } fn main() { env_logger::init(); let mountpoint = env::args_os().nth(1).unwrap(); let options = ["-o", "ro", "-o", "fsname=hello"] .iter() .map(|o| o.as_ref()) .collect::>(); fuse::mount(HelloFS, mountpoint, &options).unwrap(); }