diff --git a/Cargo.lock b/Cargo.lock index 42708e5..bc2c84e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.98" @@ -20,6 +35,21 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cc" +version = "1.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +dependencies = [ + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.1" @@ -38,9 +68,18 @@ version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ + "android-tzdata", + "iana-time-zone", "num-traits", + "windows-link", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "enum_dispatch" version = "0.3.13" @@ -78,6 +117,7 @@ name = "fat-fuse" version = "0.1.0" dependencies = [ "anyhow", + "chrono", "fat-bits", "fuser", "libc", @@ -101,6 +141,40 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.174" @@ -180,6 +254,18 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "smallvec" version = "1.15.1" @@ -229,6 +315,64 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + [[package]] name = "winapi" version = "0.3.9" @@ -251,6 +395,65 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + [[package]] name = "zerocopy" version = "0.8.26" diff --git a/fat-bits/src/iter.rs b/fat-bits/src/iter.rs index 2e34765..8a6f775 100644 --- a/fat-bits/src/iter.rs +++ b/fat-bits/src/iter.rs @@ -1,17 +1,17 @@ use std::io::Read; +use crate::FatFs; use crate::subslice::SubSlice; use crate::utils::replace; -use crate::{FatFs, SliceLike}; -pub struct ClusterChainReader<'a, S: SliceLike> { - sub_slice: SubSlice<'a, S>, +pub struct ClusterChainReader<'a> { + sub_slice: SubSlice<'a>, next_cluster: Option, } -impl<'a, S: SliceLike> ClusterChainReader<'a, S> { - pub fn new(fat_fs: &'a FatFs, first_cluster: u32) -> ClusterChainReader<'a, S> { +impl<'a> ClusterChainReader<'a> { + pub fn new(fat_fs: &'a FatFs, first_cluster: u32) -> ClusterChainReader<'a> { let next_cluster = fat_fs.next_cluster(first_cluster).unwrap_or(None); let sub_slice = fat_fs.cluster_as_subslice(first_cluster); @@ -39,7 +39,7 @@ impl<'a, S: SliceLike> ClusterChainReader<'a, S> { } } -impl<'a, S: SliceLike> Read for ClusterChainReader<'a, S> { +impl<'a> Read for ClusterChainReader<'a> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { if self.sub_slice.is_empty() { if !self.next_cluster() { diff --git a/fat-bits/src/lib.rs b/fat-bits/src/lib.rs index 5591bd5..0709cce 100644 --- a/fat-bits/src/lib.rs +++ b/fat-bits/src/lib.rs @@ -26,14 +26,6 @@ pub trait SliceLike { fn read_at_offset(&mut self, offset: u64, buf: &mut [u8]) -> std::io::Result<()>; fn write_at_offset(&mut self, offset: u64, bytes: &[u8]) -> std::io::Result<()>; - - fn read_array_at_offset(&mut self, offset: u64) -> std::io::Result<[u8; N]> { - let mut buf = [0; N]; - - self.read_at_offset(offset, &mut buf)?; - - Ok(buf) - } } impl SliceLike for &mut [u8] { @@ -87,8 +79,8 @@ impl SliceLike for std::fs::File { } #[allow(dead_code)] -pub struct FatFs { - inner: Rc>, +pub struct FatFs { + inner: Rc>, fat_offset: u64, fat_size: usize, @@ -106,15 +98,18 @@ pub struct FatFs { fat: fat::Fat, } -impl FatFs { - pub fn load(mut data: S) -> anyhow::Result> { - let bpb_bytes: [u8; 512] = data.read_array_at_offset(0)?; +impl FatFs { + pub fn load(data: Rc>) -> anyhow::Result { + let mut bpb_bytes = [0; 512]; + + data.borrow_mut().read_at_offset(0, &mut bpb_bytes)?; let bpb = bpb::Bpb::load(&bpb_bytes)?; let mut fat_buf = vec![0; bpb.fat_len_bytes()]; - data.read_at_offset(bpb.fat_offset(), &mut fat_buf)?; + data.borrow_mut() + .read_at_offset(bpb.fat_offset(), &mut fat_buf)?; let fat = fat::Fat::new(bpb.fat_type(), &fat_buf, bpb.count_of_clusters()); @@ -144,8 +139,6 @@ impl FatFs { let bytes_per_cluster = bpb.bytes_per_cluster(); - let data = Rc::new(RefCell::new(data)); - Ok(FatFs { inner: data, fat_offset, @@ -184,13 +177,13 @@ impl FatFs { self.fat().get_next_cluster(cluster) } - pub fn cluster_as_subslice_mut(&mut self, cluster: u32) -> SubSliceMut<'_, S> { + pub fn cluster_as_subslice_mut(&mut self, cluster: u32) -> SubSliceMut<'_> { 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<'_, S> { + pub fn cluster_as_subslice(&self, cluster: u32) -> SubSlice<'_> { let offset = self.data_cluster_to_offset(cluster); SubSlice::new(self, offset, self.bytes_per_cluster) diff --git a/fat-bits/src/subslice.rs b/fat-bits/src/subslice.rs index b16a417..a710974 100644 --- a/fat-bits/src/subslice.rs +++ b/fat-bits/src/subslice.rs @@ -1,16 +1,16 @@ use std::fmt::Debug; use std::io::{Read, Write}; -use crate::{FatFs, SliceLike}; +use crate::FatFs; -pub struct SubSliceMut<'a, S: SliceLike> { - fat_fs: &'a mut FatFs, +pub struct SubSliceMut<'a> { + fat_fs: &'a mut FatFs, offset: u64, len: usize, } -impl Debug for SubSliceMut<'_, S> { +impl Debug for SubSliceMut<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("SubSliceMut") .field("offset", &self.offset) @@ -19,8 +19,8 @@ impl Debug for SubSliceMut<'_, S> { } } -impl SubSliceMut<'_, S> { - pub fn new(fat_fs: &mut FatFs, offset: u64, len: usize) -> SubSliceMut<'_, S> { +impl SubSliceMut<'_> { + pub fn new(fat_fs: &mut FatFs, offset: u64, len: usize) -> SubSliceMut<'_> { SubSliceMut { fat_fs, offset, @@ -29,7 +29,7 @@ impl SubSliceMut<'_, S> { } } -impl SubSliceMut<'_, S> { +impl SubSliceMut<'_> { pub fn len(&self) -> usize { self.len } @@ -39,7 +39,7 @@ impl SubSliceMut<'_, S> { } } -impl Read for SubSliceMut<'_, S> { +impl Read for SubSliceMut<'_> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { let bytes_to_read = self.len.min(buf.len()); @@ -55,7 +55,7 @@ impl Read for SubSliceMut<'_, S> { } } -impl Write for SubSliceMut<'_, S> { +impl Write for SubSliceMut<'_> { fn write(&mut self, buf: &[u8]) -> std::io::Result { let bytes_to_write = self.len.min(buf.len()); @@ -75,14 +75,14 @@ impl Write for SubSliceMut<'_, S> { } } -pub struct SubSlice<'a, S: SliceLike> { - fat_fs: &'a FatFs, +pub struct SubSlice<'a> { + fat_fs: &'a FatFs, offset: u64, len: usize, } -impl Debug for SubSlice<'_, S> { +impl Debug for SubSlice<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("SubSliceMut") .field("offset", &self.offset) @@ -91,8 +91,8 @@ impl Debug for SubSlice<'_, S> { } } -impl SubSlice<'_, S> { - pub fn new(fat_fs: &FatFs, offset: u64, len: usize) -> SubSlice<'_, S> { +impl SubSlice<'_> { + pub fn new(fat_fs: &FatFs, offset: u64, len: usize) -> SubSlice<'_> { SubSlice { fat_fs, offset, @@ -100,11 +100,11 @@ impl SubSlice<'_, S> { } } - pub fn fat_fs(&self) -> &FatFs { + pub fn fat_fs(&self) -> &FatFs { self.fat_fs } - pub fn fat_fs_mut(&self) -> &FatFs { + pub fn fat_fs_mut(&self) -> &FatFs { self.fat_fs } @@ -116,14 +116,14 @@ impl SubSlice<'_, S> { } } -impl<'a, S: SliceLike> SubSlice<'a, S> { +impl<'a> SubSlice<'a> { /// releases the inner &FatFs, consuming self in the process - pub fn release(self) -> &'a FatFs { + pub fn release(self) -> &'a FatFs { self.fat_fs } } -impl Read for SubSlice<'_, S> { +impl Read for SubSlice<'_> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { let bytes_to_read = self.len.min(buf.len()); diff --git a/fat-dump/src/main.rs b/fat-dump/src/main.rs index 1407e9e..3cb84eb 100644 --- a/fat-dump/src/main.rs +++ b/fat-dump/src/main.rs @@ -1,6 +1,9 @@ -use fat_bits::dir::{DirIter, DirEntry}; +use std::cell::RefCell; +use std::rc::Rc; + +use fat_bits::FatFs; +use fat_bits::dir::{DirEntry, DirIter}; use fat_bits::fat::Fatty as _; -use fat_bits::{FatFs, SliceLike}; pub fn main() -> anyhow::Result<()> { let args = std::env::args(); @@ -19,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!(); @@ -41,15 +44,15 @@ pub fn main() -> anyhow::Result<()> { Ok(()) } -fn tree(fat_fs: &FatFs, show_hidden: bool) { +fn tree(fat_fs: &FatFs, show_hidden: bool) { fn do_indent(indent: u32) { for _ in 0..indent { print!(" "); } } - fn tree_impl( - fat_fs: &FatFs, + fn tree_impl( + fat_fs: &FatFs, iter: impl Iterator, show_hidden: bool, indent: u32, diff --git a/fat-fuse/Cargo.toml b/fat-fuse/Cargo.toml index f92e1df..5e60917 100644 --- a/fat-fuse/Cargo.toml +++ b/fat-fuse/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] anyhow = "1.0.98" +chrono = { version = "0.4.41", default-features = false, features = ["alloc", "clock", "std"] } fat-bits = { version = "0.1.0", path = "../fat-bits" } fuser = "0.15.1" libc = "0.2.174" diff --git a/fat-fuse/src/lib.rs b/fat-fuse/src/lib.rs index fdaef8c..83b2a34 100644 --- a/fat-fuse/src/lib.rs +++ b/fat-fuse/src/lib.rs @@ -1,52 +1,44 @@ -use std::ffi::c_int; +mod inode; + +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::ffi::c_int; +use std::rc::Rc; -use fat_bits::dir::DirEntry; use fat_bits::{FatFs, SliceLike}; -use fuser::{FileAttr, Filesystem}; +use fuser::Filesystem; use libc::{ENOSYS, EPERM}; use log::{debug, warn}; -#[allow(dead_code)] -fn dir_entry_to_attr(dir_entry: &DirEntry, ino: u64) -> FileAttr { - FileAttr { - ino, - size: dir_entry.file_size() as u64, - blocks: todo!(), - atime: todo!(), - mtime: todo!(), - ctime: todo!(), - crtime: todo!(), - kind: todo!(), - perm: todo!(), - nlink: todo!(), - uid: todo!(), - gid: todo!(), - rdev: todo!(), - blksize: todo!(), - flags: todo!(), - } -} +use crate::inode::Inode; #[allow(dead_code)] -pub struct FatFuse { - fat_fs: FatFs, +pub struct FatFuse { + fat_fs: FatFs, uid: u32, gid: u32, + + inode_table: BTreeMap, } -impl FatFuse { - pub fn new(data: S) -> anyhow::Result> { +impl FatFuse { + pub fn new(data: Rc>) -> anyhow::Result { let uid = unsafe { libc::getuid() }; let gid = unsafe { libc::getgid() }; let fat_fs = FatFs::load(data)?; - Ok(FatFuse { fat_fs, uid, gid }) + Ok(FatFuse { + fat_fs, + uid, + gid, + inode_table: BTreeMap::new(), + }) } } -impl Filesystem for FatFuse { +impl Filesystem for FatFuse { fn init( &mut self, _req: &fuser::Request<'_>,