feat: add fuser
This commit is contained in:
147
__fs/fuser/src/main.rs
Normal file
147
__fs/fuser/src/main.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
use clap::{crate_version, Arg, Command};
|
||||
use fuser::{
|
||||
FileAttr, FileType, Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry,
|
||||
Request,
|
||||
};
|
||||
use libc::ENOENT;
|
||||
use std::ffi::OsStr;
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
const TTL: Duration = Duration::from_secs(1); // 1 second
|
||||
|
||||
const HELLO_DIR_ATTR: FileAttr = FileAttr {
|
||||
ino: 1,
|
||||
size: 0,
|
||||
blocks: 0,
|
||||
atime: UNIX_EPOCH, // 1970-01-01 00:00:00
|
||||
mtime: UNIX_EPOCH,
|
||||
ctime: UNIX_EPOCH,
|
||||
crtime: UNIX_EPOCH,
|
||||
kind: FileType::Directory,
|
||||
perm: 0o755,
|
||||
nlink: 2,
|
||||
uid: 501,
|
||||
gid: 20,
|
||||
rdev: 0,
|
||||
flags: 0,
|
||||
blksize: 512,
|
||||
};
|
||||
|
||||
const HELLO_TXT_CONTENT: &str = "Hello World!\n";
|
||||
|
||||
const HELLO_TXT_ATTR: FileAttr = FileAttr {
|
||||
ino: 2,
|
||||
size: 13,
|
||||
blocks: 1,
|
||||
atime: UNIX_EPOCH, // 1970-01-01 00:00:00
|
||||
mtime: UNIX_EPOCH,
|
||||
ctime: UNIX_EPOCH,
|
||||
crtime: UNIX_EPOCH,
|
||||
kind: FileType::RegularFile,
|
||||
perm: 0o644,
|
||||
nlink: 1,
|
||||
uid: 501,
|
||||
gid: 20,
|
||||
rdev: 0,
|
||||
flags: 0,
|
||||
blksize: 512,
|
||||
};
|
||||
|
||||
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,
|
||||
_flags: i32,
|
||||
_lock: Option<u64>,
|
||||
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"),
|
||||
];
|
||||
|
||||
for (i, entry) in entries.into_iter().enumerate().skip(offset as usize) {
|
||||
// i + 1 means the index of the next entry
|
||||
if reply.add(entry.0, (i + 1) as i64, entry.1, entry.2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
reply.ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let matches = Command::new("hello")
|
||||
.version(crate_version!())
|
||||
.author("Christopher Berner")
|
||||
.arg(
|
||||
Arg::new("MOUNT_POINT")
|
||||
.required(true)
|
||||
.index(1)
|
||||
.help("Act as a client, and mount FUSE at given path"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("auto_unmount")
|
||||
.long("auto_unmount")
|
||||
.help("Automatically unmount on process exit"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("allow-root")
|
||||
.long("allow-root")
|
||||
.help("Allow root user to access filesystem"),
|
||||
)
|
||||
.get_matches();
|
||||
env_logger::init();
|
||||
let mountpoint = matches.value_of("MOUNT_POINT").unwrap();
|
||||
let mut options = vec![MountOption::RO, MountOption::FSName("hello".to_string())];
|
||||
if matches.is_present("auto_unmount") {
|
||||
options.push(MountOption::AutoUnmount);
|
||||
}
|
||||
if matches.is_present("allow-root") {
|
||||
options.push(MountOption::AllowRoot);
|
||||
}
|
||||
fuser::mount2(HelloFS, mountpoint, &options).unwrap();
|
||||
}
|
||||
Reference in New Issue
Block a user