mirror of
https://github.com/LisherSong/ps5-web-file-manager.git
synced 2026-10-06 07:00:28 +02:00
fix(extract): handle multi-volume split segments in scan and extract
unrar in RAR_OM_EXTRACT mode presents a file that spans volumes as several header segments with the SAME name, flagged RHDF_SPLITBEFORE/ SPLITAFTER. The scan dedup rejected the continuation segments as "duplicate entry name" and the whole multi-volume extract failed. Fix: segments after the first (RHDF_SPLITBEFORE set) skip the normalize/dedup/size/limit accounting in scan (the first segment already carries the full size) and, in extract, still call RARProcessFile(EXTRACT) to drive the volume chain but are not counted or size-accumulated. Verified against real fixtures (tests/fixtures-real/, generated by tests/make-rar-fixtures.bat on the user's RAR 7.23): a 512 KB file split across vol.part1/2/3.rar extracts whole (status ZIPX_OK, big.bin + root.txt). Host suite now 70 ZIP + 24 RAR checks, 0 failures.
This commit is contained in:
1 parent
91757bfd02
commit
452b9b0187
2 files changed
+30
-1
No files matched your search
@@ -660,6 +660,21 @@ scan_archive(HANDLE hArc, rarx_ctx_t *c) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Multi-volume: a file spanning volumes is presented as several header
|
||||
segments with the SAME name. Segments after the first carry
|
||||
RHDF_SPLITBEFORE; they must drive the engine forward (SKIP) but must
|
||||
not be counted, deduped or size-accumulated again. The first segment
|
||||
already carries the full file size. */
|
||||
if(hdr.Flags & RHDF_SPLITBEFORE) {
|
||||
rc = RARProcessFile(hArc, RAR_SKIP, NULL, NULL);
|
||||
if(rc != ERAR_SUCCESS && rc != ERAR_END_ARCHIVE) {
|
||||
ret = -1;
|
||||
rar_translate_error(rc, hdr.FileName, c);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(normalize_name(hdr.FileName, name, sizeof(name), &is_dir, &depth, c)) {
|
||||
ret = -1;
|
||||
break;
|
||||
@@ -765,6 +780,18 @@ extract_archive(HANDLE hArc, rarx_ctx_t *c) {
|
||||
}
|
||||
|
||||
is_dir = (hdr.Flags & RHDF_DIRECTORY) ? 1 : 0;
|
||||
/* Split continuation segments still need RARProcessFile(EXTRACT) so the
|
||||
volume chain is driven and the file is completed, but only the first
|
||||
segment is counted / reported / size-accumulated. */
|
||||
if(hdr.Flags & RHDF_SPLITBEFORE) {
|
||||
rc = RARProcessFile(hArc, RAR_EXTRACT, c->staging, NULL);
|
||||
if(rc != ERAR_SUCCESS) {
|
||||
rar_translate_error(rc, hdr.FileName, c);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
rc = RARProcessFile(hArc, RAR_EXTRACT, c->staging, NULL);
|
||||
if(rc != ERAR_SUCCESS) {
|
||||
rar_translate_error(rc, hdr.FileName, c);
|
||||
|
||||
@@ -384,7 +384,9 @@ test_real_archives(void) {
|
||||
if(st == ZIPX_OK) {
|
||||
snprintf(checkp, sizeof(checkp), "%s/root.txt", dst);
|
||||
check(exists(checkp), " root.txt present across volumes");
|
||||
check(res.entries_done >= 3, " entries_done >= 3");
|
||||
snprintf(checkp, sizeof(checkp), "%s/big.bin", dst);
|
||||
check(exists(checkp), " big.bin (split file) present and whole");
|
||||
check(res.entries_done >= 2, " entries_done >= 2");
|
||||
} else {
|
||||
printf(" message=%s\n", res.message);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user