mirror of
https://codeberg.org/icewind/logsmash.git
synced 2026-06-03 10:04:12 +02:00
add 7z archive support
This commit is contained in:
parent
bee8062f3a
commit
f47002642d
5 changed files with 215 additions and 14 deletions
|
|
@ -25,6 +25,8 @@ pub enum ReadError {
|
|||
Zip(#[from] ZipError),
|
||||
#[error(transparent)]
|
||||
Zstd(#[from] FrameDecoderError),
|
||||
#[error(transparent)]
|
||||
SevenZip(#[from] sevenz_rust2::Error),
|
||||
#[error("archive contains no files")]
|
||||
NoFiles,
|
||||
#[error("log file contained non-utf8 characters: {0:#}")]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::error::ReadError;
|
||||
use itertools::Either;
|
||||
use sevenz_rust2::{Password, SevenZReader};
|
||||
use std::borrow::Cow;
|
||||
use std::io::{Read, Seek};
|
||||
use std::iter::empty;
|
||||
|
|
@ -129,3 +130,61 @@ impl<R: Read> Archive for TarArchive<R> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SevenZipArchive<R: Read + Seek>(Mutex<SevenZReader<R>>);
|
||||
|
||||
impl<R: Read + Seek> SevenZipArchive<R> {
|
||||
pub fn new(reader: R) -> Result<Self, ReadError> {
|
||||
Ok(Self(Mutex::new(SevenZReader::new(
|
||||
reader,
|
||||
Password::empty(),
|
||||
)?)))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SevenZipEntry<'a, R: Read + Seek> {
|
||||
name: String,
|
||||
reader: &'a Mutex<SevenZReader<R>>,
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> ArchiveEntry for SevenZipEntry<'_, R> {
|
||||
fn name(&self) -> Cow<str> {
|
||||
self.name.as_str().into()
|
||||
}
|
||||
|
||||
fn extract(self) -> Result<Vec<u8>, ReadError> {
|
||||
let mut buff = Vec::new();
|
||||
let mut reader = self.reader.lock().unwrap();
|
||||
reader.for_each_entries(|entry, reader| {
|
||||
if entry.name() == self.name.as_str() {
|
||||
reader.read_to_end(&mut buff)?;
|
||||
}
|
||||
Ok(true)
|
||||
})?;
|
||||
Ok(buff)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> Archive for SevenZipArchive<R> {
|
||||
type Entry<'a>
|
||||
= SevenZipEntry<'a, R>
|
||||
where
|
||||
R: 'a;
|
||||
|
||||
fn entries(&mut self) -> impl Iterator<Item = Self::Entry<'_>> {
|
||||
let names: Vec<_> = self
|
||||
.0
|
||||
.lock()
|
||||
.unwrap()
|
||||
.archive()
|
||||
.files
|
||||
.iter()
|
||||
.filter(|file| !file.is_directory())
|
||||
.map(|f| f.name.clone())
|
||||
.collect();
|
||||
names.into_iter().map(|name| SevenZipEntry {
|
||||
name,
|
||||
reader: &self.0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ mod archive;
|
|||
pub mod logline;
|
||||
|
||||
use crate::error::ReadError;
|
||||
use crate::logfile::archive::{Archive, ArchiveEntry, TarArchive, ZipArchive};
|
||||
use crate::logfile::archive::{Archive, ArchiveEntry, SevenZipArchive, TarArchive, ZipArchive};
|
||||
use bzip2_rs::DecoderReader;
|
||||
use dialoguer::Select;
|
||||
use flate2::read::GzDecoder;
|
||||
|
|
@ -36,6 +36,9 @@ impl LogFile {
|
|||
if path.ends_with(".zip") {
|
||||
let mut zip = ZipArchive::new(file)?;
|
||||
return select_file(&mut zip);
|
||||
} else if path.ends_with(".7z") {
|
||||
let mut zip = SevenZipArchive::new(file)?;
|
||||
return select_file(&mut zip);
|
||||
}
|
||||
|
||||
if let Some(path) = path.strip_suffix(".gz") {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue