Skip to content

Commit

Permalink
Allow user provided read/write files to not be static
Browse files Browse the repository at this point in the history
  • Loading branch information
rbran authored and wcampbell0x2a committed Oct 7, 2023
1 parent c921d45 commit abeeaea
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 57 deletions.
8 changes: 4 additions & 4 deletions src/v4/filesystem/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,13 @@ pub struct SquashfsFileReader {
}

/// Read file from other SquashfsFile or an user file
pub enum SquashfsFileWriter<'a> {
UserDefined(Arc<Mutex<dyn Read + 'a>>),
SquashfsFile(FilesystemReaderFile<'a>),
pub enum SquashfsFileWriter<'a, 'b> {
UserDefined(Arc<Mutex<dyn Read + 'b>>),
SquashfsFile(FilesystemReaderFile<'a, 'b>),
Consumed(usize, Added),
}

impl<'a> fmt::Debug for SquashfsFileWriter<'a> {
impl<'a, 'b> fmt::Debug for SquashfsFileWriter<'a, 'b> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FileWriter").finish()
}
Expand Down
48 changes: 24 additions & 24 deletions src/v4/filesystem/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ use crate::v4::{Node, Squashfs, SquashfsFileReader};
/// let filesystem = squashfs.into_filesystem_reader().unwrap();
/// ```
/// [InnerNode]: [`crate::InnerNode`]
pub struct FilesystemReader {
pub struct FilesystemReader<'b> {
pub kind: Kind,
/// The size of a data block in bytes. Must be a power of two between 4096 (4k) and 1048576 (1 MiB).
pub block_size: u32,
Expand All @@ -86,16 +86,16 @@ pub struct FilesystemReader {
/// All files and directories in filesystem
pub root: Nodes<SquashfsFileReader>,
// File reader
pub(crate) reader: Mutex<Box<dyn BufReadSeek>>,
pub(crate) reader: Mutex<Box<dyn BufReadSeek + 'b>>,
// Cache used in the decompression
pub(crate) cache: Mutex<Cache>,
}

impl FilesystemReader {
impl<'b> FilesystemReader<'b> {
/// Call [`Squashfs::from_reader`], then [`Squashfs::into_filesystem_reader`]
///
/// With default kind: [`crate::kind::LE_V4_0`] and offset `0`.
pub fn from_reader<R: BufReadSeek + 'static>(reader: R) -> Result<Self, BackhandError> {
pub fn from_reader<R: BufReadSeek + 'b>(reader: R) -> Result<Self, BackhandError> {
let squashfs = Squashfs::from_reader_with_offset(reader, 0)?;
squashfs.into_filesystem_reader()
}
Expand All @@ -109,7 +109,7 @@ impl FilesystemReader {
}

/// Same as [`Self::from_reader`], but seek'ing to `offset` in `reader` before reading
pub fn from_reader_with_offset<R: BufReadSeek + 'static>(
pub fn from_reader_with_offset<R: BufReadSeek + 'b>(
reader: R,
offset: u64,
) -> Result<Self, BackhandError> {
Expand All @@ -118,7 +118,7 @@ impl FilesystemReader {
}

/// Same as [`Self::from_reader_with_offset`], but setting custom `kind`
pub fn from_reader_with_offset_and_kind<R: BufReadSeek + 'static>(
pub fn from_reader_with_offset_and_kind<R: BufReadSeek + 'b>(
reader: R,
offset: u64,
kind: Kind,
Expand All @@ -128,7 +128,7 @@ impl FilesystemReader {
}

/// Return a file handler for this file
pub fn file<'a>(&'a self, basic_file: &'a BasicFile) -> FilesystemReaderFile {
pub fn file<'a>(&'a self, basic_file: &'a BasicFile) -> FilesystemReaderFile<'a, 'b> {
FilesystemReaderFile::new(self, basic_file)
}

Expand Down Expand Up @@ -170,13 +170,13 @@ impl FilesystemReader {

/// Filesystem handle for file
#[derive(Copy, Clone)]
pub struct FilesystemReaderFile<'a> {
pub(crate) system: &'a FilesystemReader,
pub struct FilesystemReaderFile<'a, 'b> {
pub(crate) system: &'a FilesystemReader<'b>,
pub(crate) basic: &'a BasicFile,
}

impl<'a> FilesystemReaderFile<'a> {
pub fn new(system: &'a FilesystemReader, basic: &'a BasicFile) -> Self {
impl<'a, 'b> FilesystemReaderFile<'a, 'b> {
pub fn new(system: &'a FilesystemReader<'b>, basic: &'a BasicFile) -> Self {
Self { system, basic }
}

Expand All @@ -198,7 +198,7 @@ impl<'a> FilesystemReaderFile<'a> {
&self,
buf_read: &'a mut Vec<u8>,
buf_decompress: &'a mut Vec<u8>,
) -> SquashfsReadFile {
) -> SquashfsReadFile<'a, 'b> {
self.raw_data_reader().into_reader(buf_read, buf_decompress)
}

Expand All @@ -213,15 +213,15 @@ impl<'a> FilesystemReaderFile<'a> {
}
}

pub(crate) fn raw_data_reader(&self) -> SquashfsRawData {
pub(crate) fn raw_data_reader(&self) -> SquashfsRawData<'a, 'b> {
SquashfsRawData::new(Self {
system: self.system,
basic: self.basic,
})
}
}

impl<'a> IntoIterator for FilesystemReaderFile<'a> {
impl<'a, 'b> IntoIterator for FilesystemReaderFile<'a, 'b> {
type IntoIter = BlockIterator<'a>;
type Item = <BlockIterator<'a> as Iterator>::Item;

Expand Down Expand Up @@ -263,14 +263,14 @@ pub(crate) struct RawDataBlock {
pub(crate) uncompressed: bool,
}

pub(crate) struct SquashfsRawData<'a> {
pub(crate) file: FilesystemReaderFile<'a>,
pub(crate) struct SquashfsRawData<'a, 'b> {
pub(crate) file: FilesystemReaderFile<'a, 'b>,
current_block: BlockIterator<'a>,
pub(crate) pos: u64,
}

impl<'a> SquashfsRawData<'a> {
pub fn new(file: FilesystemReaderFile<'a>) -> Self {
impl<'a, 'b> SquashfsRawData<'a, 'b> {
pub fn new(file: FilesystemReaderFile<'a, 'b>) -> Self {
let pos = file.basic.blocks_start.into();
let current_block = file.into_iter();
Self {
Expand All @@ -283,7 +283,7 @@ impl<'a> SquashfsRawData<'a> {
fn read_raw_data(
&mut self,
data: &mut Vec<u8>,
block: &BlockFragment,
block: &BlockFragment<'a>,
) -> Result<RawDataBlock, BackhandError> {
match block {
BlockFragment::Block(block) => {
Expand Down Expand Up @@ -387,7 +387,7 @@ impl<'a> SquashfsRawData<'a> {
self,
buf_read: &'a mut Vec<u8>,
buf_decompress: &'a mut Vec<u8>,
) -> SquashfsReadFile<'a> {
) -> SquashfsReadFile<'a, 'b> {
let bytes_available = self.file.basic.file_size as usize;
SquashfsReadFile {
raw_data: self,
Expand All @@ -399,16 +399,16 @@ impl<'a> SquashfsRawData<'a> {
}
}

pub struct SquashfsReadFile<'a> {
raw_data: SquashfsRawData<'a>,
pub struct SquashfsReadFile<'a, 'b> {
raw_data: SquashfsRawData<'a, 'b>,
buf_read: &'a mut Vec<u8>,
buf_decompress: &'a mut Vec<u8>,
//offset of buf_decompress to start reading
last_read: usize,
bytes_available: usize,
}

impl<'a> SquashfsReadFile<'a> {
impl<'a, 'b> SquashfsReadFile<'a, 'b> {
fn available(&self) -> &[u8] {
&self.buf_decompress[self.last_read..]
}
Expand All @@ -435,7 +435,7 @@ impl<'a> SquashfsReadFile<'a> {
}
}

impl<'a> Read for SquashfsReadFile<'a> {
impl<'a, 'b> Read for SquashfsReadFile<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
// file was fully consumed
if self.bytes_available == 0 {
Expand Down
28 changes: 14 additions & 14 deletions src/v4/filesystem/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use crate::v4::{
/// fs.push_file(std::io::Cursor::new(vec![0x00, 0x01]), "usr/bin/file", header);
/// ```
#[derive(Debug)]
pub struct FilesystemWriter<'a> {
pub struct FilesystemWriter<'a, 'b> {
pub(crate) kind: Kind,
/// The size of a data block in bytes. Must be a power of two between 4096 (4k) and 1048576 (1 MiB).
pub(crate) block_size: u32,
Expand All @@ -75,13 +75,13 @@ pub struct FilesystemWriter<'a> {
/// Compressor used when writing
pub(crate) fs_compressor: FilesystemCompressor,
/// All files and directories in filesystem, including root
pub(crate) root: Nodes<SquashfsFileWriter<'a>>,
pub(crate) root: Nodes<SquashfsFileWriter<'a, 'b>>,
/// The log2 of the block size. If the two fields do not agree, the archive is considered corrupted.
pub(crate) block_log: u16,
pub(crate) pad_len: u32,
}

impl<'a> Default for FilesystemWriter<'a> {
impl<'a, 'b> Default for FilesystemWriter<'a, 'b> {
/// Create default FilesystemWriter
///
/// block_size: [`DEFAULT_BLOCK_SIZE`], compressor: default XZ compression, no nodes,
Expand All @@ -103,7 +103,7 @@ impl<'a> Default for FilesystemWriter<'a> {
}
}

impl<'a> FilesystemWriter<'a> {
impl<'a, 'b> FilesystemWriter<'a, 'b> {
/// Set block size
///
/// # Panics
Expand Down Expand Up @@ -200,7 +200,7 @@ impl<'a> FilesystemWriter<'a> {
}

/// Inherit filesystem structure and properties from `reader`
pub fn from_fs_reader(reader: &'a FilesystemReader) -> Result<Self, BackhandError> {
pub fn from_fs_reader(reader: &'a FilesystemReader<'b>) -> Result<Self, BackhandError> {
let mut root: Vec<Node<_>> = reader
.root
.nodes
Expand Down Expand Up @@ -245,7 +245,7 @@ impl<'a> FilesystemWriter<'a> {
fn mut_node<S: AsRef<Path>>(
&mut self,
find_path: S,
) -> Option<&mut Node<SquashfsFileWriter<'a>>> {
) -> Option<&mut Node<SquashfsFileWriter<'a, 'b>>> {
//the search path root prefix is optional, so remove it if present to
//not affect the search
let find_path = normalize_squashfs_path(find_path.as_ref()).ok()?;
Expand All @@ -256,7 +256,7 @@ impl<'a> FilesystemWriter<'a> {
&mut self,
path: P,
header: NodeHeader,
node: InnerNode<SquashfsFileWriter<'a>>,
node: InnerNode<SquashfsFileWriter<'a, 'b>>,
) -> Result<(), BackhandError> {
// create gid id
self.lookup_add_id(header.gid);
Expand All @@ -273,7 +273,7 @@ impl<'a> FilesystemWriter<'a> {
/// The `uid` and `gid` in `header` are added to FilesystemWriters id's
pub fn push_file<P: AsRef<Path>>(
&mut self,
reader: impl Read + 'a,
reader: impl Read + 'b,
path: P,
header: NodeHeader,
) -> Result<(), BackhandError> {
Expand All @@ -287,7 +287,7 @@ impl<'a> FilesystemWriter<'a> {
pub fn mut_file<S: AsRef<Path>>(
&mut self,
find_path: S,
) -> Option<&mut SquashfsFileWriter<'a>> {
) -> Option<&mut SquashfsFileWriter<'a, 'b>> {
self.mut_node(find_path).and_then(|node| {
if let InnerNode::File(file) = &mut node.inner {
Some(file)
Expand All @@ -301,7 +301,7 @@ impl<'a> FilesystemWriter<'a> {
pub fn replace_file<S: AsRef<Path>>(
&mut self,
find_path: S,
reader: impl Read + 'a,
reader: impl Read + 'b,
) -> Result<(), BackhandError> {
let file = self
.mut_file(find_path)
Expand Down Expand Up @@ -427,7 +427,7 @@ impl<'a> FilesystemWriter<'a> {
compressor: FilesystemCompressor,
block_size: u32,
writer: &mut W,
data_writer: &mut DataWriter,
data_writer: &mut DataWriter<'b>,
) -> Result<(), BackhandError> {
let files = self
.root
Expand Down Expand Up @@ -473,16 +473,16 @@ impl<'a> FilesystemWriter<'a> {
/// keeps track of parent directories by calling this function on all nodes of a dir to get only
/// the nodes, but going into the child dirs in the case that it contains a child dir.
#[allow(clippy::too_many_arguments)]
fn write_inode_dir<'b>(
&'b self,
fn write_inode_dir<'c>(
&'c self,
inode_writer: &'_ mut MetadataWriter,
dir_writer: &'_ mut MetadataWriter,
parent_node_id: u32,
node_id: NonZeroUsize,
superblock: &SuperBlock,
kind: &Kind,
id_table: &Vec<Id>,
) -> Result<Entry<'b>, BackhandError> {
) -> Result<Entry<'c>, BackhandError> {
let node = &self.root.node(node_id).unwrap();
let filename = node.fullpath.file_name().unwrap_or(OsStr::new("/"));
//if not a dir, return the entry
Expand Down
1 change: 0 additions & 1 deletion src/v4/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ pub trait SquashFsReader: BufReadSeek {

let block_count = (size as f32 / METADATA_MAXSIZE as f32).ceil() as u64;

let ptr = ptr;
trace!("ptr: {:02x?}", ptr);
let table = self.metadata_with_count::<T>(superblock, ptr, block_count, kind)?;

Expand Down
27 changes: 13 additions & 14 deletions src/v4/squashfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ pub(crate) struct Cache {
/// Squashfs Image initial read information
///
/// See [`FilesystemReader`] for a representation with the data extracted and uncompressed.
pub struct Squashfs {
pub struct Squashfs<'b> {
pub kind: Kind,
pub superblock: SuperBlock,
/// Compression options that are used for the Compressor located after the Superblock
Expand All @@ -212,16 +212,16 @@ pub struct Squashfs {
/// Id Lookup Table
pub id: Vec<Id>,
//file reader
file: Box<dyn BufReadSeek>,
file: Box<dyn BufReadSeek + 'b>,
}

impl Squashfs {
impl<'b> Squashfs<'b> {
/// Read Superblock and Compression Options at current `reader` offset without parsing inodes
/// and dirs
///
/// Used for unsquashfs (extraction and --stat)
pub fn superblock_and_compression_options(
reader: &mut Box<dyn BufReadSeek>,
reader: &mut Box<dyn BufReadSeek + 'b>,
kind: &Kind,
) -> Result<(SuperBlock, Option<CompressionOptions>), BackhandError> {
// Parse SuperBlock
Expand Down Expand Up @@ -281,17 +281,17 @@ impl Squashfs {
/// Create `Squashfs` from `Read`er, with the resulting squashfs having read all fields needed
/// to regenerate the original squashfs and interact with the fs in memory without needing to
/// read again from `Read`er. `reader` needs to start with the beginning of the Image.
pub fn from_reader(reader: impl BufReadSeek + 'static) -> Result<Squashfs, BackhandError> {
pub fn from_reader(reader: impl BufReadSeek + 'b) -> Result<Self, BackhandError> {
Self::from_reader_with_offset(reader, 0)
}

/// Same as [`Self::from_reader`], but seek'ing to `offset` in `reader` before Reading
///
/// Uses default [`Kind`]: [`LE_V4_0`]
pub fn from_reader_with_offset(
reader: impl BufReadSeek + 'static,
reader: impl BufReadSeek + 'b,
offset: u64,
) -> Result<Squashfs, BackhandError> {
) -> Result<Self, BackhandError> {
Self::from_reader_with_offset_and_kind(
reader,
offset,
Expand All @@ -303,11 +303,11 @@ impl Squashfs {

/// Same as [`Self::from_reader_with_offset`], but including custom `kind`
pub fn from_reader_with_offset_and_kind(
reader: impl BufReadSeek + 'static,
reader: impl BufReadSeek + 'b,
offset: u64,
kind: Kind,
) -> Result<Squashfs, BackhandError> {
let reader: Box<dyn BufReadSeek> = if offset == 0 {
) -> Result<Self, BackhandError> {
let reader: Box<dyn BufReadSeek + 'b> = if offset == 0 {
Box::new(reader)
} else {
let reader = SquashfsReaderWithOffset::new(reader, offset)?;
Expand All @@ -317,9 +317,9 @@ impl Squashfs {
}

fn inner_from_reader_with_offset_and_kind(
mut reader: Box<dyn BufReadSeek>,
mut reader: Box<dyn BufReadSeek + 'b>,
kind: Kind,
) -> Result<Squashfs, BackhandError> {
) -> Result<Self, BackhandError> {
let (superblock, compression_options) =
Self::superblock_and_compression_options(&mut reader, &kind)?;

Expand Down Expand Up @@ -621,8 +621,7 @@ impl Squashfs {
/// Convert into [`FilesystemReader`] by extracting all file bytes and converting into a filesystem
/// like structure in-memory
#[instrument(skip_all)]
pub fn into_filesystem_reader(self) -> Result<FilesystemReader, BackhandError> {
info!("creating fs tree");
pub fn into_filesystem_reader(self) -> Result<FilesystemReader<'b>, BackhandError> {
let mut root = Nodes::new_root(NodeHeader::from_inode(self.root_inode.header, &self.id));
self.extract_dir(
&mut PathBuf::from("/"),
Expand Down

0 comments on commit abeeaea

Please sign in to comment.