Commit Graph
9 Commits
Author SHA1 Message Date
Songlx516 f820016de3 test(host): fix statvfs shim for big-file e2e; add standalone bigfile driver
Host-side verification that the ZIP engine can extract a >4GiB zip64
entry end to end (4.7 GiB fixture, content byte-compared):

- tests/compat/sys/statvfs.h: resolve the path before taking the drive
  letter (relative paths used to fail) and scale f_bavail by 4096 since
  `unsigned long` is 32-bit on Windows and silently truncated ~250GB
  down to ~2.3GB; real 64-bit hosts and the PS5 (LP64) are unaffected.
- tests/bigfile_e2e.c: standalone driver to extract one large archive
  and print the engine result (verification via cmp/sha256 by caller).
- tests/run-tests.sh: incremental clean instead of `rm -rf` of the whole
  build tree.
- Makefile: force -DHAVE_FSEEKO so minizip uses fseeko/ftello instead of
  falling back to fseek/ftell on libcs without the probe.

Result: 4.7 GiB zip64 extracts OK on host in ~6s, output identical to
source. Engine 64-bit write path confirmed clean; PS5 failure needs the
strerror passthrough build for real-machine errno capture.
2026-09-06 09:41:32 +08:00
Songlx516 ad765776f7 fix(build): stub libgcc __cpu_model symbols for PS5 link
unrar rijndael/system call __builtin_cpu_supports (AES-NI probe) which
clang lowers to __cpu_model + __cpu_indicator_init; the FreeBSD-style PS5
sysroot ships no libgcc, so the link failed. Add a PS5-only (x86_64, non
linux/win) stub TU; host builds keep the real libgcc-provided symbols.
2026-09-05 23:34:35 +08:00
Songlx516 af6b440f33 fix(build): compile project C sources with -x c when linking via clang++
The link driver is now the C++ compiler (needed for unrar objects), but
it treats the .c files on the command line as C++ and clang 18 rejects
that with -Werror=deprecated. Pass -x c before the C source list and
-x none before the object files.
2026-09-05 23:30:03 +08:00
Songlx516 01a6616472 fix(build): exclude Windows-only unrar sources on PS5/linux; abort on make fail
isnt.cpp / motw.cpp need windows.h (OS version / Zone.Identifier checks)
and are not in the official unrar UNIX makefile; the _UNIX branch
#ifdef's their symbols out, so PS5 and linux builds must not compile
them (first PS5 build failed on isnt.cpp). run-tests.sh MinGW flow
keeps them.

build-elf.sh: make failure previously fell through to step 7 which
reported the STALE elf as OK (sha unchanged, user confused); make now
aborts the script (pipefail already set).
2026-09-05 23:26:37 +08:00
Songlx516 068983b062 release(v1.9): docs, notices and version bumps (ELF sha TBD until WSL build)
- CHANGELOG: new [v1.9] section (engine swap rationale, v6 / multi-volume /
  decryption-capable, 94 checks); banner with TBD size/sha256.
- README: header version v1.9; "What's new in v1.9"; RAR extraction section
  rewritten for unrar 7.20.1 (v6 + multi-volume supported, encrypted pending
  password plumbing); vendoring/licence and old v1.9-plan sections replaced.
- THIRD_PARTY_NOTICES: dmc_unrar GPL-2.0 entry -> rarlab UnRAR freeware
  licence entry (third_party/unrar7/license.txt); dmc_unrar history note.
- assets/main.js APP_VERSION "v1.8.3" -> "v1.9" (footer version string).
- Makefile VERSION_TAG v1.8 -> v1.9.
2026-09-05 23:23:21 +08:00
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
Songlx516 2a346d694c relax(extract): default limits 256 GiB -> 512 GiB / 1 TiB -> 2 TiB; large 2 TiB -> 4 TiB; threshold 240 GiB -> 480 GiB (v1.8.2)
A 3A-game archive with a single ~300 GiB uncompressed file was silently
rejected by the v1.8.1 default profile (scan_archive returns
ZIPX_ERR_LIMIT_FILE_SIZE before the request ever reaches the frontend
confirmation prompt, so the user just sees "卡壳"). The 256 GiB default
cap was tuned for PS5 system backups (many smaller entries) and was wrong
for the 3A-game single-file case.

Limits changes:
- src/zip_extract.c k_default_limits: 1 TiB / 256 GiB / 500 -> 2 TiB / 512 GiB / 500
- src/zip_extract.c k_large_limits:   2 TiB / 1 TiB   / 1000 -> 4 TiB / 1 TiB / 1000 (must stay > default)
- assets/main.js LARGE_FILE_THRESHOLD_BYTES: 240 GiB -> 480 GiB
- assets/lang-{en,zh}.js extractLargeAsk copy reflects new numbers
- tests/test_zip_extract.c: large.max_total_bytes advertised-number assertion updated to 4 TiB
- README.md / docs/HANDOVER.md: limit tables, FAQ, threshold snippets updated
- CHANGELOG.md: v1.8.2 entry added above v1.8.1

PS5-only build fixes (caught by WSL cross-compile, host tests pass without):
- Makefile CFLAGS: add -Ithird_party/unrar so src/rar_extract.c can find
  the dmc_unrar_api.h facade header (THIRD_PARTY_CFLAGS already had it
  but the main CFLAGS for project sources did not).
- src/extract.c: move extract_progress() definition before
  extract_dispatch() so the implicit function declaration is not flagged
  by -Werror=implicit-function-declaration (clang 18 in the PS5 SDK is
  stricter than the host gcc used by tests/run-tests.sh).

