Deep-review hardening and GUI experience release. An 80-item review of the whole
repository (path escapes, patch-layout collisions, CWD leaks, partial artifacts,
CLI contract mismatches, vacuous tests, doc drift) is resolved, together with
the follow-up regressions found while re-reviewing those fixes and a final pass
over the fix commits. The desktop app gains Donate/About/Exit header actions, F8
window screenshots, and a startup update prompt backed by the same UpdateCore
- 24-hour cache the CLI uses. Namespace note:
UnpackOptions,ProcessRunResult,ExplorerNode, andXisoExplorerOptionsmoved fromXISOSharptoXISOSharp.Models— addusing XISOSharp.Models;when upgrading from 1.4.1. Targets remainnet8.0/net9.0/net10.0; full suite green on all three (1818 tests on net10.0: 1817 passed, 1 opt-in skip; 1757 on net8.0/net9.0: 1756 passed, 1 opt-in skip). The suite runs fully sequentially (assembly-wideDisableTestParallelization) because create/extract mutate the process CWD.
- Path safety: crafted image names (separators, Windows drive-relative colons, any trailing dot/space) are rejected at extract on Windows or sanitized by repair/salvage; listing, tree, rewrite, and ZAR packing accept every structurally valid name on every host, matching the reference tool (the colon stays valid on Unix where the writer/patcher accept it).
- Patching: the allocator reserves the optimized tag (sector 15), the
ECMA-119 descriptor pair (16-17), and the layout-tool signature sector — also
for header-only volumes; sector counts use 64-bit math; the root table size
is recorded even when the table stays in place; a child offset that would
encode the
0xFFFFempty-child sentinel fails instead of truncating. - Walkers: all child offsets are bounded by the recorded table size, the
all-zero empty-table sentinel is honored,
./..records are skipped consistently, truncated names fail instead of truncating the walk (includingCollectFileEntries), and zero-size directory entries list as empty. - Writing/containers: CWD is restored on every path; a cwd source
(
-c ./-c ..) defaults its output next to the source instead of aborting on the same-leaf guard; relative-dresolves against the caller CWD; failed/cancelled runs delete partial.iso/.cso/.zaroutput (including thebuild-imageremap writer, and closing split-part handles first on Windows) but never a pre-existing file the call did not create; CISO headers/indexes are validated; split part naming handles dotted bases;Latin1Encodingrange checks are overflow-safe. - Repair/audit: a missing optimized tag is written at the disc offset for prepended images; path and device audits agree on trailing magic, empty-image tag probing, and an oversized root table (audit now matches extraction).
XisoPathsresolves both sides of an input==output check against one CWD snapshot;XisoExplorer.Disposeserializes with keep-open reads.
--silentis order-independent in every position, including with-v/--help, and still requires--checksum;--file-time/--preserve-attrs/--jobs/--policyare rejected outside their modes, and--jobsis rejected with--compressor a multi-mode redump run where it cannot take effect;--wipe/--trimhonor-o;--is-optimizedhonors--skip-sectors;--ciso-splitrefuses a source named like its own first part.-Ddeletes.oldonly after a fully successful (validated) rewrite, and a failed file no longer suppresses a later file's success or keeps its backup.- Help shows
-o <output>for the redump modes instead of a positional second file (which is parsed as another input). - stdout/stderr are always UTF-8 instead of the host console code page, so
Latin-1 filenames (
café.txt) render and pipe identically on every platform (matching xdvdfs's UTF-8 output); the battle harness now decodes each tool with its real encoding (extract-xiso Latin-1; xdvdfs, xboxkit, and the CLI UTF-8) so non-ASCII names compare equal instead of collapsing toU+FFFD.
- Donate/About/Exit header actions with an About dialog; F8 screenshots; startup update prompt (subscribed before probing so a fast show cannot hang it); tooltips.
- Drag-and-drop routing fixed (only
*.isofolders go to Batch;.zardrops go to Rebuild in single- and multi-item drops); Wipe/Trim pass-obefore the image;CliStatusupdates on the UI thread; settings persist again; screenshot environment warnings stay local and the fallback folder is tried for security exceptions.
- Shared Serilog pipeline; expected operational warnings are tagged
NoBugReport; the shared API key is double-Base64 encoded (ApiKeyStore); the dedupe map is bounded;ProcessRunnerfalls back to a stable working directory when the inherited CWD was deleted.
- List comparison parses the real
\name (N bytes)format and decodes extract-xiso's Latin-1 output; two empty parses fail instead of passing; remaining dead wrappers (RunQuietAsync) removed.
- Drift fixed (test counts,
--help, Release packing, battle default, coverage OS/figures, Tester CI, sequential-suite description, missing scripts,ConversionPlan.md, namespace samples); publish scripts stage into%TEMP%and merge instead of deleting the protectedpublish*/trees, andpublish-cli.ps1 -Ziprequires an exact tag or-Version <x.y.z>so a pre-release run cannot overwrite a shippedrelease_*.zip;docs/serves Pages (Docsify_sidebar.md) and syncs to the wiki (Home.md+_Sidebar.md) via.github/workflows/wiki.yml.
Dependency and legal maintenance release. ZArchiveSharp moves 1.3.0 → 1.4.0
(drop-in: upstream rewrote its pipeline layer as original MIT work with no
public-surface, wire-format, or CLI changes), and the ZArchiveSharp notice is
refreshed — the library, including the ZArchiveSharp.Pipeline pack/extract
layer XISOSharp uses, is fully MIT. No XISOSharp API or CLI behavior changes;
targets remain net8.0 / net9.0 / net10.0; full suite green on all three
(1427 tests: 1426 passed, 1 opt-in skip, 0 failed).
ZArchiveSharp1.3.0 → 1.4.0. Upstream highlights: original MIT pipeline layer (ZarPipeline,ZarPackEngine,ProcessRunner), stricter per-item batch isolation, and a robust stderr drain that no longer stalls on an inherited pipe. The public surface is unchanged, so ZAR output, CLI semantics, and exit codes are untouched.
LICENSEitem 4 records ZArchiveSharp as fully MIT as of v1.4.0 (Copyright (c) 2026 PureLogicCode.com; lead developer Peterson Fernandes), includingZArchiveSharp.Pipeline.- The packaged library license (
XISOSharp/LICENSE) is synced with the rootLICENSE, so the NuGet package now carries the full third-party notices (extract-xiso BSD-4-clause, xdvdfs, XboxKit, ZArchiveSharp).
- Root
README.mdanddocs/building.mddependency references updated 1.3.0 → 1.4.0.
Integrity-audit release. The CLI's -V audit no longer fails a structurally
sound image just because the optimized tag is missing: it reports the tag
(Optimized: yes/no) and passes raw/unconverted dumps, while structural damage
still fails. Audits now accept .cso images (previously compressed bytes were
read as sectors), the library gains a requireOptimizedTag overload plus the
AuditResult.IsOptimized property, and empty (zero-root) images report tag
presence instead of always false. Targets remain net8.0 / net9.0 /
net10.0; full suite green on all three (1427 tests: 1426 passed, 1 opt-in
skip, 0 failed).
- New overloads
AuditXiso(string isoPath, bool requireOptimizedTag)andAuditXiso(IBlockDevice dev, string isoName, bool requireOptimizedTag). WithrequireOptimizedTag: falsea missing tag is not an audit issue, so raw (unconverted) images audit as valid; the 1-arg overloads keep the original strict behavior (true). - New
AuditResult.IsOptimizedproperty reports whether the tag was found. The empty/zero-root early-return paths previously skipped the tag probe, so an image whose root fields are zero but whose tag is intact reportedfalse; both the path and block-device overloads now probe and report it. AuditXiso(string)now opens throughOpenImageStream(CISO-aware) instead of a plainFileStream, matchingGetVolumeInfo. A.csoinput used to be audited as compressed bytes, producing bogus tree/bounds issues.
-Vis an integrity audit: it printsOptimized: yes/no, a missing tag no longer fails the run, and raw/unconverted images exit 0. Use--is-optimizedfor the strict tag-only probe or--repairto write a missing tag. Help text updated.
- 1427 tests across
net8.0/net9.0/net10.0: 1426 passed, 1 opt-in skip (XISO_UPDATE_FIXTURE=1fixture validator), 0 failed. - New:
CliAuditTests(3 end-to-end-Vruns: optimized, raw passing withOptimized: no, corrupt tree failing),AuditXisoTestsintegrity/tag/CISO cases (4, incl. plain-vs-CISO parity), and device empty-root tag coverage.
coverlet.collector10.0.1 → 10.1.0 (Tests). No library dependency changes.
README.md,XISOSharp/README.md,XISOSharp.Cli/README.md,docs/cli.md, anddocs/api-xisoreader.mddocument the integrity audit, therequireOptimizedTagoverload, andIsOptimized;docs/troubleshooting.mdanddocs/getting-started.mdrefreshed; suite counts updated.- Release bundles now include
WhatsNew.mdnext toREADME.mdandLICENSE.
Correctness and maintenance release. The rewrite -o output name is now
honored for real — including rooted/absolute paths — and a rewrite that fails
to write reports an error instead of exiting 0. Wrapped exceptions carry their
cause, the reference-binary interop tests resolve the current References/
drop again, and the bug-report wire format is locked by tests. Targets remain
net8.0 / net9.0 / net10.0; full suite green on all three (1419 tests:
1418 passed, 1 opt-in skip, 0 failed).
XisoWriter.CreateXisoignoredinNamein rewrite mode, soXisoReader.Rewrite(..., outputName:)(CLI-o) had no effect on the output filename. The name is now used verbatim: relative names resolve against the-ddirectory, and rooted names are kept intact. The Windows drive-letter strip used for legacy names no longer applies to a rooted-o, which turnedC:\out\game.isointo:\out\game.isoand failed with a path-syntax error.XisoReader.DecodeXiso(and thereforeRewrite) now returns the writer's non-zero result when the output cannot be written. Previously the writer logged the failure but the rewrite still reported success and returned 0.- Regression tests:
Rewrite_WithAbsoluteOutputName_UsesProvidedName,Rewrite_UnwritableOutput_ReturnsError.
- Wrapped rethrows embed the caught exception as
InnerException(Meziantou MA0054):ProcessRunnertimeout →TimeoutException,XisoReadertruncated file copy →IOException, GUIMainViewModeloutput-verification failures →InvalidOperationException. Message text is unchanged, so existing diagnostics and exception filters keep working.
- Rewrite (
-r) now checks the decode result: a failed rewrite exits 1 and does not printsuccessfully rewritten(the input stays at<name>.old, exactly as before the fix). -oaccepts relative and rooted paths and uses them as-is.
UpdateCheckerdebug-logs every previously silent catch (offline checks and API/cache failures stay belowWarning, so they never file bug reports); GUICliLocator.ProductVersiondebug-logs unreadable CLI metadata.BugReporterextractsComposeReportand exposesBuildExceptionBlockto tests; newBugReportFormatTests(5) lock the Environment / Error / Exception sections required by the bug-report service.
- 1419 tests across
net8.0/net9.0/net10.0: 1418 passed, 1 opt-in skip (XISO_UPDATE_FIXTURE=1fixture validator), 0 failed. TestConditionsresolves the compiledextract-xiso.exefrom the currentReferences/drop (canonicalReferences/extract-xiso.exe, dated drop root, or in-tree CMake build) instead of the removed202505152050artifact path; the legacyllCompatinterop tests run and pass again.RegenerateFixtureIso_WhenRequestedrenamed toValidateFixtureIso_WhenRequested(it validates only; regeneration stays manual) —docs/testing.mdupdated.
Meziantou.Analyzer3.0.257 → 3.0.290 (all projects),Avalonia12.1.2 → 12.1.3 (GUI),QuestPDF2026.8.0 → 2026.9.1 (Tester),Microsoft.NET.Test.Sdk18.10.0 → 18.10.1 (Tests). No library dependency changes.
- Badge rows (CI, NuGet version/downloads, release, .NET, platform/RIDs,
license, docs site, per-project) added to the root, library, CLI, Tests,
Tester, and docs READMEs; suite counts refreshed;
-orooted-path behavior documented in the CLI reference.
Additive release for VFS-consumer parity (SimpleXisoDrive/Dokan): the probe and
read stack now accepts the rebuilt "sector-0" XISO layout (volume descriptor at
the very start of the image instead of partition sector 32), and the in-place
patcher, sector ranges, and ZAR packing understand it end-to-end. Targets remain
net8.0 / net9.0 / net10.0; full suite green on all three (1412 tests:
1408 passed, 4 pre-existing skips, 0 failed).
VerifyXiso(stream and block-device overloads),GetVolumeInfo,GetFileTimeRaw/SetFileTime(both overloads), andOffsetBlockDevice.Probedetect a volume descriptor at absolute offset 0. Such images reportDiscLseek = 0andDescriptorSector = 0; sector numbers stay partition-relative, soXisoExplorer, directory listing, and bounded file reads work unchanged on them.XisoReader.TryFindHeaderBaseresolves the descriptor base for callers that take a partition offset (standard sector-32 candidate first, then sector-0).GetSectorLayoutmarks the detected descriptor sector as used instead of hardcoding partition sector 32, soSectorAllocator.FromLayoutcan no longer hand out the live header to the in-place patcher.PatchVolumeHeaderRootwrites the relocated root pointer to the active header base (DiscLseek + DescriptorSector * 2048), fixing a silent-corruption path whereCopyInon a sector-0 image overwrote the descriptor or left the header pointing at the old root table.XisoRanges.GetXisoRanges/GetFileEntriesandXisoZarchive.CreateZarresolve the descriptor with the same helper; invalid images keep the historical fallback base and failure behavior.XisoRedump.RebuildRedumprejects sector-0 inputs with an explicit error (repack to the standard sector-32 layout first) because a verbatim embed would place the descriptor at partition sector 0;HasXisoMagicrecognizes sector-0 images so they keep working as.zarsidecar inputs.
- The brute-force seed search now checks the cancellation token inside each worker's candidate chunk. A canceled search stops promptly instead of grinding through the rest of the chunk — removing the coverage-instrumented stall that tripped CI's 15-minute blame-hang watchdog on the net8.0 test host.
- New
XisoRebuiltSector0Tests(12 tests): probe/verify/volume-info parity, explorer listing +OpenReadStream, filetime read/write, block-device probe, sector layout used/free ranges, in-place add/replace/root-table-move, andGetXisoRanges/CreateZarround-trips on sector-0 images.
docs/xiso-format.mddocuments the rebuilt sector-0 variant; theapi-xisoreader.mdprobe table,DescriptorSectorcontract, and the library/CLI READMEs cover the accepted layout and the Redump rebuild restriction.
- Test runs always publish a
.trxartifact for post-mortems and skip hang-dump collection (--blame-hang-dump-type none); the instrumented seed-search stall that aborted the net8.0 job is gone (windows tests dropped from ~15 min to ~1.5 min per TFM).
Additive release for VFS-consumer parity (SimpleXisoDrive/Dokan): the public API
gains bounded in-place file reads, a keep-open explorer mode, descriptor
creation-time/sector surfacing, FileShare control, and Windows attribute
mapping — no behavior change to existing APIs. Targets remain net8.0 /
net9.0 / net10.0; full suite green on all three (1400 tests: 1396 passed,
4 pre-existing skips, 0 failed).
XisoExplorer.OpenReadStream(string)/OpenReadStream(ExplorerNode)return a read-only, seekableStreamover a file's data extent inside the image. Reads are clamped to the entry'sFileSize(not the image length), so a corrupt TOC cannot leak the next file's sectors; seeking at/past the end reads 0 bytes perStreamconventions; CISO/split-CISO images work transparently through the decompressed block device. No copy is made, so 4 GB files stream in place.XisoReader.ReadFileBytes(isoPath, internalPath, Span<byte>, fileOffset)and the stream overload are one-shot conveniences over the same bounds; the stream overload leaves the caller's stream open, and missing paths/directories throwInvalidDataException.- A stateless explorer's read stream owns the image handle (dispose it); a keep-open explorer's read streams stay valid until the explorer is disposed.
- New
XisoExplorerOptions { KeepOpen, Share }andXisoExplorer(string, XisoExplorerOptions):KeepOpenholds one image stream for the explorer's lifetime (metadata calls use the held stream), serializes operations with an internal lock, andDispose()closes the stream — the mount/VFS shape that avoids re-opening the image for every lookup.KeepOpen: falsestays byte-for-byte identical to 1.0.2.
XisoReader.OpenImageStream(path, FileShare)andXisoExplorerOptions.Share: plain-ISO streams pass the share mode through (defaultFileShare.Read, unchanged), and CISO inputs thread it to the container file.FileShare.ReadWritelets a mounted image coexist with AV scanners or sync clients that open the.isofor write.
VolumeInfogainsCreationTime(DateTimeOffset?,nullwhen invalid; raw 0 maps to 1601-01-01),FileTimeRaw, andDescriptorSector(partition-relative sector32for every supported layout — the partition shift isDiscLseek; −1 when invalid) — all populated by the same probeGetVolumeInfoalready performs, so no second open is needed.GetVolumeInfoagrees withGetFileTimefor the same image.
- New
XisoAttributes.ToWindowsFileAttributes(byte): pure bit math mapping the raw XDVDFS attribute byte toSystem.IO.FileAttributes(ReadOnlyalways set;Directory/Hidden/System/ArchiveOR'd in;Normalwhen nothing else applies; reserved bits masked), matching SimpleXisoDrive's locked expectations.
- Modern dark theme: left navigation rail with an accent pill, card layout, green accent palette, rounded inputs and log console, and a dark native title bar on Windows.
- New ZAR tab: packs an ISO/XISO/Redump image into a
.zar(ZArchive/zstd, loadable in Xenia canary) with overwrite/skip/auto-rename collision policies; drop routing and tab-order shortcuts account for the new tab.
XisoExplorer.OpenReadStream(string)and the keep-open constructor no longer leak the image handle when a lookup or probe throws.BoundedSubStreamrejects seeks before the window start withIOException(perStreamconventions) instead of reading preceding image bytes.ReadFileBytesvalidates the path even when the buffer is empty.GetVolumeInfoskips probe candidates past EOF instead of aborting, so a trimmed XGD3 image (smaller than the global candidate offset) is detected.
- Library/Getting-Started quick samples for the VFS use case, and the Utilities
page documents explorer options, the read-bounds contract, and
XisoAttributes.
ZArchiveSharpNuGet dependency updated 1.0.2 → 1.3.0 (mount-friendly reader API, specific open-failure reasons; additive, no wire-format changes).
Release tag 1.0.2.
Targets remain net8.0 / net9.0 / net10.0; full suite green on all three
(1338 tests: 1334 passed, 4 pre-existing skips, 0 failed).
-v (and the usage header) now prints
XISOSharp v<version> for <win|linux|macos|cross-platform> - https://github.com/purelogiccode/XISOSharp
instead of the extract-xiso compatibility line. The version is the MinVer
build stamp with +build metadata trimmed, so it matches the package/assembly
version. Constants.ExisoVersion is kept for provenance and the on-disk
optimized tag (in!xiso!2.7.1 (01.11.14)) is unchanged, so image compatibility
is unaffected. The extract-xiso BSD-4-clause acknowledgement remains in the
shipped LICENSE.
Every interactive launch compares the running version against the latest
GitHub release — at most one request per 24 hours, cached at
%LocalAppData%/XISOSharp/update-check.json. A newer release prints an
[UPDATE] notice with the release page and the matching
release_<version>_<rid>.zip asset, and on an interactive console you are
offered to open the release page in your browser. The check is skipped for
-q/-Q/-v runs and test hosts, never fails the run, and can be disabled
with XISO_NO_UPDATE_CHECK=1.
--sector-layout (volume summary, per-file extents, used/free ranges),
--ranges (system/bone vs file sector ranges), and --is-optimized
(optimized-tag probe, --skip-sectors aware).
Double-clicking XISOSharp.exe with no arguments prints usage and waits for a
keypress instead of closing the console window. Scripts, pipes, test hosts, and
XISO_NO_PAUSE=1 are never blocked.
The shared Serilog pipeline in the CLI, GUI, and Tester forwards
Warning-and-above events to the bug-report API with environment, error, and
exception sections; opt out with XISO_DISABLE_BUGREPORT=1.
- CLI discovery fix for single-file bundles:
ToolLocatornow also probes the directory of the real executable (Environment.ProcessPath) afterAppContext.BaseDirectory, since self-extracting bundles run from%TEMP%\.net\.... This resolves the "CLI not found" state when the GUI runs from a published bundle. - The legacy
XISOSharp.Clifile-name fallback was removed; resolution isXISOSharp(.exe)only. - Status bar and log show a branded product label (
XISOSharp <version>) read from the CLI binary's version metadata instead of echoing the-vbanner. - The app icon is embedded in both the executable and the window.
- Framework-dependent publish builds and stages the CLI beside the GUI
automatically (previous attempts failed with
NETSDK1151).
ToolLocatoris now the shared resolver/probe used by the GUI, Tester, and BattleTests: explicit override → app directory → process directory →PATH, with a bounded, tree-killed-vprobe viaProcessRunner, plus a newToolLocatorTestssuite.Constants.Bannerreports the XISOSharp product version; the extract-xiso baseline constant is retained for provenance.
- GitHub Pages publishes the Docsify documentation, and a workflow syncs the wiki (sidebar included).
LICENSEnow carries the full third-party notices (extract-xiso BSD-4-clause, xdvdfs, XboxKit, ZArchiveSharp); distributed bundles includeLICENSEandREADME.md.- Docs and readmes refreshed for the branded banner, the new inspection verbs, update checks, the GUI bundle layout, and the shared tool locator.
No library dependency changes: ZArchiveSharp stays at 1.0.2, analyzer/Roslynator
versions are unchanged from 1.0.1.
Release tag 1.0.1.
Targets remain net8.0 / net9.0 / net10.0; full suite green on all three
(1290 tests: 1286 passed, 4 pre-existing skips, 0 failed).
Optimizing (-r / Rewrite) an image containing a zero-size directory entry —
seen in the wild in e.g. Marvel vs Capcom 2 — used to write that entry back as a
file (ARC attribute, file data) instead of a directory, breaking the game.
Cause: XisoReader.TraverseXiso in GenerateAvl mode only recursed into
subdirectories with fileSize > 0 and left AvlNode.Subdirectory as null for
zero-size ones; the writer treats null as "file". The fix assigns
AvlNode.EmptySubdirectory, matching upstream extract-xiso build
202609111233, which fixed the same bug in traverse_xiso() (subdirectory left
NULL instead of EMPTY_SUBDIRECTORY). See Rewrite mode
and XISO Format.
XisoChecksum.ComputeImageChecksum used only the BCL
IncrementalHash SHA3-256, which throws PlatformNotSupportedException on OSes
without a SHA3 provider (Windows 10 CNG, OpenSSL 1.x) — all checksum tests
failed there. New pure-managed FIPS 202 SHA3-256 (XISOSharp/Sha3.cs, no new
dependencies, trim/AOT-safe) is now used as a fallback whenever
SHA3_256.IsSupported is false; digests are identical either way (verified
against OpenSSL 3.0, including rate-boundary sizes). See
Checksums.
ZArchiveSharp1.0.1 → 1.0.2, now consumed purely as a NuGet package — the sibling-checkoutProjectReferencefallback was removed, so no side-by-sideCSharp_ZArchiveSharpclone is needed to build. See Building.Meziantou.Analyzer3.0.235 → 3.0.236 (all projects),Avalonia.Diagnostics11.3.21 → 11.3.22 (GUI, Debug-only). Dev-only, no runtime impact.
- Checksum docs (xdvdfs Compat, XisoReader, Utilities) describe the BCL/managed-fallback behavior.
- Rewrite docs (XisoWriter) and the format reference (XISO Format) document the zero-size-directory handling and upstream parity.
- Reference/build docs updated for the NuGet-only ZArchiveSharp consumption and
the
extract-xiso-build-202609111233reference drop. - Library README intro no longer pins a single extract-xiso version number.
Solution-wide Roslynator formatting cleanup (line wrapping, Fill(0) →
Clear(), internal Sha3_256 → Sha3256 rename).
Initial NuGet release: pure-C# port of extract-xiso v2.7.1 (byte-identical
output) extended with XboxKit archival workflows and xdvdfs packing
(build-image remapping, CISO, SHA3-256 checksums). See the
README for the full feature list.