Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add deflate64 method #43

Merged
merged 5 commits into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading