1extern crate fuse_rs;
2extern crate nix;
3
4use fuse_rs::{
5 fs::{DirEntry, FileInfo, FileStat, OpenFileInfo},
6 Filesystem,
7};
8use nix::{errno::Errno, fcntl::OFlag, sys::stat::SFlag};
9use std::{ffi::OsString, io::Read, path::Path};
10
11static HELLO_WORLD: &str = "Hello World!\n";
12
13struct HelloFS;
14
15impl Filesystem for HelloFS {
16 fn metadata(&self, path: &Path) -> fuse_rs::Result<FileStat> {
17 let mut stat = FileStat::new();
18 match path.to_str().expect("path") {
19 "/" => {
20 stat.st_mode = SFlag::S_IFDIR.bits() | 0o755;
21 stat.st_nlink = 3;
22 }
23 "/hello.txt" => {
24 stat.st_mode = SFlag::S_IFREG.bits() | 0o644;
25 stat.st_nlink = 1;
26 stat.st_size = HELLO_WORLD.len() as _;
27 }
28 _ => return Err(Errno::ENOENT),
29 }
30 Ok(stat)
31 }
32
33 fn read_dir(
34 &mut self,
35 path: &Path,
36 _offset: u64,
37 _file_info: FileInfo,
38 ) -> fuse_rs::Result<Vec<DirEntry>> {
39 if path != Path::new("/") {
40 return Err(Errno::ENOENT);
41 }
42
43 Ok(vec![".", "..", "hello.txt"]
44 .into_iter()
45 .map(|n| DirEntry {
46 name: OsString::from(n),
47 metadata: None,
48 offset: None,
49 })
50 .collect())
51 }
52
53 fn open(&mut self, path: &Path, file_info: &mut OpenFileInfo) -> fuse_rs::Result<()> {
54 if path != Path::new("/hello.txt") {
55 return Err(Errno::ENOENT);
56 }
57
58 if (file_info.flags().unwrap_or(OFlag::empty()) & OFlag::O_ACCMODE) != OFlag::O_RDONLY {
59 return Err(Errno::EACCES);
60 }
61
62 Ok(())
63 }
64
65 fn read(
66 &mut self,
67 path: &Path,
68 buf: &mut [u8],
69 offset: u64,
70 _file_info: FileInfo,
71 ) -> fuse_rs::Result<usize> {
72 if path != Path::new("/hello.txt") {
73 return Err(Errno::ENOENT);
74 }
75
76 let size = HELLO_WORLD.len() as u64;
77 let mut cap = buf.len() as u64;
78 if offset > size as _ {
79 return Ok(0);
80 }
81
82 if offset + cap > size {
83 cap = size - offset;
84 }
85
86 (&HELLO_WORLD.as_bytes()[offset as usize..cap as usize])
87 .read(buf)
88 .map_err(|e| Errno::from_i32(e.raw_os_error().expect("read error")))
89 }
90}
91
92fn main() -> Result<(), fuse_rs::Error> {
93 let opts = vec![
94 OsString::from("-s"),
95 OsString::from("-f"),
96 OsString::from("-d"),
97 OsString::from("-o"),
98 OsString::from("volname=hello_world"),
99 OsString::from("-o"),
100 OsString::from("ro"),
101 ];
102 static mut FS: HelloFS = HelloFS {};
103 unsafe {
104 fuse_rs::mount(
105 std::env::args_os().next().unwrap(),
106 "./hello_fs",
107 &mut FS,
108 opts,
109 )
110 }
111}