Skip to content

Commit

Permalink
feat: Add deflate64 method (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime authored Jan 27, 2024
1 parent 0ec8144 commit 1507282
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"rust-analyzer.cargo.features": ["default", "lzma"]
"rust-analyzer.cargo.features": ["default", "lzma", "deflate64"]
}
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/jean/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ humansize = "2.1.3"
positioned-io.workspace = true
indicatif = "0.17.7"
tracing-subscriber = "0.3.18"
cfg-if = "1.0.0"

[features]
default = ["lzma"]
deflate = ["rc-zip/deflate"]
deflate64 = ["rc-zip/deflate64"]
lzma = ["rc-zip/lzma"]
60 changes: 32 additions & 28 deletions crates/jean/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use cfg_if::cfg_if;
use clap::{Parser, Subcommand};
use humansize::{format_size, BINARY};
use rc_zip::{prelude::*, EntryContents};
Expand Down Expand Up @@ -147,6 +148,10 @@ fn do_main(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
size = format_size(entry.inner.uncompressed_size, BINARY),
);
if verbose {
print!(
" ({} compressed)",
format_size(entry.inner.compressed_size, BINARY)
);
print!(
" {modified} {uid} {gid}",
modified = entry.modified(),
Expand Down Expand Up @@ -210,39 +215,38 @@ fn do_main(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
match entry.contents() {
EntryContents::Symlink => {
num_symlinks += 1;
#[cfg(windows)]
{
let path = dir.join(entry_name);
std::fs::create_dir_all(
path.parent()
.expect("all full entry paths should have parent paths"),
)?;
let mut entry_writer = File::create(path)?;
let mut entry_reader = entry.reader();
std::io::copy(&mut entry_reader, &mut entry_writer)?;
}

#[cfg(not(windows))]
{
let path = dir.join(entry_name);
std::fs::create_dir_all(
path.parent()
.expect("all full entry paths should have parent paths"),
)?;
if let Ok(metadata) = std::fs::symlink_metadata(&path) {
if metadata.is_file() {
std::fs::remove_file(&path)?;
cfg_if! {
if #[cfg(windows)] {
let path = dir.join(entry_name);
std::fs::create_dir_all(
path.parent()
.expect("all full entry paths should have parent paths"),
)?;
let mut entry_writer = File::create(path)?;
let mut entry_reader = entry.reader();
std::io::copy(&mut entry_reader, &mut entry_writer)?;
} else {
let path = dir.join(entry_name);
std::fs::create_dir_all(
path.parent()
.expect("all full entry paths should have parent paths"),
)?;
if let Ok(metadata) = std::fs::symlink_metadata(&path) {
if metadata.is_file() {
std::fs::remove_file(&path)?;
}
}
}

let mut src = String::new();
entry.reader().read_to_string(&mut src)?;
let mut src = String::new();
entry.reader().read_to_string(&mut src)?;

// validate pointing path before creating a symbolic link
if src.contains("..") {
continue;
// validate pointing path before creating a symbolic link
if src.contains("..") {
continue;
}
std::os::unix::fs::symlink(src, &path)?;
}
std::os::unix::fs::symlink(src, &path)?;
}
}
EntryContents::Directory => {
Expand Down
6 changes: 4 additions & 2 deletions crates/rc-zip/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ num_enum = "0.7.2"
byteorder = "1.5.0"
cfg-if = "1.0.0"
lzma-rs = { version = "0.3.0", features = ["stream"], optional = true }
deflate64 = { version = "0.1.7", optional = true }

[features]
default = ["sync", "file", "deflate"]
sync = []
file = ["positioned-io"]
deflate = ["flate2"]
lzma = ["lzma-rs"]
deflate = ["dep:flate2"]
lzma = ["dep:lzma-rs"]
deflate64 = ["dep:deflate64"]

[dev-dependencies]
tracing-test = "0.2.4"
7 changes: 3 additions & 4 deletions crates/rc-zip/src/reader/sync/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,12 @@ impl LimitedReader {

impl io::Read for LimitedReader {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if self.inner.available_space() == 0 {
self.inner.shift();
}

let len = cmp::min(buf.len() as u64, self.remaining) as usize;
tracing::trace!(%len, buf_len = buf.len(), remaining = self.remaining, available_data = self.inner.available_data(), available_space = self.inner.available_space(), "computing len");

let res = self.inner.read(&mut buf[..len]);
if let Ok(n) = res {
tracing::trace!(%n, "read ok");
self.remaining -= n as u64;
}
res
Expand Down
22 changes: 22 additions & 0 deletions crates/rc-zip/src/reader/sync/entry_reader/deflate64_dec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::io::{BufReader, Read};

use deflate64::Deflate64Decoder;

use crate::reader::sync::{Decoder, LimitedReader};

impl<R> Decoder<R> for Deflate64Decoder<BufReader<R>>
where
R: Read,
{
fn into_inner(self: Box<Self>) -> R {
Self::into_inner(*self).into_inner()
}

fn get_mut(&mut self) -> &mut R {
Self::get_mut(self).get_mut()
}
}

pub(crate) fn mk_decoder(r: LimitedReader) -> impl Decoder<LimitedReader> {
Deflate64Decoder::new(r)
}
18 changes: 17 additions & 1 deletion crates/rc-zip/src/reader/sync/entry_reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ mod lzma_dec;
#[cfg(feature = "deflate")]
mod deflate_dec;

#[cfg(feature = "deflate64")]
mod deflate64_dec;

use cfg_if::cfg_if;
use nom::Offset;
use std::io;
Expand Down Expand Up @@ -102,7 +105,11 @@ where
} => {
{
let buffer = decoder.get_mut().get_mut();
if !self.eof && buffer.available_space() > 0 {
if !self.eof && buffer.available_data() == 0 {
if buffer.available_space() == 0 {
buffer.shift();
}

match self.rd.read(buffer.space())? {
0 => {
self.eof = true;
Expand Down Expand Up @@ -271,6 +278,15 @@ where
}
}
}
Method::Deflate64 => {
cfg_if! {
if #[cfg(feature = "deflate64")] {
Box::new(deflate64_dec::mk_decoder(limited_reader))
} else {
return Err(Error::method_not_enabled(self.method));
}
}
}
Method::Lzma => {
cfg_if! {
if #[cfg(feature = "lzma")] {
Expand Down
12 changes: 12 additions & 0 deletions crates/rc-zip/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,18 @@ fn test_cases() -> Vec<ZipTest> {
}],
..Default::default()
},
#[cfg(feature = "deflate64")]
ZipTest {
source: ZipSource::File("found-me-deflate64.zip"),
expected_encoding: Some(Encoding::Utf8),
files: vec![ZipTestFile {
name: "found-me.txt",
content: FileContent::Bytes("Oh no, you found me\n".repeat(5000).into()),
modified: Some(date((2024, 1, 26), (17, 14, 36), 0, time_zone(0)).unwrap()),
..Default::default()
}],
..Default::default()
},
]
}

Expand Down

0 comments on commit 1507282

Please sign in to comment.