diff --git a/Cargo.lock b/Cargo.lock index a9c6e8a..b60f235 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,16 +168,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "ctrlc" -version = "3.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73" -dependencies = [ - "nix 0.30.1", - "windows-sys", -] - [[package]] name = "enum_dispatch" version = "0.3.13" @@ -253,7 +243,6 @@ name = "fat-mount" version = "0.1.0" dependencies = [ "anyhow", - "ctrlc", "env_logger", "fat-fuse", "fuser", @@ -268,7 +257,7 @@ dependencies = [ "libc", "log", "memchr", - "nix 0.29.0", + "nix", "page_size", "pkg-config", "smallvec", @@ -387,18 +376,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "num-traits" version = "0.2.19" diff --git a/fat-bits/src/bpb.rs b/fat-bits/src/bpb.rs index 362346c..26e4223 100644 --- a/fat-bits/src/bpb.rs +++ b/fat-bits/src/bpb.rs @@ -236,7 +236,6 @@ impl Bpb { if self.fat_type() == FatType::Fat32 { return None; } - Some(self.fat_offset() + self.sector_to_offset(self.num_fats() as u32 * self.fat_size())) } diff --git a/fat-bits/src/lib.rs b/fat-bits/src/lib.rs index bd50960..f17275c 100644 --- a/fat-bits/src/lib.rs +++ b/fat-bits/src/lib.rs @@ -98,15 +98,8 @@ pub struct FatFs { fat: fat::Fat, } -unsafe impl Send for FatFs {} - impl FatFs { - pub fn load(data: S) -> anyhow::Result - where - S: SliceLike + Send + 'static, - { - let data = Rc::new(RefCell::new(data)); - + pub fn load(data: Rc>) -> anyhow::Result { let mut bpb_bytes = [0; 512]; data.borrow_mut().read_at_offset(0, &mut bpb_bytes)?; @@ -185,28 +178,12 @@ impl FatFs { } pub fn cluster_as_subslice_mut(&mut self, cluster: u32) -> SubSliceMut<'_> { - if cluster == 0 { - // for cluster 0 simply return empty subslice - // this makes things a bit easier, since cluster 0 is used as a marker that a file/dir - // is empty - - SubSliceMut::new(self, 0, 0); - } - let offset = self.data_cluster_to_offset(cluster); SubSliceMut::new(self, offset, self.bytes_per_cluster) } pub fn cluster_as_subslice(&self, cluster: u32) -> SubSlice<'_> { - if cluster == 0 { - // for cluster 0 simply return empty subslice - // this makes things a bit easier, since cluster 0 is used as a marker that a file/dir - // is empty - - SubSlice::new(self, 0, 0); - } - let offset = self.data_cluster_to_offset(cluster); SubSlice::new(self, offset, self.bytes_per_cluster) diff --git a/fat-dump/src/main.rs b/fat-dump/src/main.rs index 39e16ff..2ddc569 100644 --- a/fat-dump/src/main.rs +++ b/fat-dump/src/main.rs @@ -22,7 +22,7 @@ pub fn main() -> anyhow::Result<()> { // println!("{}", bpb); - let fat_fs = FatFs::load(file)?; + let fat_fs = FatFs::load(Rc::new(RefCell::new(file)))?; println!("{}", fat_fs.bpb()); println!(); diff --git a/fat-fuse/src/fuse.rs b/fat-fuse/src/fuse.rs index b037ea2..512b99d 100644 --- a/fat-fuse/src/fuse.rs +++ b/fat-fuse/src/fuse.rs @@ -2,15 +2,13 @@ use std::ffi::c_int; use std::time::Duration; use fat_bits::dir::DirEntry; -use fuser::{FileType, Filesystem}; -use libc::{EINVAL, EIO, ENOENT, ENOSYS, ENOTDIR, EPERM}; +use fuser::Filesystem; +use libc::{EIO, ENOENT, ENOSYS, EPERM}; use log::{debug, warn}; use crate::FatFuse; use crate::inode::Inode; -const TTL: Duration = Duration::from_secs(1); - impl Filesystem for FatFuse { fn init( &mut self, @@ -34,18 +32,14 @@ impl Filesystem for FatFuse { let Some(name) = name.to_str() else { // TODO: add proper handling of non-utf8 strings - debug!("cannot convert OsStr {:?} to str", name); reply.error(ENOSYS); return; }; - debug!("looking up file {} with parent ino {}", name, parent); - let Some(parent_inode) = self.get_inode(parent) else { // parent inode does not exist // TODO: how can we make sure this does not happed? // TODO: panic? - debug!("could not find inode for parent ino {}", parent); reply.error(EIO); return; @@ -73,33 +67,29 @@ impl Filesystem for FatFuse { }) { Ok(dir_entry) => dir_entry, Err(err) => { - debug!("error: {}", err); reply.error(err); return; } }; - // let inode = match self.get_inode_by_first_cluster(dir_entry.first_cluster()) { - // Some(inode) => inode, - // None => { - // // no inode found, make a new one - // let ino = self.next_ino(); + let inode = match self.get_inode_by_first_cluster(dir_entry.first_cluster()) { + Some(inode) => inode, + None => { + // no inode found, make a new one - // let inode = Inode::new(&self.fat_fs, &dir_entry, ino, self.uid, self.gid); + let ino = self.next_ino(); - // self.insert_inode(inode) - // } - // }; + let inode = Inode::new(&self.fat_fs, dir_entry, ino, self.uid, self.gid); - let inode = self.get_or_make_inode_by_dir_entry(&dir_entry); + self.insert_inode(inode) + } + }; let attr = inode.file_attr(); let generation = inode.generation(); - reply.entry(&TTL, &attr, generation as u64); - - inode.refcount_inc(); + reply.entry(&Duration::from_secs(1), &attr, generation as u64); } fn forget(&mut self, _req: &fuser::Request<'_>, ino: u64, nlookup: u64) { @@ -109,9 +99,18 @@ impl Filesystem for FatFuse { return; }; - // *ref_count = ref_count.saturating_sub(nlookup); + let ref_count = inode.ref_count_mut(); - if inode.refcount_dec(nlookup) == 0 { + if *ref_count < nlookup { + debug!( + "tried to forget {} refs of inode {}, but ref_count is only {}", + nlookup, ino, *ref_count + ); + } + + *ref_count = ref_count.saturating_sub(nlookup); + + if *ref_count == 0 { // no more references, drop inode self.drop_inode(ino); } @@ -124,28 +123,8 @@ impl Filesystem for FatFuse { fh: Option, reply: fuser::ReplyAttr, ) { - // warn!("[Not Implemented] getattr(ino: {:#x?}, fh: {:#x?})", ino, fh); - // reply.error(ENOSYS); - - let inode = if let Some(fh) = fh { - let Some(inode) = self.get_inode_by_fh(fh) else { - reply.error(EIO); - - return; - }; - - inode - } else if let Some(inode) = self.get_inode(ino) { - inode - } else { - reply.error(EIO); - - return; - }; - - let attr = inode.file_attr(); - - reply.attr(&TTL, &attr); + warn!("[Not Implemented] getattr(ino: {:#x?}, fh: {:#x?})", ino, fh); + reply.error(ENOSYS); } fn setattr( @@ -235,6 +214,21 @@ impl Filesystem for FatFuse { reply.error(ENOSYS); } + fn symlink( + &mut self, + _req: &fuser::Request<'_>, + parent: u64, + link_name: &std::ffi::OsStr, + target: &std::path::Path, + reply: fuser::ReplyEntry, + ) { + debug!( + "[Not Implemented] symlink(parent: {:#x?}, link_name: {:?}, target: {:?})", + parent, link_name, target, + ); + reply.error(EPERM); + } + fn rename( &mut self, _req: &fuser::Request<'_>, @@ -253,19 +247,23 @@ impl Filesystem for FatFuse { reply.error(ENOSYS); } - fn open(&mut self, _req: &fuser::Request<'_>, ino: u64, _flags: i32, reply: fuser::ReplyOpen) { - if !self.inode_table.contains_key(&ino) { - reply.error(EINVAL); - return; - } + fn link( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + newparent: u64, + newname: &std::ffi::OsStr, + reply: fuser::ReplyEntry, + ) { + debug!( + "[Not Implemented] link(ino: {:#x?}, newparent: {:#x?}, newname: {:?})", + ino, newparent, newname + ); + reply.error(EPERM); + } - let fh = self.next_fh(); - - if let Some(old_ino) = self.ino_by_fh.insert(fh, ino) { - debug!("fh {} was associated with ino {}, now with ino {}", fh, old_ino, ino); - } - - reply.opened(fh, 0); + fn open(&mut self, _req: &fuser::Request<'_>, _ino: u64, _flags: i32, reply: fuser::ReplyOpen) { + reply.opened(0, 0); } fn read( @@ -356,17 +354,11 @@ impl Filesystem for FatFuse { fn opendir( &mut self, _req: &fuser::Request<'_>, - ino: u64, + _ino: u64, _flags: i32, reply: fuser::ReplyOpen, ) { - let fh = self.next_fh(); - - if let Some(old_ino) = self.ino_by_fh.insert(fh, ino) { - debug!("fh {} was already associated with ino {}, now with ino {}", fh, old_ino, ino); - } - - reply.opened(fh, 0); + reply.opened(0, 0); } fn readdir( @@ -375,79 +367,10 @@ impl Filesystem for FatFuse { ino: u64, fh: u64, offset: i64, - mut reply: fuser::ReplyDirectory, + reply: fuser::ReplyDirectory, ) { - let Ok(mut offset): Result = offset.try_into() else { - return; - }; - - let Some(inode) = self.get_inode_by_fh(fh) else { - debug!("could not find inode accociated with fh {} (ino: {})", fh, ino); - - reply.error(EINVAL); - return; - }; - - if inode.ino() != ino { - debug!( - "ino {} of inode associated with fh {} does not match given ino {}", - inode.ino(), - fh, - ino - ); - - reply.error(EINVAL); - return; - } - - let mut _next_idx = 1; - let mut next_offset = || { - let next_idx = _next_idx; - _next_idx += 1; - next_idx - }; - - if inode.is_root() { - if offset == 0 { - debug!("adding . to root dir"); - if reply.add(1, next_offset(), FileType::Directory, ".") { - return; - } - } else { - offset -= 1; - } - - if offset == 0 { - debug!("adding .. to root dir"); - if reply.add(1, next_offset(), FileType::Directory, "..") { - return; - } - } else { - offset -= 1; - } - } - - let Ok(dir_iter) = inode.dir_iter(&self.fat_fs) else { - reply.error(ENOTDIR); - return; - }; - - // need to drop dir_iter here so we can borrow self mut again - // also skip over `offset` entries - let dirs: Vec = dir_iter.skip(offset).collect(); - - for dir_entry in dirs { - let name = dir_entry.name_string().unwrap_or("".into()); - - let inode: &Inode = self.get_or_make_inode_by_dir_entry(&dir_entry); - - debug!("adding entry {} (ino: {})", name, inode.ino()); - if reply.add(ino, next_offset(), inode.kind().into(), name) { - return; - } - } - - reply.ok(); + warn!("[Not Implemented] readdir(ino: {:#x?}, fh: {}, offset: {})", ino, fh, offset); + reply.error(ENOSYS); } fn readdirplus( @@ -468,34 +391,11 @@ impl Filesystem for FatFuse { fn releasedir( &mut self, _req: &fuser::Request<'_>, - ino: u64, - fh: u64, + _ino: u64, + _fh: u64, _flags: i32, reply: fuser::ReplyEmpty, ) { - let Some(ino) = self.ino_by_fh.remove(&fh) else { - debug!("can't find inode {} by fh {}", ino, fh); - - reply.error(EIO); - return; - }; - - let Some(inode) = self.inode_table.get(&ino) else { - debug!("ino {} not associated with an inode", ino); - - reply.ok(); - return; - }; - - if inode.ino() != ino { - debug!( - "inode with ino {}, associated with fh {}, does not have expected ino {}", - inode.ino(), - fh, - ino - ); - } - reply.ok(); } @@ -518,6 +418,62 @@ impl Filesystem for FatFuse { reply.statfs(0, 0, 0, 0, 0, 512, 255, 0); } + fn setxattr( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + name: &std::ffi::OsStr, + _value: &[u8], + flags: i32, + position: u32, + reply: fuser::ReplyEmpty, + ) { + debug!( + "[Not Implemented] setxattr(ino: {:#x?}, name: {:?}, flags: {:#x?}, position: {})", + ino, name, flags, position + ); + reply.error(ENOSYS); + } + + fn getxattr( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + name: &std::ffi::OsStr, + size: u32, + reply: fuser::ReplyXattr, + ) { + debug!("[Not Implemented] getxattr(ino: {:#x?}, name: {:?}, size: {})", ino, name, size); + reply.error(ENOSYS); + } + + fn listxattr( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + size: u32, + reply: fuser::ReplyXattr, + ) { + debug!("[Not Implemented] listxattr(ino: {:#x?}, size: {})", ino, size); + reply.error(ENOSYS); + } + + fn removexattr( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + name: &std::ffi::OsStr, + reply: fuser::ReplyEmpty, + ) { + debug!("[Not Implemented] removexattr(ino: {:#x?}, name: {:?})", ino, name); + reply.error(ENOSYS); + } + + fn access(&mut self, _req: &fuser::Request<'_>, ino: u64, mask: i32, reply: fuser::ReplyEmpty) { + debug!("[Not Implemented] access(ino: {:#x?}, mask: {})", ino, mask); + reply.error(ENOSYS); + } + fn create( &mut self, _req: &fuser::Request<'_>, @@ -536,6 +492,104 @@ impl Filesystem for FatFuse { reply.error(ENOSYS); } + fn getlk( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + fh: u64, + lock_owner: u64, + start: u64, + end: u64, + typ: i32, + pid: u32, + reply: fuser::ReplyLock, + ) { + debug!( + "[Not Implemented] getlk(ino: {:#x?}, fh: {}, lock_owner: {}, start: {}, \ + end: {}, typ: {}, pid: {})", + ino, fh, lock_owner, start, end, typ, pid + ); + reply.error(ENOSYS); + } + + fn setlk( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + fh: u64, + lock_owner: u64, + start: u64, + end: u64, + typ: i32, + pid: u32, + sleep: bool, + reply: fuser::ReplyEmpty, + ) { + debug!( + "[Not Implemented] setlk(ino: {:#x?}, fh: {}, lock_owner: {}, start: {}, \ + end: {}, typ: {}, pid: {}, sleep: {})", + ino, fh, lock_owner, start, end, typ, pid, sleep + ); + reply.error(ENOSYS); + } + + fn bmap( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + blocksize: u32, + idx: u64, + reply: fuser::ReplyBmap, + ) { + debug!( + "[Not Implemented] bmap(ino: {:#x?}, blocksize: {}, idx: {})", + ino, blocksize, idx, + ); + reply.error(ENOSYS); + } + + fn ioctl( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + fh: u64, + flags: u32, + cmd: u32, + in_data: &[u8], + out_size: u32, + reply: fuser::ReplyIoctl, + ) { + debug!( + "[Not Implemented] ioctl(ino: {:#x?}, fh: {}, flags: {}, cmd: {}, \ + in_data.len(): {}, out_size: {})", + ino, + fh, + flags, + cmd, + in_data.len(), + out_size, + ); + reply.error(ENOSYS); + } + + fn fallocate( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + fh: u64, + offset: i64, + length: i64, + mode: i32, + reply: fuser::ReplyEmpty, + ) { + debug!( + "[Not Implemented] fallocate(ino: {:#x?}, fh: {}, offset: {}, \ + length: {}, mode: {})", + ino, fh, offset, length, mode + ); + reply.error(ENOSYS); + } + fn lseek( &mut self, _req: &fuser::Request<'_>, @@ -551,4 +605,26 @@ impl Filesystem for FatFuse { ); reply.error(ENOSYS); } + + fn copy_file_range( + &mut self, + _req: &fuser::Request<'_>, + ino_in: u64, + fh_in: u64, + offset_in: i64, + ino_out: u64, + fh_out: u64, + offset_out: i64, + len: u64, + flags: u32, + reply: fuser::ReplyWrite, + ) { + debug!( + "[Not Implemented] copy_file_range(ino_in: {:#x?}, fh_in: {}, \ + offset_in: {}, ino_out: {:#x?}, fh_out: {}, offset_out: {}, \ + len: {}, flags: {})", + ino_in, fh_in, offset_in, ino_out, fh_out, offset_out, len, flags + ); + reply.error(ENOSYS); + } } diff --git a/fat-fuse/src/inode.rs b/fat-fuse/src/inode.rs index ead17ec..96c8000 100644 --- a/fat-fuse/src/inode.rs +++ b/fat-fuse/src/inode.rs @@ -6,7 +6,6 @@ use fat_bits::FatFs; use fat_bits::dir::DirEntry; use fuser::FileAttr; use libc::ENOTDIR; -use log::debug; use rand::{Rng, SeedableRng as _}; thread_local! { @@ -92,7 +91,7 @@ impl Inode { ((secs as u32) << 16) | rand as u32 } - pub fn new(fat_fs: &FatFs, dir_entry: &DirEntry, ino: u64, uid: u32, gid: u32) -> Inode { + pub fn new(fat_fs: &FatFs, dir_entry: DirEntry, ino: u64, uid: u32, gid: u32) -> Inode { assert!(dir_entry.is_file() || dir_entry.is_dir()); let generation = Self::new_generation(); @@ -115,12 +114,6 @@ impl Inode { let mtime = datetime_to_system(dir_entry.write_time()); let crtime = datetime_to_system(dir_entry.create_time()); - debug!( - "creating new inode: ino: {} name: {}", - ino, - dir_entry.name_string().unwrap_or("".into()) - ); - Inode { ino, generation, @@ -138,28 +131,6 @@ impl Inode { } } - pub fn root_inode(fat_fs: &FatFs, uid: u32, gid: u32) -> Inode { - // let generation = Self::new_generation(); - - let root_cluster = fat_fs.bpb().root_cluster().unwrap_or(0); - - Inode { - ino: 1, - generation: 0, - ref_count: 0, - size: 0, - block_size: fat_fs.bpb().bytes_per_sector() as u32, - kind: Kind::Dir, - read_only: false, - atime: SystemTime::UNIX_EPOCH, - mtime: SystemTime::UNIX_EPOCH, - crtime: SystemTime::UNIX_EPOCH, - uid, - gid, - first_cluster: root_cluster, - } - } - pub fn ino(&self) -> u64 { self.ino } @@ -172,37 +143,14 @@ impl Inode { self.ref_count } - pub fn refcount_inc(&mut self) { - self.ref_count += 1; - } - - pub fn refcount_dec(&mut self, n: u64) -> u64 { - if self.ref_count < n { - debug!( - "inode {}: tried to decrement refcount by {}, but is only {}", - self.ino(), - n, - self.ref_count - ); - } - - self.ref_count = self.ref_count.saturating_sub(n); - - self.ref_count - } - - pub fn kind(&self) -> Kind { - self.kind + pub fn ref_count_mut(&mut self) -> &mut u64 { + &mut self.ref_count } pub fn first_cluster(&self) -> u32 { self.first_cluster } - pub fn is_root(&self) -> bool { - self.ino == ROOT_INO - } - pub fn file_attr(&self) -> FileAttr { let perm = if self.read_only { 0o555 } else { 0o777 }; @@ -232,7 +180,7 @@ impl Inode { return Err(ENOTDIR); } - if self.is_root() { + if self.ino == ROOT_INO { // root dir return Ok(fat_fs.root_dir_iter()); diff --git a/fat-fuse/src/lib.rs b/fat-fuse/src/lib.rs index 6e993b6..e3a77c3 100644 --- a/fat-fuse/src/lib.rs +++ b/fat-fuse/src/lib.rs @@ -5,7 +5,6 @@ use std::cell::RefCell; use std::collections::BTreeMap; use std::rc::Rc; -use fat_bits::dir::DirEntry; use fat_bits::{FatFs, SliceLike}; use log::debug; @@ -19,55 +18,31 @@ pub struct FatFuse { gid: u32, next_ino: u64, - next_fh: u64, + next_fd: u32, inode_table: BTreeMap, ino_by_first_cluster: BTreeMap, - ino_by_fh: BTreeMap, -} - -impl Drop for FatFuse { - fn drop(&mut self) { - println!("inode_table: {}", self.inode_table.len()); - - println!("ino_by_first_cluster: {}", self.ino_by_first_cluster.len()); - for (&first_cluster, &ino) in self.ino_by_first_cluster.iter() { - println!("{} -> {}", first_cluster, ino); - } - - println!("ino_by_fh: {}", self.ino_by_fh.len()); - } } impl FatFuse { - pub fn new(data: S) -> anyhow::Result - where - S: SliceLike + Send + 'static, - { + pub fn new(data: Rc>) -> anyhow::Result { let uid = unsafe { libc::getuid() }; let gid = unsafe { libc::getgid() }; let fat_fs = FatFs::load(data)?; - let mut fat_fuse = FatFuse { + // TODO: build and insert root dir inode + + Ok(FatFuse { fat_fs, uid, gid, next_ino: 2, // 0 is reserved and 1 is root - next_fh: 0, + next_fd: 0, inode_table: BTreeMap::new(), ino_by_first_cluster: BTreeMap::new(), - ino_by_fh: BTreeMap::new(), - }; - - // TODO: build and insert root dir inode - - let root_inode = Inode::root_inode(&fat_fuse.fat_fs, uid, gid); - - fat_fuse.insert_inode(root_inode); - - Ok(fat_fuse) + }) } fn next_ino(&mut self) -> u64 { @@ -80,16 +55,6 @@ impl FatFuse { ino } - fn next_fh(&mut self) -> u64 { - let fh = self.next_fh; - - assert!(!self.ino_by_fh.contains_key(&fh)); - - self.next_fh += 1; - - fh - } - fn insert_inode(&mut self, inode: Inode) -> &mut Inode { let ino = inode.ino(); let generation = inode.generation(); @@ -113,6 +78,8 @@ impl FatFuse { } }; + let old_ino = self.ino_by_first_cluster.insert(first_cluster, ino); + debug!( "inserted new inode with ino {} and generation {} (first cluster: {})", ino, generation, first_cluster @@ -122,18 +89,14 @@ impl FatFuse { debug!("ejected inode {} {}", old_inode.ino(), old_inode.generation()); } - if first_cluster != 0 { - if let Some(old_ino) = self.ino_by_first_cluster.insert(first_cluster, ino) { - debug!("ejected old {} -> {} cluster to ino mapping", first_cluster, old_ino); - } + if let Some(old_ino) = old_ino { + debug!("ejected old {} -> {} cluster to ino mapping", first_cluster, old_ino); } new_inode } fn drop_inode(&mut self, ino: u64) { - debug!("dropping ino {}", ino); - let Some(inode) = self.inode_table.remove(&ino) else { debug!("tried to drop inode with ino {}, but was not in table", ino); @@ -142,30 +105,30 @@ impl FatFuse { let first_cluster = inode.first_cluster(); - if first_cluster != 0 { - let entry = self.ino_by_first_cluster.entry(first_cluster); + let entry = self.ino_by_first_cluster.entry(first_cluster); - match entry { - std::collections::btree_map::Entry::Vacant(_) => debug!( - "removed inode with ino {} from table, but it's first cluster did not point to any ino", - ino - ), - std::collections::btree_map::Entry::Occupied(occupied_entry) => { - let found_ino = *occupied_entry.get(); + match entry { + std::collections::btree_map::Entry::Vacant(_) => debug!( + "removed inode with ino {} from table, but it's first cluster did not point to any ino", + ino + ), + std::collections::btree_map::Entry::Occupied(occupied_entry) => { + let found_ino = *occupied_entry.get(); - if found_ino == ino { - // matches our inode, remove it - occupied_entry.remove(); - } else { - // does not match removed inode, leave it as is - debug!( - "removed inode with ino {} from table, but it's first cluster pointer to ino {} instead", - ino, found_ino - ); - } + if found_ino == ino { + // matches our inode, remove it + occupied_entry.remove(); + } else { + // does not match removed inode, leave it as is + debug!( + "removed inode with ino {} from table, but it's first cluster pointer to ino {} instead", + ino, found_ino + ); } } } + + todo!() } fn get_inode(&self, ino: u64) -> Option<&Inode> { @@ -176,31 +139,7 @@ impl FatFuse { self.inode_table.get_mut(&ino) } - fn get_or_make_inode_by_dir_entry(&mut self, dir_entry: &DirEntry) -> &mut Inode { - if self - .get_inode_by_first_cluster_mut(dir_entry.first_cluster()) - .is_some() - { - return self - .get_inode_by_first_cluster_mut(dir_entry.first_cluster()) - .unwrap(); - } - - // no inode found, make a new one - let ino = self.next_ino(); - - let inode = Inode::new(&self.fat_fs, dir_entry, ino, self.uid, self.gid); - - self.insert_inode(inode) - } - pub fn get_inode_by_first_cluster(&self, first_cluster: u32) -> Option<&Inode> { - if first_cluster == 0 { - debug!("trying to get inode by first cluster 0"); - - return None; - } - let ino = self.ino_by_first_cluster.get(&first_cluster)?; if let Some(inode) = self.inode_table.get(ino) { @@ -216,12 +155,6 @@ impl FatFuse { } pub fn get_inode_by_first_cluster_mut(&mut self, first_cluster: u32) -> Option<&mut Inode> { - if first_cluster == 0 { - debug!("trying to get inode by first cluster 0"); - - return None; - } - let ino = self.ino_by_first_cluster.get(&first_cluster)?; if let Some(inode) = self.inode_table.get_mut(ino) { @@ -235,28 +168,4 @@ impl FatFuse { None } } - - pub fn get_inode_by_fh(&self, fh: u64) -> Option<&Inode> { - let ino = self.ino_by_fh.get(&fh)?; - - if let Some(inode) = self.inode_table.get(ino) { - Some(inode) - } else { - debug!("fh {} is mapped to ino {}, but inode is not in table", fh, ino); - - None - } - } - - pub fn get_inode_by_fh_mut(&mut self, fh: u64) -> Option<&mut Inode> { - let ino = self.ino_by_fh.get(&fh)?; - - if let Some(inode) = self.inode_table.get_mut(ino) { - Some(inode) - } else { - debug!("fh {} is mapped to ino {}, but inode is not in table", fh, ino); - - None - } - } } diff --git a/fat-mount/Cargo.toml b/fat-mount/Cargo.toml index ba48f80..e9f82da 100644 --- a/fat-mount/Cargo.toml +++ b/fat-mount/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] anyhow = "1.0.98" -ctrlc = "3.4.7" env_logger = "0.11.8" fat-fuse = { version = "0.1.0", path = "../fat-fuse" } fuser = "0.15.1" diff --git a/fat-mount/src/main.rs b/fat-mount/src/main.rs index 31a5a8f..f9ea244 100644 --- a/fat-mount/src/main.rs +++ b/fat-mount/src/main.rs @@ -1,5 +1,6 @@ +use std::cell::RefCell; use std::fs::File; -use std::sync::mpsc::channel; +use std::rc::Rc; use fat_fuse::FatFuse; use fuser::MountOption; @@ -9,13 +10,12 @@ fn main() -> anyhow::Result<()> { let mut args = std::env::args(); - let _prog_name = args.next().unwrap(); let path = args.next().ok_or(anyhow::anyhow!("missing fs path"))?; let mountpoint = args.next().ok_or(anyhow::anyhow!("missing mount point"))?; let file = File::open(path)?; - let fat_fuse = FatFuse::new(file)?; + let fat_fuse = FatFuse::new(Rc::new(RefCell::new(file)))?; let options = vec![ MountOption::RO, @@ -23,18 +23,7 @@ fn main() -> anyhow::Result<()> { MountOption::AutoUnmount, ]; - let (tx, rx) = channel(); - - ctrlc::set_handler(move || { - tx.send(()).unwrap(); - }) - .unwrap(); - - let handle = fuser::spawn_mount2(fat_fuse, mountpoint, &options)?; - - rx.recv().unwrap(); - - println!("done"); + fuser::mount2(fat_fuse, mountpoint, &options).unwrap(); Ok(()) }