Added read files + lookup

This commit is contained in:
Alexander
2026-06-19 21:37:32 +02:00
parent 50cb21b9e5
commit 872580602d
3 changed files with 170 additions and 22 deletions
+134 -22
View File
@@ -1,26 +1,24 @@
use fuser::{
Errno, FileAttr, FileType, Filesystem, INodeNo, ReplyAttr, ReplyData, ReplyDirectory,
ReplyEntry, Request,
Errno, FileAttr, FileType, Filesystem, Generation, INodeNo, ReplyAttr, ReplyDirectory, Request,
};
use serde_json::{Map, Value, json};
use std::collections::BTreeMap;
use std::env;
use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{Duration, SystemTime};
struct JsonFilesystem;
impl Filesystem for JsonFilesystem {
// For stat function like `stat /path/to/fuse`
fn getattr(
&self,
_req: &Request,
ino: fuser::INodeNo,
fh: Option<fuser::FileHandle>,
reply: ReplyAttr,
) {
println!("getattr(ino={})", ino);
struct JsonFilesystem {
tree: Map<String, Value>,
attrs: BTreeMap<INodeNo, FileAttr>,
inodes: BTreeMap<String, INodeNo>,
}
impl JsonFilesystem {
fn new(tree: &Map<String, Value>) -> JsonFilesystem {
let mut attrs = BTreeMap::new();
let mut inodes = BTreeMap::new();
let ts = SystemTime::now();
let attr = FileAttr {
ino: INodeNo::ROOT,
@@ -40,13 +38,58 @@ impl Filesystem for JsonFilesystem {
flags: 0,
};
let ttl = Duration::new(1, 0);
attrs.insert(INodeNo(1), attr);
inodes.insert("/".to_string(), INodeNo(1));
if ino == INodeNo::ROOT {
reply.attr(&ttl, &attr);
} else {
reply.error(Errno::ENOSYS);
for (i, (key, value)) in tree.iter().enumerate() {
let attr = FileAttr {
ino: INodeNo(i as u64 + 2),
size: value.to_string().len() as u64,
blocks: 0,
atime: ts,
mtime: ts,
ctime: ts,
crtime: ts,
kind: FileType::RegularFile,
perm: 0o644,
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
blksize: 0,
flags: 0,
};
attrs.insert(attr.ino, attr);
inodes.insert(key.clone(), attr.ino);
}
return JsonFilesystem {
tree: tree.clone(),
attrs: attrs,
inodes: inodes,
};
}
}
impl Filesystem for JsonFilesystem {
// For stat function like `stat /path/to/fuse`
fn getattr(
&self,
_req: &Request,
ino: fuser::INodeNo,
fh: Option<fuser::FileHandle>,
reply: ReplyAttr,
) {
println!("getattr(ino={})", ino);
match self.attrs.get(&ino) {
Some(attr) => {
let ttl = Duration::new(1, 0);
reply.attr(&ttl, attr);
}
None => reply.error(Errno::ENOENT),
};
}
fn readdir(
@@ -61,17 +104,86 @@ impl Filesystem for JsonFilesystem {
if ino == INodeNo::ROOT {
if offset == 0 {
reply.add(INodeNo::ROOT, 0, FileType::Directory, &Path::new("."));
reply.add(INodeNo::ROOT, 1, FileType::Directory, &Path::new(".."));
let _ = reply.add(INodeNo::ROOT, 0, FileType::Directory, &Path::new("."));
let _ = reply.add(INodeNo::ROOT, 1, FileType::Directory, &Path::new(".."));
for (i, key) in self.tree.keys().enumerate() {
let inode: u64 = 2 + i as u64;
let offset: u64 = 2 + i as u64;
let _ = reply.add(
INodeNo(inode),
offset,
FileType::RegularFile,
&Path::new(key),
);
}
}
reply.ok();
} else {
reply.error(Errno::ENOSYS);
}
}
fn lookup(
&self,
_req: &Request,
parent: INodeNo,
name: &std::ffi::OsStr,
reply: fuser::ReplyEntry,
) {
println!("lookup(parent={}, name={})", parent, name.display());
let inode = match self.inodes.get(name.to_str().unwrap()) {
Some(inode) => inode,
None => {
reply.error(Errno::ENOENT);
return;
}
};
match self.attrs.get(inode) {
Some(attr) => {
let ttl = Duration::new(1, 0);
reply.entry(&ttl, attr, Generation(0));
}
None => reply.error(Errno::ENOENT),
};
}
fn read(
&self,
_req: &Request,
ino: INodeNo,
fh: fuser::FileHandle,
offset: u64,
size: u32,
flags: fuser::OpenFlags,
lock_owner: Option<fuser::LockOwner>,
reply: fuser::ReplyData,
) {
println!(
"read(ino={}, fh={}, offset={}, size={})",
ino, fh, offset, size
);
for (key, &inode) in self.inodes.iter() {
if inode == ino {
let value = self.tree.get(key).unwrap();
reply.data(value.to_string().as_bytes());
return;
}
}
reply.error(Errno::ENOENT);
}
}
fn main() {
let data = json!({
"foo": "bar",
"answer": 42,
});
let tree = data.as_object().unwrap();
let fs = JsonFilesystem::new(tree);
let mountpoint = match env::args().nth(1) {
Some(path) => path,
None => {
@@ -90,7 +202,7 @@ fn main() {
.expect("Error setting Ctrl+C handler");
let cfg = fuser::Config::default();
let session = fuser::spawn_mount2(JsonFilesystem, &mountpoint, &cfg);
let session = fuser::spawn_mount2(fs, &mountpoint, &cfg);
while running.load(Ordering::SeqCst) {
std::thread::sleep(Duration::from_millis(100));