Skip to content

Commit

Permalink
More movement
Browse files Browse the repository at this point in the history
  • Loading branch information
wcampbell0x2a committed Oct 12, 2023
1 parent 903c0d1 commit 5220fda
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 256 deletions.
110 changes: 75 additions & 35 deletions src/bin/unsquashfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ use std::path::{Component, Path, PathBuf};
use std::process::ExitCode;
use std::sync::Mutex;

use backhand::compressor::CompressionOptions;
use backhand::kind::Kind;
use backhand::{
BufReadSeek, FilesystemReader, InnerNode, MultiFilesystemReader, MultiSquashfs, Node,
NodeHeader, Squashfs, SquashfsBlockDevice, SquashfsCharacterDevice, SquashfsDir,
SquashfsFileReader, SquashfsSymlink,
BufReadSeek, FilesystemReader, InnerNode, MultiFilesystemReader, MultiSquashfs,
MultiSuperBlock, Node, NodeHeader, Squashfs, SquashfsBlockDevice, SquashfsCharacterDevice,
SquashfsDir, SquashfsFileReader, SquashfsSymlink,
};
use clap::builder::PossibleValuesParser;
use clap::{CommandFactory, Parser};
Expand Down Expand Up @@ -401,50 +402,89 @@ fn stat(args: Args, mut file: BufReader<File>, kind: Kind) {
file.seek(SeekFrom::Start(args.offset)).unwrap();
let mut reader: Box<dyn BufReadSeek> = Box::new(file);
let (superblock, compression_options) =
Squashfs::superblock_and_compression_options(&mut reader, &kind).unwrap();
MultiSuperBlock::superblock_and_compression_options(&mut reader, &kind).unwrap();

// show info about flags
match superblock {
MultiSuperBlock::V3(v3) => stat_v3(v3),
MultiSuperBlock::V4(v4) => stat_v4(v4, compression_options),
}
}

fn stat_v4(superblock: backhand::v4::SuperBlock, co: Option<CompressionOptions>) {
println!("{superblock:#08x?}");

// // show info about compression options
// println!("Compression Options: {compression_options:#x?}");
// show info about compression options
println!("Compression Options: {co:#x?}");

// show info about flags
if superblock.inodes_uncompressed() {
println!("flag: inodes uncompressed");
}

if superblock.data_block_stored_uncompressed() {
println!("flag: data blocks stored uncompressed");
}

if superblock.fragments_stored_uncompressed() {
println!("flag: fragments stored uncompressed");
}

if superblock.fragments_are_not_used() {
println!("flag: fragments are not used");
}

if superblock.fragments_are_always_generated() {
println!("flag: fragments are always generated");
}

if superblock.duplicate_data_removed() {
println!("flag: data has been duplicated");
}

if superblock.nfs_export_table_exists() {
println!("flag: nfs export table exists");
}

if superblock.xattrs_are_stored_uncompressed() {
println!("flag: xattrs are stored uncompressed");
}

// // show info about flags
// if superblock.inodes_uncompressed() {
// println!("flag: inodes uncompressed");
// }
if superblock.compressor_options_are_present() {
println!("flag: compressor options are present");
}
}

// if superblock.data_block_stored_uncompressed() {
// println!("flag: data blocks stored uncompressed");
// }
fn stat_v3(superblock: backhand::v3::SuperBlock) {
println!("{superblock:#08x?}");

// if superblock.fragments_stored_uncompressed() {
// println!("flag: fragments stored uncompressed");
// }
// show info about flags
if superblock.inodes_uncompressed() {
println!("flag: inodes uncompressed");
}

// if superblock.fragments_are_not_used() {
// println!("flag: fragments are not used");
// }
if superblock.data_block_stored_uncompressed() {
println!("flag: data blocks stored uncompressed");
}

// if superblock.fragments_are_always_generated() {
// println!("flag: fragments are always generated");
// }
if superblock.fragments_stored_uncompressed() {
println!("flag: fragments stored uncompressed");
}

// if superblock.data_has_been_duplicated() {
// println!("flag: data has been duplicated");
// }
if superblock.fragments_are_not_used() {
println!("flag: fragments are not used");
}

// if superblock.nfs_export_table_exists() {
// println!("flag: nfs export table exists");
// }
if superblock.fragments_are_always_generated() {
println!("flag: fragments are always generated");
}

// if superblock.xattrs_are_stored_uncompressed() {
// println!("flag: xattrs are stored uncompressed");
// }
if superblock.duplicate_data_removed() {
println!("flag: data duplicated was removed");
}

// if superblock.compressor_options_are_present() {
// println!("flag: compressor options are present");
// }
if superblock.nfs_export_table_exists() {
println!("flag: nfs export table exists");
}
}

fn set_attributes(
Expand Down
29 changes: 29 additions & 0 deletions src/bufread.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::io::{BufRead, Read, Seek, Write};

/// Similar to to Seek, but only require the `rewind` function
pub trait SeekRewind {
/// Set the IO position back at the start
fn rewind(&mut self) -> std::io::Result<()>;
}

impl<T: Seek> SeekRewind for T {
fn rewind(&mut self) -> std::io::Result<()> {
<Self as Seek>::rewind(self)
}
}

/// Pseudo-Trait for Read + SeekRewind
pub trait ReadRewind: Read + SeekRewind {}
impl<T: Read + SeekRewind> ReadRewind for T {}

/// Pseudo-Trait for BufRead + SeekRewind
pub trait BufReadRewind: BufRead + SeekRewind {}
impl<T: BufRead + SeekRewind> BufReadRewind for T {}

/// Pseudo-Trait for BufRead + Seek
pub trait BufReadSeek: BufRead + Seek + Send {}
impl<T: BufRead + Seek + Send> BufReadSeek for T {}

/// Pseudo-Trait for Write + Seek
pub trait WriteSeek: Write + Seek {}
impl<T: Write + Seek> WriteSeek for T {}
16 changes: 16 additions & 0 deletions src/flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#[rustfmt::skip]
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub enum Flags {
InodesStoredUncompressed = 0b0000_0000_0000_0001,
DataBlockStoredUncompressed = 0b0000_0000_0000_0010,
Unused = 0b0000_0000_0000_0100,
FragmentsStoredUncompressed = 0b0000_0000_0000_1000,
FragmentsAreNotUsed = 0b0000_0000_0001_0000,
FragmentsAreAlwaysGenerated = 0b0000_0000_0010_0000,
DataHasBeenDeduplicated = 0b0000_0000_0100_0000,
NFSExportTableExists = 0b0000_0000_1000_0000,
XattrsAreStoredUncompressed = 0b0000_0001_0000_0000,
NoXattrsInArchive = 0b0000_0010_0000_0000,
CompressorOptionsArePresent = 0b0000_0100_0000_0000,
}
29 changes: 27 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,18 @@
#[doc = include_str!("../README.md")]
type _ReadmeTest = ();

pub mod bufread;
pub mod compressor;
pub mod error;
mod flags;
pub mod kinds;
pub mod v3;
pub mod v4;

use compressor::CompressionOptions;
use kind::Kind;
use kinds::Version;

pub use crate::bufread::BufReadSeek;
pub use crate::compressor::{CompressionExtra, ExtraXz, FilesystemCompressor};
pub use crate::v4::data::DataSize;
pub use crate::v4::export::Export;
Expand All @@ -76,7 +79,6 @@ pub use crate::v4::filesystem::writer::FilesystemWriter;
pub use crate::v4::fragment::Fragment;
pub use crate::v4::id::Id;
pub use crate::v4::inode::{BasicFile, Inode};
pub use crate::v4::reader::BufReadSeek;
pub use crate::v4::squashfs::{
Squashfs, SuperBlock, DEFAULT_BLOCK_SIZE, DEFAULT_PAD_LEN, MAX_BLOCK_SIZE, MIN_BLOCK_SIZE,
};
Expand All @@ -96,6 +98,29 @@ pub mod compression {
};
}

pub enum MultiSuperBlock {
V3(v3::SuperBlock),
V4(v4::SuperBlock),
}

