Files
LisherSong--ps5-web-file-ma…/tests/run-tests.sh
T
Songlx516 a0482a41ed feat(extract): swap RAR engine to unrar 7.20.1 (v1.9, v6/multi-volume)
Replace the dmc_unrar 1.7.0 backend (third_party/unrar/) with the rarlab
UnRAR 7.20.1 source vendored in third_party/unrar7/ (commit c68c0de),
driven through its C-compatible DLL API.

Why: dmc_unrar only dispatches RAR5 compression version 5
(switch(file->version) case 0x5000). WinRAR 6.x/7.x archives (algorithm
"v6") land on the default branch -> DMC_UNRAR_FILE_UNSUPPORTED_VERSION
-> user-visible "corrupt archive", confirmed on a real v6:8M archive on
2026-09-05. unrar 7.20.1 natively handles v6, multi-volume (.partNN.rar
auto-merge) and encrypted archives.

Engine changes (src/rar_extract.c):
- Facade include swapped to third_party/unrar7/unrar_c_api.h; all calls
  now go through RAROpenArchiveEx/RARReadHeaderEx/RARProcessFile/
  RARCloseArchive. scan + extract each re-open the archive (the DLL API
  is sequential, unlike dmc's index-based access).
- Error translation rewritten for the ERAR_* code set.
- extract no longer builds each staging path by hand (open_parent_dirs/
  extract_one removed): unrar writes the whole tree under the staging
  root; names were validated during scan.
- Bug fix: normalize_name() cleared the caller-provided *is_dir (it set
  *is_dir = 0), turning directory entries into files and tripping the
  duplicate detector whenever an explicit directory header followed
  files beneath it (real v6 archive had exactly this). RHDF_DIRECTORY
  is now honored end to end.
- Encrypted RAR still fails up front (ZIPX_ERR_UNSUPPORTED): unrar can
  decrypt, but password plumbing (API/UI) lands in a later commit.

Build:
- Makefile: C++ compiler vars (CXX/HOST_CXX, prospero-clang++ defaults
  to -stdlib=libc++), unrar7 RARDLL source set (49 files, mirrors
  UnRARDll.vcxproj), .cpp pattern rules, link through the C++ driver.
- tests/run-tests.sh: compiles unrar7 objects with $CXX, links the RAR
  test with g++ and -lpowrprof on Windows.
- third_party/unrar/ (dmc_unrar) removed; see git history.

Verified on host (MinGW): full engine run on the user's real v6 archive
(24.9 MB, 170 headers) -> ZIPX_OK, 170/170 entries, 133 files + 37 dirs,
71,514,931 bytes. Host suite: 70 ZIP + 14 RAR checks green.

Frontend password/multi-volume UX and release plumbing (CHANGELOG,
THIRD_PARTY_NOTICES, README, tag) follow in the v1.9 release commit.
2026-09-05 22:40:58 +08:00

100 lines
3.8 KiB
Bash

#!/usr/bin/env bash
# Host test runner for the ZIP and RAR extraction engines.
# Builds the vendored minizip-ng/zlib/dmc_unrar sources, both engines and
# the test suites with the host compiler and runs each suite.
#
# ./tests/run-tests.sh
#
# On Windows this expects MinGW gcc in PATH (Git Bash is fine).
set -e
ROOT="$(cd "$(dirname "$0")/.." && pwd -W 2>/dev/null || pwd)"
BUILD="$ROOT/.build/host-test"
PYTHON="${PYTHON:-python3}"
CC="${CC:-gcc}"
rm -rf "$BUILD"
mkdir -p "$BUILD"
"$PYTHON" "$ROOT/tests/make_fixtures.py"
MZ_CFLAGS=(-I"$ROOT/third_party/minizip-ng/include" -DHAVE_ZLIB -DZLIB_COMPAT)
RAR_CFLAGS=(-I"$ROOT/third_party/unrar" -DDMC_UNRAR_DISABLE_BE32TOH_BE64TOH=1)
HOST_KIND=posix
# MinGW has no O_NOFOLLOW; the flag is only a host build workaround.
case "$(uname -s)" in
MINGW*|MSYS*|CYGWIN*) MZ_CFLAGS+=(-DO_NOFOLLOW=0); HOST_KIND=windows ;;
esac
# zlib + minizip-ng (plain POSIX sources, no shim needed)
for src in "$ROOT"/third_party/zlib/src/*.c "$ROOT"/third_party/minizip-ng/src/*.c; do
name="$(basename "$src" .c)"
extra=()
# minizip's POSIX backend needs utime/lstat/symlink/readlink, stubbed on Windows.
case "$name:$HOST_KIND" in
mz_os_posix:windows) extra=(-include "$ROOT/tests/mingw_host.h") ;;
esac
"$CC" -c -O2 -w -I"$ROOT/third_party/zlib/include" -DHAVE_UNISTD_H=1 \
"${MZ_CFLAGS[@]}" "${extra[@]}" -o "$BUILD/$name.o" "$src"
done
# unrar 7.20.1 (RARDLL source set; compiled with the host C++ compiler).
UNRAR7_SRCS="$ROOT/third_party/unrar7"
UNRAR7_CFLAGS=(-O2 -w -std=c++17 -DRARDLL -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE)
CXX="${CXX:-g++}"
for src in \
archive arcread blake2s cmddata consio crc crypt dll encname errhnd extinfo \
extract filcreat file filefn filestr find getbits global hash headers isnt \
largepage match motw options pathfn qopen rar rarpch rarvm rawread rdwrfn \
rijndael rs rs16 scantree secpassword sha1 sha256 smallfn strfn strlist \
system threadpool timefn ui unicode unpack volume; do
"$CXX" -c "${UNRAR7_CFLAGS[@]}" -o "$BUILD/unrar7_$src.o" \
"$UNRAR7_SRCS/$src.cpp" || exit 1
done
COMPAT_INC="$ROOT/tests/compat"
# The engines and the test suites get the POSIX shim on Windows hosts.
"$CC" -c -O2 -Wall -Wextra -Wno-unused-parameter \
-I"$ROOT/third_party/minizip-ng/include" -I"$ROOT/src" -I"$COMPAT_INC" \
-include "$ROOT/tests/posix_compat.h" \
-o "$BUILD/zip_extract.o" "$ROOT/src/zip_extract.c"
"$CC" -c -O2 -Wall -Wextra -Wno-unused-parameter \
-I"$ROOT/third_party/minizip-ng/include" -I"$ROOT/third_party/unrar7" -I"$ROOT/src" -I"$COMPAT_INC" \
-include "$ROOT/tests/posix_compat.h" \
-o "$BUILD/rar_extract.o" "$ROOT/src/rar_extract.c"
"$CC" -c -O2 -Wall -Wextra -Wno-unused-parameter -I"$ROOT/src" \
-I"$COMPAT_INC" -include "$ROOT/tests/posix_compat.h" \
-o "$BUILD/test_zip_extract.o" "$ROOT/tests/test_zip_extract.c"
"$CC" -c -O2 -Wall -Wextra -Wno-unused-parameter -I"$ROOT/src" \
-I"$COMPAT_INC" -include "$ROOT/tests/posix_compat.h" \
-o "$BUILD/test_rar_extract.o" "$ROOT/tests/test_rar_extract.c"
objs=()
rar_objs=()
for obj in "$BUILD"/*.o; do
case "$obj" in
*/zip_extract.o|*/rar_extract.o|*/test_zip_extract.o|*/test_rar_extract.o) continue ;;
*/unrar7_*.o) rar_objs+=("$obj"); continue ;;
esac
objs+=("$obj")
done
"$CC" -O2 -o "$BUILD/test-zip-extract" \
"$BUILD/zip_extract.o" "$BUILD/test_zip_extract.o" "${objs[@]}"
# The RAR test links the unrar7 objects, so it needs the C++ driver.
# Windows unrar system.cpp references SetSuspendState (PowrProf).
RAR_LIBS=()
[ "$HOST_KIND" = windows ] && RAR_LIBS=(-lpowrprof)
"$CXX" -O2 -o "$BUILD/test-rar-extract" \
"$BUILD/rar_extract.o" "$BUILD/test_rar_extract.o" \
"$BUILD/zip_extract.o" "${objs[@]}" "${rar_objs[@]}" "${RAR_LIBS[@]}"
"$BUILD/test-zip-extract" "$ROOT/tests/fixtures" "$BUILD/work-zip"
"$BUILD/test-rar-extract" "$ROOT/tests/fixtures" "$BUILD/work-rar"