Release artifact: web-file-mgr.elf 509 704 bytes,
sha256 1b2c3d68b35e32737105f17d14a80a3c159ceca0cabd274ee168cbcd81906f65,
e_machine 0x003e (x86_64-sie-ps5).

Safety argument is unchanged from v1.8.1: zip-bomb defence is
check_space() (statvfs-based real disk-space check before staging) +
max_ratio (declared compression ratio cap). The size caps are a UX guard,
not a security boundary.

RAR extraction inherits the new defaults automatically (rar_extract.c
threads c->limits from the engine).

84 host-side checks (70 ZIP + 14 RAR), 0 failures. PS5 cross-compile
succeeds; ELF size grew from 427 656 (v1.8) to 509 704 (v1.8.2) due to
the dmc_unrar vendor TU being linked in.
2026-09-05 16:10:31 +08:00
Songlx516 50eb1734c1 feat(extract): RAR4/RAR5 single-volume backend via dmc_unrar facade
src/rar_extract.{c,h} (1276 LOC) — new public engine:
  rar_extract(rar_path, dst_dir, conflict, limits, cancel, progress, userdata, result)
Mirrors the zip_extract contract exactly: same three-phase template
(scan -> extract to .wfm-extract-*.tmp staging + fsync -> publish via
rename -> cleanup/rollback), same zipx_status_t / zipx_limits_t /
zipx_conflict_t / zipx_result_t / zipx_progress_t types, same callback
signatures. Reuses publish_dir/publish_entry/publish_staging so a RAR
extract behaves identically to a ZIP extract under conflict-policy
(overwrite / merge / fail), rollback, fsync, and per-entry fsync.

Internals:
  - rarx_ctx_t carries limits, callback, staging dir, published paths,
    detail-msg accumulator, and the nameset for path-conflict detection.
  - rar_translate_error maps every dmc_unrar_return code to a
    zipx_status_t (UNSUPPORTED volumes/encryption/method -> UNSUPPORTED,
    unsupported_link -> SPECIAL, oversized entry -> LIMIT_FILE,
    CRC fail -> CRC, etc.) so the frontend needs zero per-engine branching.
  - normalize_name converts backslash -> forward slash (RAR names may use
    either on Windows) and detects directory entries by trailing slash
    rather than relying on external attributes alone.
  - open_parent_dirs / check_space / remove_tree / cleanup_staging /
    rollback_published reused from zip_extract's pattern.

src/extract.c — adds extract_dispatch(file_task_t*, conflict, limits,
result*) routing .zip -> zipx_extract(), .rar -> rar_extract(), else
ZIPX_ERR_UNSUPPORTED ('only .zip and .rar are accepted'). The existing
extract_worker now calls dispatch instead of zipx_extract directly.
ends_with_ci() helper for the .rar suffix match (case-insensitive, trims
trailing '/' from paths that the frontend might send).

Makefile:
  - VERSION_TAG := v1.8 (was v1.7)
  - COMMON_SRCS adds src/rar_extract.c
  - THIRD_PARTY_SRCS adds third_party/unrar/dmc_unrar.c (compiled as its
    own TU; never inlined into rar_extract.c)
  - THIRD_PARTY_CFLAGS adds -Ithird_party/unrar and
    -DDMC_UNRAR_DISABLE_BE32TOH_BE64TOH=1 to avoid <endian.h> conflicts
    with the SDK's headers.

Limitations surfaced as ZIPX_ERR_UNSUPPORTED with frontend-visible
err_extract_unsupported messages:
  - multi-volume RAR (.partNN.rar chains) -- dmc_unrar upstream
    limitation; documented v1.9 plan is to vendor opello/unrar C++
  - encrypted RAR (password= ignored) -- dmc_unrar upstream limitation
  - symlinks / FIFOs / device nodes -- ZIPX_ERR_SPECIAL
  - RAR1.4 / RAR1.5 -- ZIPX_ERR_UNSUPPORTED

No ELF rebuild attached in this commit (cross-compile is WSL-side and
deferred to the release commit).
2026-09-05 15:09:32 +08:00
Songlx516 5cb0b76e7a Initial import of PS5 Web File Manager v1.7
Homebrew HTTP file manager payload for jailbroken PS5 consoles (x86_64-sie-ps5,
title id FMGR88888). Browse, edit, upload, download and extract ZIPs through
any browser on the LAN; single self-contained ELF, no external services.

Highlights (v1.7):
- ZIP large-file profile (large=1): 2 TiB total / 1 TiB per entry / 1000:1
  ratio. Frontend prompts for confirmation whenever archive > 60 GiB on disk.
- Default ZIP profile stays safe: 512 GiB / 64 GiB / 200:1.
- 69 host-side C tests (tests/run-tests.sh) covering traversal, ZIP64,
  encryption rejection, conflict policies and the large-file profile.
- Three-phase extraction engine (scan -> extract -> publish -> cleanup) with
  atomic staging + rename, located in src/zip_extract.{c,h}.

Project layout:
  src/          C payload sources
  assets/       HTML / CSS / JS / icons / param.json
  tests/        POSIX/host test suite + fixtures
  third_party/  vendored zlib + minizip-ng (zlib license)
  docs/screenshots/  README screenshot images
  LICENSE       GPLv3+

Build:
  make         # cross-compile with PS5_PAYLOAD_SDK
  make linux   # Linux host binary for UI dev
2026-09-04 14:21:15 +08:00