Added read files + lookup
This commit is contained in:
Generated
+35
@@ -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"
|
||||
|
||||
@@ -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
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user