Created
October 6, 2018 17:43
-
-
Save jmillikin/827bc1c174f3444f33ff70933d4db16a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::ffi::CString; | |
use std::io; | |
use std::time::Duration; | |
extern crate fuse; | |
use fuse::fs::{NodeId, Request}; | |
use fuse::Respond; | |
struct MyFS {} | |
impl fuse::fs::Filesystem for MyFS { | |
fn mount_name(&self) -> String { | |
"hello-world".to_string() | |
} | |
fn mount_type(&self) -> String { | |
"hello-world".to_string() | |
} | |
fn init(&mut self, request: &fuse::fs::InitRequest) -> io::Result<fuse::fs::InitResponse> { | |
let mut resp = request.new_response(); | |
//let mut flags = resp.flags(); | |
//flags.set(fuse::fs::InitFlag::READDIRPLUS, false); | |
//resp.set_flags(flags); | |
resp.set_max_write(131072); | |
resp.set_time_gran(1); | |
Ok(resp) | |
} | |
fn lookup( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::LookupRequest, | |
) -> Respond<fuse::fs::LookupResponse> { | |
let mut resp = request.new_response(); | |
resp.set_cache_duration(Duration::new(1, 0)); | |
if request.name().to_bytes() == b"foobar" { | |
resp.set_node_id(123, 1); | |
resp.mut_attr().set_mode(0x8000 /* S_IFREG */ | 0o755); | |
} else if request.name().to_bytes() == b"foobar.dir" { | |
resp.set_node_id(124, 1); | |
resp.mut_attr().set_mode(0x4000 /* S_IFDIR */ | 0o755); | |
} else if request.name().to_bytes() == b"foobar.fifo" { | |
resp.set_node_id(125, 1); | |
resp.mut_attr().set_mode(0x1000 /* S_IFIFO */ | 0o755); | |
} else if request.name().to_bytes() == b"foobar.chr" { | |
resp.set_node_id(126, 1); | |
resp.mut_attr().set_mode(0x2000 /* S_IFCHR */ | 0o755); | |
} else { | |
return ctx.respond_err(io::Error::from_raw_os_error(2 /* ENOENT */)); | |
} | |
resp.mut_attr().set_size(13); | |
resp.mut_attr().set_nlink(1); | |
ctx.respond_ok(resp) | |
} | |
fn getattr( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::GetattrRequest, | |
) -> Respond<fuse::fs::GetattrResponse> { | |
let mut resp = request.new_response(); | |
resp.set_cache_duration(Duration::new(1, 0)); | |
let attr = resp.mut_attr(); | |
if request.node_id() == 1 { | |
attr.set_user_id(1000); | |
attr.set_group_id(1000); | |
attr.set_mode(0x4000 /* S_IFDIR */ | 0o755); | |
attr.set_nlink(2); | |
} else if request.node_id() == 123 { | |
attr.set_user_id(1000); | |
attr.set_group_id(1000); | |
attr.set_mode(0x8000 /* S_IFREG */ | 0o755); | |
attr.set_size(b"Hello world!\n".len() as u64); | |
attr.set_nlink(2); | |
} else if request.node_id() == 124 { | |
attr.set_user_id(1000); | |
attr.set_group_id(1000); | |
attr.set_mode(0x4000 /* S_IFDIR */ | 0o755); | |
attr.set_nlink(2); | |
} else if request.node_id() == 125 { | |
attr.set_user_id(1000); | |
attr.set_group_id(1000); | |
attr.set_mode(0x1000 /* S_IFIFO */ | 0o755); | |
attr.set_nlink(2); | |
} else if request.node_id() == 126 { | |
attr.set_user_id(1000); | |
attr.set_group_id(1000); | |
attr.set_mode(0x2000 /* S_IFCHR */ | 0o755); | |
attr.set_nlink(2); | |
} else { | |
return ctx.respond_err(io::Error::from_raw_os_error(2 /* ENOENT */)); | |
} | |
ctx.respond_ok(resp) | |
} | |
fn open( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::OpenRequest, | |
) -> Respond<fuse::fs::OpenResponse> { | |
let mut resp = request.new_response(); | |
resp.set_handle(1234); | |
ctx.respond_ok(resp) | |
} | |
fn read( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::ReadRequest, | |
) -> Respond<fuse::fs::ReadResponse> { | |
if request.handle() != 1234 { | |
return ctx.respond_err(io::Error::from_raw_os_error(5 /* EIO */)); | |
} | |
let mut resp = request.new_response(); | |
let mut value = Vec::new(); | |
value.extend_from_slice(b"Hello world!\n"); | |
resp.set_value(&value).unwrap(); | |
ctx.respond_ok(resp) | |
} | |
fn write( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::WriteRequest, | |
) -> Respond<fuse::fs::WriteResponse> { | |
if request.handle() != 1234 { | |
return ctx.respond_err(io::Error::from_raw_os_error(5 /* EIO */)); | |
} | |
let mut resp = request.new_response(); | |
resp.set_size(request.value().len() as u32); | |
ctx.respond_ok(resp) | |
} | |
fn opendir( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::OpendirRequest, | |
) -> Respond<fuse::fs::OpendirResponse> { | |
let mut resp = request.new_response(); | |
resp.set_handle(12345); | |
ctx.respond_ok(resp) | |
} | |
fn readdir( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::ReaddirRequest, | |
) -> Respond<fuse::fs::ReaddirResponse> { | |
let mut resp = request.new_response(); | |
if request.offset() != 0 { | |
return ctx.respond_ok(resp); | |
} | |
{ | |
let name = CString::new("foobar").unwrap(); | |
let mut dirent = resp.push(NodeId::new(123).unwrap(), 1, &name).unwrap(); | |
dirent.set_node_kind(fuse::fs::NodeKind::REG); | |
if let Some(node) = dirent.mut_node() { | |
node.mut_attr().set_size(13); | |
node.mut_attr().set_nlink(1); | |
} | |
} | |
{ | |
let name = CString::new("foobar.dir").unwrap(); | |
let mut dirent = resp.push(NodeId::new(124).unwrap(), 2, &name).unwrap(); | |
dirent.set_node_kind(fuse::fs::NodeKind::DIR); | |
} | |
{ | |
let name = CString::new("foobar.fifo").unwrap(); | |
let mut dirent = resp.push(NodeId::new(125).unwrap(), 3, &name).unwrap(); | |
dirent.set_node_kind(fuse::fs::NodeKind::FIFO); | |
} | |
{ | |
let name = CString::new("foobar.chr").unwrap(); | |
let mut dirent = resp.push(NodeId::new(126).unwrap(), 4, &name).unwrap(); | |
dirent.set_node_kind(fuse::fs::NodeKind::CHR); | |
println!("dirent:\n{:?}", dirent); | |
} | |
ctx.respond_ok(resp) | |
} | |
fn releasedir( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::ReleasedirRequest, | |
) -> Respond<fuse::fs::ReleasedirResponse> { | |
let resp = request.new_response(); | |
ctx.respond_ok(resp) | |
} | |
fn statfs( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::StatfsRequest, | |
) -> Respond<fuse::fs::StatfsResponse> { | |
let resp = request.new_response(); | |
ctx.respond_ok(resp) | |
} | |
fn listxattr( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::ListxattrRequest, | |
) -> Respond<fuse::fs::ListxattrResponse> { | |
let mut resp = request.new_response(); | |
resp.push(&CString::new("SOME_TEST_XATTR").unwrap()) | |
.unwrap(); | |
resp.push(&CString::new("ANOTHER.TEST.ATTR").unwrap()) | |
.unwrap(); | |
ctx.respond_ok(resp) | |
} | |
fn getxattr( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::GetxattrRequest, | |
) -> Respond<fuse::fs::GetxattrResponse> { | |
let mut resp = request.new_response(); | |
if request.name().to_bytes() == b"SOME_TEST_XATTR" { | |
resp.set_value(&[72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]) | |
.unwrap(); | |
return ctx.respond_ok(resp); | |
} | |
if request.name().to_bytes() == b"ANOTHER.TEST.ATTR" { | |
resp.set_value(&[1, 2, 3, 0, 4, 5, 6]).unwrap(); | |
return ctx.respond_ok(resp); | |
} | |
return ctx.respond_err(io::Error::from_raw_os_error(61 /* ENODATA */)); | |
} | |
fn setxattr( | |
&self, | |
ctx: fuse::ServerContext, | |
request: &fuse::fs::SetxattrRequest, | |
) -> Respond<fuse::fs::SetxattrResponse> { | |
let resp = request.new_response(); | |
ctx.respond_ok(resp) | |
} | |
} | |
fn main() { | |
let fs = MyFS {}; | |
let mountpoint = std::env::args_os().nth(1).unwrap(); | |
let mut vol = fuse::mount(fs, mountpoint).unwrap(); | |
vol.run().unwrap(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment