From 50cb21b9e5dac76c207f807a05db7f91ddd0ad1a Mon Sep 17 00:00:00 2001 From: Alexander Date: Fri, 19 Jun 2026 18:45:08 +0200 Subject: [PATCH] Implement read and stat for dir --- Cargo.lock | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 3 ++ src/main.rs | 89 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 198 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7be432e..ea4134f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,15 @@ version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -26,6 +35,35 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "ctrlc" +version = "3.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" +dependencies = [ + "dispatch2", + "nix 0.31.3", + "windows-sys", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags", + "block2", + "libc", + "objc2", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -42,7 +80,7 @@ dependencies = [ "libc", "log", "memchr", - "nix", + "nix 0.30.1", "num_enum", "page_size", "parking_lot", @@ -108,7 +146,10 @@ dependencies = [ name = "musicfs" version = "0.1.0" dependencies = [ + "ctrlc", "fuser", + "libc", + "time", ] [[package]] @@ -124,6 +165,24 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + [[package]] name = "num_enum" version = "0.7.6" @@ -146,6 +205,21 @@ dependencies = [ "syn", ] +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + [[package]] name = "page_size" version = "0.6.0" @@ -185,6 +259,12 @@ version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -290,6 +370,25 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "time" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -354,6 +453,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "winnow" version = "1.0.3" diff --git a/Cargo.toml b/Cargo.toml index bc2edc1..1b8b6b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] +ctrlc = "3.5.2" fuser = "0.17.0" +libc = "0.2.186" +time = "0.3.49" diff --git a/src/main.rs b/src/main.rs index 71343b3..a6f0b71 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,75 @@ -use fuser::Filesystem; +use fuser::{ + Errno, FileAttr, FileType, Filesystem, INodeNo, ReplyAttr, ReplyData, ReplyDirectory, + ReplyEntry, Request, +}; 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 {} +impl Filesystem for JsonFilesystem { + // For stat function like `stat /path/to/fuse` + fn getattr( + &self, + _req: &Request, + ino: fuser::INodeNo, + fh: Option, + reply: ReplyAttr, + ) { + println!("getattr(ino={})", ino); + + let ts = SystemTime::now(); + let attr = FileAttr { + ino: INodeNo::ROOT, + size: 0, + blocks: 0, + atime: ts, + mtime: ts, + ctime: ts, + crtime: ts, + kind: FileType::Directory, + perm: 0o755, + nlink: 0, + uid: 0, + gid: 0, + rdev: 0, + blksize: 0, + flags: 0, + }; + + let ttl = Duration::new(1, 0); + + if ino == INodeNo::ROOT { + reply.attr(&ttl, &attr); + } else { + reply.error(Errno::ENOSYS); + } + } + + fn readdir( + &self, + _req: &Request, + ino: INodeNo, + fh: fuser::FileHandle, + offset: u64, + mut reply: ReplyDirectory, + ) { + println!("readdir(ino={}, fh={}, offset={})", ino, fh, offset); + + 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("..")); + } + reply.ok(); + } else { + reply.error(Errno::ENOSYS); + } + } +} fn main() { let mountpoint = match env::args().nth(1) { @@ -13,6 +79,23 @@ fn main() { return; } }; + + let running = Arc::new(AtomicBool::new(true)); + let r_clone = running.clone(); + + ctrlc::set_handler(move || { + println!("Ctrl+C received, shutting down"); + r_clone.store(false, Ordering::SeqCst); + }) + .expect("Error setting Ctrl+C handler"); + let cfg = fuser::Config::default(); - let _ = fuser::mount2(JsonFilesystem, &mountpoint, &cfg); + let session = fuser::spawn_mount2(JsonFilesystem, &mountpoint, &cfg); + + while running.load(Ordering::SeqCst) { + std::thread::sleep(Duration::from_millis(100)); + } + + println!("Unmounting"); + drop(session); }