mirror of
https://github.com/LisherSong/ps5-web-file-manager.git
synced 2026-10-06 09:00:26 +02:00
The 7z chain decoder (commit 2748b38) handles bytes; what the /api/extract
task needed was a third sibling of zip_extract.c and rar_extract.c that
runs that chain over a real archive, mirrors their staging / publish /
rollback / name-validation machinery, and fills in zipx_result_t the same
way so the dispatcher and the web UI can treat every format alike.
* src/sevenz_extract.[ch] -- one pass over the archive (scan: validate every
name, sum bytes, drop archives the chain cannot drive), then folder by
folder through the chain. The publish phase recurses with OVERWRITE and
MERGE alike for matching directories, and only differs at the file
leaves -- a strict non-recursive OVERWRITE would have made the policy
useless for any archive that overlaps a directory already on disk.
* src/zipx_common.c -- the limits profiles and zipx_status_string() that
the three engines share. Pulled out of zip_extract.c so every consumer
gets the same error text and the same MAX_* numbers.
* src/zip_extract.[ch] -- ZIPX_ERR_PASSWORD joined the contract (7zAES).
* tests/run-sevenz-tests.sh -- the engine matrix now also runs the facade
over every fixture, plus 22 error and policy checks against
test_sevenz_extract. KNOWN_GAPS holds only "aeshe" (encrypted header);
the plain 7zAES fixture is in the matrix.
* tests/test_sevenz_extract.c -- end-to-end driver for the facade.
The POSIX shim the host test runner injects needed three more pieces so
the tests pass on a CP936 host:
* lstat/stat -> wfm_stat (the MinGW ANSI entry points can't see a UTF-8
filename in CP936; without the redirect a non-ASCII entry causes the
publish phase to lstat() a mangled path and fail with ENOENT).
* opendir/readdir/closedir -> the wide variants, so readdir() hands us
real UTF-8 names instead of CP936 bytes that nothing can round-trip.
* fopen -> _wfopen, for the test helpers that read a non-ASCII file
back to verify it.
ZIP 108 checks / RAR 27 checks / 7z 26 checks, all green; the AES
fixture extracts with the password "Secret123" and rejects wrong / absent
passwords with "password required or wrong" / "wrong password, or the
archive is damaged".
tests/fixtures/ gains the volume-set fixtures (broken.zip.001, gap.zip.*,
disks.*, parts.part*.zip, plain.zip.*, split_single.zip) that were
generated by tests/make_split_fixtures.py in earlier sessions but never
made it into the index.
Next commit wires sevenz_extract() into the dispatch in src/extract.c and
recognises 7z archives in assets/main.js.
125 lines
5.3 KiB
Bash
125 lines
5.3 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}"
|
|
|
|
# Clean previous build outputs without nuking the whole tree (avoids
|
|
# bulk-delete guards); stale fixture copies in work-* dirs are fine because
|
|
# make_fixtures.py rewrites fixtures/ and the suites recreate their workdirs.
|
|
find "$BUILD" -maxdepth 1 -type f -name '*.o' -delete 2>/dev/null || true
|
|
find "$BUILD" -maxdepth 1 -type f -name 'test-*' -delete 2>/dev/null || true
|
|
find "$BUILD" -maxdepth 1 -type f -name '*.log' -delete 2>/dev/null || true
|
|
mkdir -p "$BUILD"
|
|
|
|
"$PYTHON" "$ROOT/tests/make_fixtures.py"
|
|
"$PYTHON" "$ROOT/tests/make_split_fixtures.py"
|
|
|
|
MZ_CFLAGS=(-I"$ROOT/third_party/minizip-ng/include" -DHAVE_ZLIB -DZLIB_COMPAT -D_FILE_OFFSET_BITS=64)
|
|
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"
|
|
|
|
# Format-independent helpers (limits profiles + status string) live here.
|
|
"$CC" -c -O2 -Wall -Wextra -Wno-unused-parameter -I"$ROOT/src" \
|
|
-I"$COMPAT_INC" -include "$ROOT/tests/posix_compat.h" \
|
|
-o "$BUILD/zipx_common.o" "$ROOT/src/zipx_common.c"
|
|
|
|
# Volume support: the concatenating stream and the volume set detector.
|
|
"$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/zipx_volstream.o" "$ROOT/src/zipx_volstream.c"
|
|
|
|
"$CC" -c -O2 -Wall -Wextra -Wno-unused-parameter -I"$ROOT/src" \
|
|
-I"$COMPAT_INC" -include "$ROOT/tests/posix_compat.h" \
|
|
-o "$BUILD/zipx_volume.o" "$ROOT/src/zipx_volume.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|*/zipx_common.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/zipx_common.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" "$BUILD/zipx_common.o" "${objs[@]}" "${rar_objs[@]}" "${RAR_LIBS[@]}"
|
|
|
|
"$BUILD/test-zip-extract" "$ROOT/tests/fixtures" "$BUILD/work-zip"
|
|
# Real RAR fixtures (v6 / multi-volume / encrypted) live in fixtures-real/,
|
|
# generated by tests/make-rar-fixtures.bat (WinRAR required); fixtures/
|
|
# itself is wiped by make_fixtures.py on every run.
|
|
"$BUILD/test-rar-extract" "$ROOT/tests/fixtures" "$BUILD/work-rar" \
|
|
"$ROOT/tests/fixtures-real"
|