Skip to content

Commit

Permalink
Expose directory tell, seek and rewind functionnality
Browse files Browse the repository at this point in the history
  • Loading branch information
sosthene-nitrokey committed Jun 12, 2023
1 parent f1c9abe commit 760bb7f
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 2 deletions.
66 changes: 66 additions & 0 deletions src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,13 +1033,79 @@ impl ReadDirAllocation {
}
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct DirIterationTell {
tell_result: u32,
}

pub struct ReadDir<'a, 'b, S: driver::Storage> {
alloc: RefCell<&'b mut ReadDirAllocation>,
fs: &'b Filesystem<'a, S>,
#[cfg(feature = "dir-entry-path")]
path: PathBuf,
}

impl<'a, 'b, S: driver::Storage> ReadDir<'a, 'b, S> {
/// Return the position of the directory
///
/// The returned offset is only meant to be consumed by seek and may not make
/// sense, but does indicate the current position in the directory iteration.
///
/// Returns the position of the directory, which can be returned to using [`seek`](Self::seek).
pub fn tell(&self) -> Result<DirIterationTell> {
let value = unsafe {
ll::lfs_dir_tell(
&mut self.fs.alloc.borrow_mut().state,
&mut self.alloc.borrow_mut().state,
)
};
if value < 0 {
Err(io::result_from((), value).unwrap_err())
} else {
Ok(DirIterationTell {
tell_result: value as u32,
})
}
}

/// Change the position of the directory
///
/// The new off must be a value previous returned from [`tell`](Self::tell) and specifies
/// an absolute offset in the directory seek.
pub fn seek(&mut self, state: DirIterationTell) -> Result<DirIterationTell> {
let value = unsafe {
ll::lfs_dir_seek(
&mut self.fs.alloc.borrow_mut().state,
&mut self.alloc.borrow_mut().state,
state.tell_result,
)
};
if value < 0 {
Err(io::result_from((), value).unwrap_err())
} else {
Ok(DirIterationTell {
tell_result: value as u32,
})
}
}

/// Change the position of the directory to the beginning of the directory
pub fn rewind(&mut self) -> Result<()> {
let res = unsafe {
ll::lfs_dir_rewind(
&mut self.fs.alloc.borrow_mut().state,
&mut self.alloc.borrow_mut().state,
)
};

if res < 0 {
Err(io::result_from((), res).unwrap_err())
} else {
Ok(())
}
}
}

impl<'a, 'b, S: driver::Storage> Iterator for ReadDir<'a, 'b, S> {
type Item = Result<DirEntry>;

Expand Down
26 changes: 24 additions & 2 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,12 +449,16 @@ fn test_iter_dirs() {
file.set_len(37)?;
fs.create_file_and_then(b"/tmp/file.b\0".try_into()?, |file| file.set_len(42))
})?;
let mut tells = Vec::new();

fs.read_dir_and_then(b"/tmp\0".try_into()?, |dir| {
fs.read_dir_and_then(b"/tmp\0".try_into()?, |mut dir| {
let mut found_files: usize = 0;
let mut sizes = [0usize; 4];
let mut i = 0;

for (i, entry) in dir.enumerate() {
tells.push(dir.tell()?);
while let Some(entry) = dir.next() {
tells.push(dir.tell()?);
let entry = entry?;

// assert_eq!(entry.file_name(), match i {
Expand All @@ -467,13 +471,31 @@ fn test_iter_dirs() {

sizes[i] = entry.metadata().len();
found_files += 1;
i += 1;
}

assert_eq!(sizes, [0, 0, 37, 42]);
assert_eq!(found_files, 4);

for (i, tell) in tells.iter().enumerate() {
dir.rewind().unwrap();
let mut found_files: usize = 0;
let mut sizes = Vec::new();
dir.seek(*tell)?;

for entry in &mut dir {
let entry = entry?;
sizes.push(entry.metadata().len());
found_files += 1;
}

assert_eq!(sizes, [0, 0, 37, 42][i..]);
assert_eq!(found_files, 4 - i);
}
Ok(())
})
.unwrap();
Ok(())
})
.unwrap();
}
Expand Down

0 comments on commit 760bb7f

Please sign in to comment.