diff --git a/examples/hello.rs b/examples/hello.rs index 75d6dcb..0380781 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -7,7 +7,7 @@ use std::env; use std::ffi::OsStr; use libc::ENOENT; use time::Timespec; -use fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyDirectory}; +use fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyDirectory, ReplyWrite, ReplyOpen, ReplyCreate, ReplyEmpty}; const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second @@ -30,8 +30,6 @@ const HELLO_DIR_ATTR: FileAttr = FileAttr { flags: 0, }; -const HELLO_TXT_CONTENT: &'static str = "Hello World!\n"; - const HELLO_TXT_ATTR: FileAttr = FileAttr { ino: 2, size: 13, @@ -49,12 +47,23 @@ const HELLO_TXT_ATTR: FileAttr = FileAttr { flags: 0, }; -struct HelloFS; +struct HelloFS { + hello_txt_content: Vec, +} + +impl HelloFS { + fn hello_txt_attr(&self) -> FileAttr { + let mut attr = HELLO_TXT_ATTR; + attr.size = self.hello_txt_content.len() as u64; + attr + } +} 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); + let attr = self.hello_txt_attr(); + reply.entry(&TTL, &attr, 0); } else { reply.error(ENOENT); } @@ -63,14 +72,45 @@ impl Filesystem for HelloFS { 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), + 2 => reply.attr(&TTL, &self.hello_txt_attr()), + _ => reply.error(ENOENT), + } + } + + fn setattr(&mut self, _req: &Request, ino: u64, _mode: Option, _uid: Option, _gid: Option, _size: Option, _atime: Option, _mtime: Option, _fh: Option, _crtime: Option, _chgtime: Option, _bkuptime: Option, _flags: Option, reply: ReplyAttr) { + match ino { + 1 => reply.attr(&TTL, &HELLO_DIR_ATTR), + 2 => reply.attr(&TTL, &self.hello_txt_attr()), _ => reply.error(ENOENT), } } - fn read(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, _size: u32, reply: ReplyData) { + fn open(&mut self, _req: &Request, ino: u64, flags: u32, reply: ReplyOpen) { + if ino == 2 { + reply.opened(0, flags) + } else { + reply.error(ENOENT); + } + } + + fn read(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, size: u32, reply: ReplyData) { + if ino == 2 { + let offset = offset as usize; + let size = size as usize; + let read_size = size.min(self.hello_txt_content.len() - offset); + reply.data(&self.hello_txt_content.as_slice()[offset .. offset + read_size]); + } else { + reply.error(ENOENT); + } + } + + fn write(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, data: &[u8], _flags: u32, reply: ReplyWrite) { if ino == 2 { - reply.data(&HELLO_TXT_CONTENT.as_bytes()[offset as usize..]); + let offset = offset as usize; + let overwrite_len = data.len().min(self.hello_txt_content.len() - offset); + self.hello_txt_content.as_mut_slice()[offset .. offset + overwrite_len].copy_from_slice(&data[.. overwrite_len]); + self.hello_txt_content.extend_from_slice(&data[overwrite_len ..]); + reply.written(data.len() as u32) } else { reply.error(ENOENT); } @@ -93,5 +133,21 @@ impl Filesystem for HelloFS { fn main() { env_logger::init().unwrap(); let mountpoint = env::args_os().nth(1).unwrap(); - fuse::mount(HelloFS, &mountpoint, &[]).unwrap(); + fuse::mount(HelloFS { hello_txt_content: vec![] }, &mountpoint, &[]).unwrap(); } + +#[test] +fn stale_data_bug() { + use std::io::Read; + use std::io::Write; + let mut file_read = std::fs::File::open("/tmp/mnt/hello.txt").unwrap(); + let mut file_write = std::fs::File::create("/tmp/mnt/hello.txt").unwrap(); + file_write.write_all("Init".as_bytes()).unwrap(); + let mut buffer1 = vec![]; + file_read.read_to_end(&mut buffer1).unwrap(); + println!("buffer1 {:?}", buffer1); + file_write.write_all("Hello World!".as_bytes()).unwrap(); + let mut buffer2 = vec![]; + file_read.read_to_end(&mut buffer2).unwrap(); + println!("buffer2 {:?}", buffer2); +} \ No newline at end of file