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
Generated
+35
View File
@@ -106,6 +106,12 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "libc"
version = "0.2.186"
@@ -149,6 +155,7 @@ dependencies = [
"ctrlc",
"fuser",
"libc",
"serde_json",
"time",
]
@@ -333,6 +340,15 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
]
[[package]]
name = "serde_core"
version = "1.0.228"
@@ -353,6 +369,19 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
dependencies = [
"itoa",
"memchr",
"serde",
"serde_core",
"zmij",
]
[[package]]
name = "smallvec"
version = "1.15.2"
@@ -490,3 +519,9 @@ dependencies = [
"quote",
"syn",
]
[[package]]
name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+1
View File
@@ -7,4 +7,5 @@ edition = "2024"
ctrlc = "3.5.2"
fuser = "0.17.0"
libc = "0.2.186"
serde_json = "1.0.150"
time = "0.3.49"
+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));