Skip to content

Commit dddc115

Browse files
authored
Merge branch 'main' into landlock
2 parents 1ada8f9 + 3aada32 commit dddc115

4 files changed

Lines changed: 58 additions & 33 deletions

File tree

Cargo.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ strum = { version = "0.28.0", features = ["derive"] }
4545
tar = "0.4.45"
4646
tempfile = "3.27.0"
4747
time = { version = "0.3.47", default-features = false }
48-
unrar = { version = "0.5.8", optional = true }
48+
unrar = { package = "unrar-ng", version = "0.7.6", optional = true }
4949
zip = { version = "8.6.0", default-features = false, features = [
5050
"time",
5151
"aes-crypto",
@@ -60,7 +60,7 @@ infer = "0.19.0"
6060
insta = { version = "1.47.2", features = ["filters"] }
6161
itertools = "0.14.0"
6262
memchr = "2.8.0"
63-
parse-display = "0.9.1"
63+
parse-display = "0.11.0"
6464
pretty_assertions = "1.4.1"
6565
proptest = "1.11.0"
6666
rand = { version = "0.9.4", default-features = false, features = [

src/archive/rar.rs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
//! Contains RAR-specific building and unpacking functions
22
3-
use std::path::Path;
3+
use std::path::{Path, PathBuf};
44

5-
use unrar::Archive;
5+
use unrar::{
6+
Archive, ExtractEvent,
7+
error::{Code, UnrarError, When},
8+
};
69

710
use crate::{
8-
error::{Error, Result},
11+
error::{Error, FinalError, Result},
912
info,
1013
list::{FileInArchive, ListFileType},
11-
utils::BytesFmt,
14+
utils::{BytesFmt, PathFmt},
1215
};
1316

1417
/// Unpacks the archive given by `archive_path` into the folder given by `output_folder`.
@@ -19,24 +22,46 @@ pub fn unpack_archive(archive_path: &Path, output_folder: &Path, password: Optio
1922
None => Archive::new(archive_path),
2023
};
2124

22-
let mut archive = archive.open_for_processing()?;
23-
let mut files_unpacked = 0;
25+
let archive = archive.open_for_processing()?;
26+
27+
let mut files_unpacked: u64 = 0;
28+
let mut first_err: Option<(PathBuf, i32)> = None;
2429

25-
while let Some(header) = archive.read_header()? {
26-
let entry = header.entry();
27-
archive = if entry.is_file() {
30+
let cb_result = archive.extract_all_with_callback(output_folder, |event| match event {
31+
ExtractEvent::Ok { filename, size } => {
32+
info!("extracted ({}) {}", BytesFmt(size), PathFmt(&filename));
33+
files_unpacked += 1;
34+
true
35+
}
36+
ExtractEvent::Err { filename, error_code } => {
37+
first_err = Some((filename, error_code));
38+
// Returning false cancels the rest of the extraction so any
39+
// additional per-file errors don't get silently swallowed.
40+
false
41+
}
42+
ExtractEvent::LargeDictWarning {
43+
dict_size_kb,
44+
max_dict_size_kb,
45+
} => {
2846
info!(
29-
"extracted ({}) {}",
30-
BytesFmt(entry.unpacked_size),
31-
entry.filename.display(),
47+
"archive requires {} KiB dictionary; this build supports up to {} KiB",
48+
dict_size_kb, max_dict_size_kb,
3249
);
33-
files_unpacked += 1;
34-
header.extract_with_base(output_folder)?
35-
} else {
36-
header.skip()?
37-
};
38-
}
50+
// Reject the oversized dictionary so the DLL fails the
51+
// operation with Code::LargeDict instead of silently
52+
// proceeding with a result it cannot actually produce.
53+
false
54+
}
55+
_ => true,
56+
});
3957

58+
if let Some((path, code)) = first_err {
59+
let inner = UnrarError::from(Code::from(code), When::Process).to_string();
60+
return Err(Error::Custom {
61+
reason: FinalError::with_title(format!("failed to extract {}", PathFmt(&path))).detail(inner),
62+
});
63+
}
64+
let _status = cb_result?;
4065
Ok(files_unpacked)
4166
}
4267

src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ impl From<zip::result::ZipError> for Error {
249249
impl From<unrar::error::UnrarError> for Error {
250250
fn from(err: unrar::error::UnrarError) -> Self {
251251
Self::Custom {
252-
reason: FinalError::with_title("Unexpected error in rar archive").detail(format!("{:?}", err.code)),
252+
reason: FinalError::with_title("Unexpected error in rar archive").detail(err.to_string()),
253253
}
254254
}
255255
}

0 commit comments

Comments
 (0)