diff --git a/examples/partition.rs b/examples/partition.rs new file mode 100644 index 0000000..2559ac4 --- /dev/null +++ b/examples/partition.rs @@ -0,0 +1,83 @@ +extern crate fatfs; + +use std::{cmp, fs, io}; +use std::io::{prelude::*, SeekFrom, ErrorKind}; +use fatfs::{FileSystem, FsOptions, BufStream}; + +trait ReadWriteSeek: Read + Write + Seek {} +impl ReadWriteSeek for T where T: Read + Write + Seek {} + +// File wrapper for accessing part of file +#[derive(Clone)] +pub(crate) struct Partition { + inner: T, + start_offset: u64, + current_offset: u64, + size: u64, +} + +impl Partition { + pub(crate) fn new(mut inner: T, start_offset: u64, size: u64) -> io::Result { + inner.seek(SeekFrom::Start(start_offset))?; + Ok(Self { + start_offset, size, inner, + current_offset: 0, + }) + } +} + +impl Read for Partition { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let max_read_size = cmp::min((self.size - self.current_offset) as usize, buf.len()); + let bytes_read = self.inner.read(&mut buf[..max_read_size])?; + self.current_offset += bytes_read as u64; + Ok(bytes_read) + } +} + +impl Write for Partition { + fn write(&mut self, buf: &[u8]) -> io::Result { + let max_write_size = cmp::min((self.size - self.current_offset) as usize, buf.len()); + let bytes_written = self.inner.write(&buf[..max_write_size])?; + self.current_offset += bytes_written as u64; + Ok(bytes_written) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} + +impl Seek for Partition { + fn seek(&mut self, pos: SeekFrom) -> io::Result { + let new_offset = match pos { + SeekFrom::Current(x) => self.current_offset as i64 + x, + SeekFrom::Start(x) => x as i64, + SeekFrom::End(x) => self.size as i64 + x, + }; + if new_offset < 0 || new_offset as u64 > self.size { + Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek")) + } else { + self.inner.seek(SeekFrom::Start(self.start_offset + new_offset as u64))?; + self.current_offset = new_offset as u64; + Ok(self.current_offset) + } + } +} + +fn main() { + // Open disk image + let file = fs::File::open("resources/fat32.img").unwrap(); + // Provide sample partition localization. In real application it should be read from MBR/GPT. + let first_lba = 0; + let last_lba = 10000; + // Create partition using provided start address and size in bytes + let partition = Partition::::new(file, first_lba, last_lba - first_lba + 1).unwrap(); + // Create buffered stream to optimize file access + let mut buf_rdr = BufStream::new(partition); + // Finally initialize filesystem struct using provided partition + let fs = FileSystem::new(&mut buf_rdr, FsOptions::new()).unwrap(); + // Read and display volume label + println!("Volume Label: {}", fs.volume_label()); + // other operations +}