#[allow(dead_code)]
use std::path::PathBuf;
#[derive(Clone, Debug, PartialEq, Default)]
struct RedgoldFs {
pub root: PathBuf
}
impl RedgoldFs {
pub fn new(root: PathBuf) -> Self {
Self { root }
}
pub fn from_redgold_dir(root: PathBuf) -> Self {
Self { root: root.join("..") }
}
}
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);
const HELLO_DIR_ATTR: FileAttr = FileAttr {
ino: 1,
size: 0,
blocks: 0,
atime: UNIX_EPOCH, 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, 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) {
if reply.add(entry.0, (i + 1) as i64, entry.1, entry.2) {
break;
}
}
reply.ok();
}
}
#[ignore]
#[test]
fn test() {
let home_or_current = dirs::home_dir()
.expect("Unable to find home directory for default data store path as path not specified explicitly");
let redgold_dir = home_or_current.join(".rg");
let rdg_fs = RedgoldFs::from_redgold_dir(redgold_dir);
let mountpoint = rdg_fs.root.to_str().unwrap().to_string();
let mut options = vec![MountOption::RO, MountOption::FSName("hello".to_string())];
options.push(MountOption::AutoUnmount);
fuser::mount2(HelloFS, mountpoint, &options).unwrap();
}