impl MultiSuperBlock {
pub fn superblock_and_compression_options<'a>(
reader: &mut Box<dyn BufReadSeek + 'a>,
kind: &Kind,
) -> Result<(Self, Option<CompressionOptions>), BackhandError> {
match kind.inner.version {
Version::V3_0 => {
let (s, comp) = v3::Squashfs::superblock_and_compression_options(reader, kind)?;
Ok((MultiSuperBlock::V3(s), comp))
}
Version::V4_0 => {
let (s, comp) = v4::Squashfs::superblock_and_compression_options(reader, kind)?;
Ok((MultiSuperBlock::V4(s), comp))
}
}
}
}

pub enum MultiSquashfs<'a> {
V3(v3::Squashfs<'a>),
V4(v4::Squashfs<'a>),
Expand Down
2 changes: 1 addition & 1 deletion src/v3/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use std::io::{Read, Seek, Write};
use deku::prelude::*;
use tracing::instrument;

use crate::bufread::WriteSeek;
use crate::compressor::{CompressionAction, FilesystemCompressor};
use crate::error::BackhandError;
use crate::v3::filesystem::reader::SquashfsRawData;
use crate::v3::fragment::Fragment;
use crate::v3::reader::WriteSeek;

// bitflag for data size field in inode for signifying that the data is uncompressed
const DATA_STORED_UNCOMPRESSED: u32 = 1 << 24;
Expand Down
2 changes: 1 addition & 1 deletion src/v3/filesystem/reader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::io::{Read, SeekFrom};
use std::sync::Mutex;

use crate::bufread::BufReadSeek;
use crate::compressor::{CompressionOptions, Compressor};
use crate::error::BackhandError;
use crate::kinds::Kind;
Expand All @@ -9,7 +10,6 @@ use crate::v3::filesystem::node::Nodes;
use crate::v3::fragment::Fragment;
use crate::v3::id::Id;
use crate::v3::inode::BasicFile;
use crate::v3::reader::BufReadSeek;
use crate::v3::squashfs::Cache;
use crate::v3::{Node, Squashfs, SquashfsFileReader};

Expand Down
1 change: 0 additions & 1 deletion src/v3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ pub use filesystem::reader::{FilesystemReader, FilesystemReaderFile, SquashfsRea
pub use fragment::Fragment;
pub use id::Id;
pub use inode::{BasicFile, Inode};
pub use reader::BufReadSeek;
pub use squashfs::{
Squashfs, SuperBlock, DEFAULT_BLOCK_SIZE, DEFAULT_PAD_LEN, MAX_BLOCK_SIZE, MIN_BLOCK_SIZE,
};
29 changes: 1 addition & 28 deletions src/v3/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use deku::prelude::*;
use rustc_hash::FxHashMap;
use tracing::{error, instrument, trace};

use crate::bufread::BufReadSeek;
use crate::error::BackhandError;
use crate::kinds::Kind;
use crate::v3::export::Export;
Expand Down Expand Up @@ -58,34 +59,6 @@ impl<R: BufReadSeek> Seek for SquashfsReaderWithOffset<R> {
}
}

/// Similar to to Seek, but only require the `rewind` function
pub trait SeekRewind {
/// Set the IO position back at the start
fn rewind(&mut self) -> std::io::Result<()>;
}

impl<T: Seek> SeekRewind for T {
fn rewind(&mut self) -> std::io::Result<()> {
<Self as Seek>::rewind(self)
}
}

/// Pseudo-Trait for Read + SeekRewind
pub trait ReadRewind: Read + SeekRewind {}
impl<T: Read + SeekRewind> ReadRewind for T {}

/// Pseudo-Trait for BufRead + SeekRewind
pub trait BufReadRewind: BufRead + SeekRewind {}
impl<T: BufRead + SeekRewind> BufReadRewind for T {}

/// Pseudo-Trait for BufRead + Seek
pub trait BufReadSeek: BufRead + Seek + Send {}
impl<T: BufRead + Seek + Send> BufReadSeek for T {}

/// Pseudo-Trait for Write + Seek
pub trait WriteSeek: Write + Seek {}
impl<T: Write + Seek> WriteSeek for T {}

impl<T: BufReadSeek> SquashFsReader for T {}

/// Squashfs data extraction methods implemented over [`Read`] and [`Seek`]
Expand Down
Loading

0 comments on commit 5220fda

Please sign in to comment.