moved FUSE impl into separate file, more work on inodes

This commit is contained in:
Moritz Gmeiner 2025-07-29 20:33:36 +02:00
commit 372aa34022
5 changed files with 686 additions and 540 deletions

View file

@ -1,11 +1,35 @@
use std::cell::{LazyCell, RefCell};
use std::time::SystemTime;
use chrono::{NaiveDateTime, NaiveTime};
use fat_bits::FatFs;
use fat_bits::dir::DirEntry;
use fat_bits::dir::{DirEntry, DirIter};
use fuser::FileAttr;
use rand::{Rng, SeedableRng as _};
#[derive(Debug, Clone, Copy)]
thread_local! {
/// SAFETY
///
/// do not access this directly, only invoke the get_random_u32 function
// static RNG: LazyCell<UnsafeCell<rand::rngs::SmallRng>> = LazyCell::new(|| UnsafeCell::new(rand::rngs::SmallRng::from_os_rng()));
/// performance should not be a bottleneck here, since we only need to occasionally generate u32s to
/// be used as generations in inodes
/// if at some point (contrary to expectations) it should become, can switch it to an UnsafeCell
static RNG: LazyCell<RefCell<rand::rngs::SmallRng>> = LazyCell::new(|| RefCell::new(rand::rngs::SmallRng::from_os_rng()));
}
fn get_random_u32() -> u32 {
// RNG.with(|x| unsafe {
// let rng = &mut (*x.get());
// rng.random::<u32>()
// })
RNG.with(|rng| rng.borrow_mut().random())
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Kind {
File,
Dir,
@ -20,13 +44,15 @@ impl From<Kind> for fuser::FileType {
}
}
const ROOT_INO: u64 = 1;
#[derive(Debug)]
#[allow(dead_code)]
pub struct Inode {
ino: u64,
generation: u32,
size: u64,
// blocks: u64,
block_size: u32,
kind: Kind,
@ -49,6 +75,8 @@ impl Inode {
pub fn new(fat_fs: &FatFs, dir_entry: DirEntry, uid: u32, gid: u32) -> Inode {
assert!(dir_entry.is_file() || dir_entry.is_dir());
let generation = get_random_u32();
let kind = if dir_entry.is_dir() {
Kind::Dir
} else {
@ -69,6 +97,7 @@ impl Inode {
Inode {
ino: dir_entry.first_cluster() as u64,
generation,
size: dir_entry.file_size() as u64,
block_size: fat_fs.bpb().bytes_per_sector() as u32,
kind,
@ -103,4 +132,22 @@ impl Inode {
flags: 0,
}
}
pub fn dir_iter(&self, fat_fs: &FatFs) -> anyhow::Result<impl Iterator<Item = DirEntry>> {
anyhow::ensure!(self.kind == Kind::Dir, "cannot dir_iter on a file");
// TODO: the boxing here is not particularly pretty, but neccessary, since the DirIter for
// the root holds a
if self.ino == ROOT_INO {
// root dir
return Ok(fat_fs.root_dir_iter());
}
let chain_reader = fat_fs.chain_reader(self.first_cluster);
// TODO: get rid of this Box if the boxing is removed from root_dir_iter
Ok(DirIter::new(Box::new(chain_reader)))
}
}