Compare commits

...

4 commits

Author SHA1 Message Date
3c20c2c97c dump.rs: added tree function 2025-07-27 00:24:48 +02:00
fc7a0c4616 FatFs: moved data/inner behind Rc+RefCell
so that non-mut ref can read
2025-07-27 00:24:32 +02:00
17e5bfc27c DirEntry: added is_dot, is_dotdot, is_hidden methods 2025-07-27 00:22:27 +02:00
db105d3534 DirEntry: updated Display 2025-07-27 00:17:23 +02:00
5 changed files with 94 additions and 19 deletions

View file

@ -76,7 +76,7 @@ impl Display for RegularDirEntry {
write!(
f,
"DirEntry {{ {} {: <16} created: {} modified: {} }}",
"{} {: <16} created: {} modified: {}",
self.attr,
name,
self.create_time().format("%a %b %d %H:%M:%S%.3f %Y"),
@ -167,6 +167,30 @@ impl RegularDirEntry {
self.attr.contains(Attr::Directory) && !self.attr.intersects(Attr::System | Attr::VolumeId)
}
pub fn is_dot(&self) -> bool {
if !self.is_dir() {
return false;
}
// &self.name[..2] == &[b'.', b' ']
self.name[0] == b'.' && &self.name[1..] == &[b' '; 10]
}
pub fn is_dotdot(&self) -> bool {
if !self.is_dir() {
return false;
}
// &self.name[..3] == &[b'.', b'.', b' ']
&self.name[..2] == &[b'.', b'.'] && &self.name[2..] == &[b' '; 9]
}
pub fn is_hidden(&self) -> bool {
self.is_dot() || self.is_dotdot() || self.attr.contains(Attr::Hidden)
}
pub fn name(&self) -> &[u8] {
&self.name
}

View file

@ -1,7 +1,8 @@
use std::io::Read;
use fat_rs::FatFs;
use fat_rs::dir::{DirIter, RegularDirEntry};
use fat_rs::fat::Fatty as _;
use fat_rs::{FatFs, SliceLike};
pub fn main() -> anyhow::Result<()> {
let args = std::env::args();
@ -38,5 +39,45 @@ pub fn main() -> anyhow::Result<()> {
println!("{}", dir_entry);
}
println!();
println!();
tree(&fat_fs);
Ok(())
}
fn tree<S: SliceLike>(fat_fs: &FatFs<S>) {
fn do_indent(indent: u32) {
for _ in 0..indent {
print!(" ");
}
}
fn tree_impl<S: SliceLike>(
fat_fs: &FatFs<S>,
iter: impl Iterator<Item = RegularDirEntry>,
indent: u32,
) {
for dir_entry in iter.filter(|x| !x.is_hidden()) {
do_indent(indent);
println!("{}", dir_entry);
if dir_entry.is_dot() || dir_entry.is_dotdot() {
// do not descent into . and ..
continue;
}
if dir_entry.is_dir() {
let reader = fat_fs.chain_reader(dir_entry.first_cluster());
let iter = DirIter::new(reader);
tree_impl(fat_fs, iter, indent + 1);
}
}
}
tree_impl(fat_fs, fat_fs.root_dir_iter(), 0);
}

View file

@ -1,6 +1,5 @@
use std::io::Read;
use crate::fat::Fatty;
use crate::subslice::SubSlice;
use crate::utils::replace;
use crate::{FatFs, SliceLike};
@ -12,7 +11,7 @@ pub struct ClusterChainReader<'a, S: SliceLike> {
}
impl<'a, S: SliceLike> ClusterChainReader<'a, S> {
pub fn new(fat_fs: &'a mut FatFs<S>, first_cluster: u32) -> ClusterChainReader<'a, S> {
pub fn new(fat_fs: &'a FatFs<S>, first_cluster: u32) -> ClusterChainReader<'a, S> {
let next_cluster = fat_fs.next_cluster(first_cluster).unwrap_or(None);
let sub_slice = fat_fs.cluster_as_subslice(first_cluster);

View file

@ -1,4 +1,6 @@
use std::io::{Read as _, Seek as _, SeekFrom, Write as _};
use std::cell::RefCell;
use std::io::{Read, Seek, SeekFrom, Write};
use std::rc::Rc;
use crate::dir::{DirIter, RegularDirEntry};
use crate::fat::{FatError, Fatty};
@ -94,7 +96,7 @@ impl SliceLike for std::fs::File {
#[allow(dead_code)]
pub struct FatFs<S: SliceLike> {
data: S,
inner: Rc<RefCell<S>>,
fat_offset: u64,
fat_size: usize,
@ -150,8 +152,10 @@ impl<S: SliceLike> FatFs<S> {
let bytes_per_cluster = bpb.bytes_per_cluster();
let data = Rc::new(RefCell::new(data));
Ok(FatFs {
data,
inner: data,
fat_offset,
fat_size,
root_dir_offset,
@ -194,7 +198,7 @@ impl<S: SliceLike> FatFs<S> {
SubSliceMut::new(self, offset, self.bytes_per_cluster)
}
pub fn cluster_as_subslice(&mut self, cluster: u32) -> SubSlice<'_, S> {
pub fn cluster_as_subslice(&self, cluster: u32) -> SubSlice<'_, S> {
let offset = self.data_cluster_to_offset(cluster);
SubSlice::new(self, offset, self.bytes_per_cluster)
@ -215,20 +219,20 @@ impl<S: SliceLike> FatFs<S> {
let mut data = vec![0; self.bytes_per_cluster];
self.data
.read_at_offset(self.data_cluster_to_offset(cluster), &mut data)?;
let mut inner = self.inner.borrow_mut();
inner.read_at_offset(self.data_cluster_to_offset(cluster), &mut data)?;
while let Ok(Some(next_cluster)) = self.next_cluster(cluster) {
cluster = next_cluster;
self.data
.read_at_offset(self.data_cluster_to_offset(cluster), &mut data)?;
inner.read_at_offset(self.data_cluster_to_offset(cluster), &mut data)?;
}
Ok(data)
}
pub fn root_dir_iter(&mut self) -> Box<dyn Iterator<Item = RegularDirEntry> + '_> {
pub fn root_dir_iter(&self) -> Box<dyn Iterator<Item = RegularDirEntry> + '_> {
// TODO: maybe wrap this in another RootDirIter enum, so we don't have to Box<dyn>
if let Some(root_dir_offset) = self.root_dir_offset {
@ -248,4 +252,8 @@ impl<S: SliceLike> FatFs<S> {
Box::new(DirIter::new(cluster_iter))
}
pub fn chain_reader(&self, first_cluster: u32) -> impl Read {
iter::ClusterChainReader::new(self, first_cluster)
}
}

View file

@ -44,7 +44,8 @@ impl<S: SliceLike> Read for SubSliceMut<'_, S> {
let bytes_to_read = self.len.min(buf.len());
self.fat_fs
.data
.inner
.borrow_mut()
.read_at_offset(self.offset, &mut buf[..bytes_to_read])?;
self.offset += bytes_to_read as u64;
@ -59,7 +60,8 @@ impl<S: SliceLike> Write for SubSliceMut<'_, S> {
let bytes_to_write = self.len.min(buf.len());
self.fat_fs
.data
.inner
.borrow_mut()
.write_at_offset(self.offset, &buf[..bytes_to_write])?;
self.offset += bytes_to_write as u64;
@ -74,7 +76,7 @@ impl<S: SliceLike> Write for SubSliceMut<'_, S> {
}
pub struct SubSlice<'a, S: SliceLike> {
fat_fs: &'a mut FatFs<S>,
fat_fs: &'a FatFs<S>,
offset: u64,
len: usize,
@ -90,7 +92,7 @@ impl<S: SliceLike> Debug for SubSlice<'_, S> {
}
impl<S: SliceLike> SubSlice<'_, S> {
pub fn new(fat_fs: &mut FatFs<S>, offset: u64, len: usize) -> SubSlice<'_, S> {
pub fn new(fat_fs: &FatFs<S>, offset: u64, len: usize) -> SubSlice<'_, S> {
SubSlice {
fat_fs,
offset,
@ -115,7 +117,7 @@ impl<S: SliceLike> SubSlice<'_, S> {
}
impl<'a, S: SliceLike> SubSlice<'a, S> {
pub fn release(self) -> &'a mut FatFs<S> {
pub fn release(self) -> &'a FatFs<S> {
self.fat_fs
}
}
@ -125,7 +127,8 @@ impl<S: SliceLike> Read for SubSlice<'_, S> {
let bytes_to_read = self.len.min(buf.len());
self.fat_fs
.data
.inner
.borrow_mut()
.read_at_offset(self.offset, &mut buf[..bytes_to_read])?;
self.offset += bytes_to_read as u64;