* Read directory extents in volume order
ParseDirectoryDescriptors now keeps one worklist of directory extents for
all volume descriptors, sorted by offset, and always reads the next
extent at or after the last one, wrapping around at the end. Each extent
is read once. The record loop moves to a shared helper.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Add a path lookup for ISO 9660 directory records
FindDirectoryRecords follows a path from the root directory of one
volume descriptor and reads only the directories on that path. Names
are compared case-insensitively, without the version suffix or a
trailing period. A file recorded in several extents returns all of its
records.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This will make it so that exceptions are surfaced directly into the test log and cancel right away. It effectively does the same thing as capturing the error log and redirecting it, but with many less steps.
* Stop writing after the last file of a cabinet folder
When the last data block of a folder held the end of two or more files,
WriteData still wrote the rest of the block after EndFile had closed the
last file, which threw an ObjectDisposedException. It now returns there,
as it already does when the first file in a block ends the folder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Simplify the console check in the cabinet extraction test
Extract catches the ObjectDisposedException and only writes it to
Console.Error, so the test still reads the console, but without the
try/finally. It now fails with the whole exception as its message.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The file of a custom dialog is named after the dialog name from the
script, which is free text. On Windows, a name like "Install under NT?"
is not a valid filename, so writing the file threw an IOException and
stopped the extraction.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Look for the Wise overlay header before opening the file again
ExtractWiseOverlay (and ExtractWise for NE) opened a second stream on
the executable for multi-part Wise installers before checking for a
Wise overlay header at all. For any other executable that stream was
never closed, so the file stayed open until the stream was finalized.
On Windows such a file cannot be deleted, so an extraction folder that
contains it is left behind in TEMP.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Close the Wise script and the multipart file after extraction
ExtractWiseOverlay (and ExtractWise for NE) never closed WiseScript.bin,
which it opens from the output directory, nor the stream with the
installer and its parts, so these files stayed open until their streams
were finalized.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Keep the original block that opens the multipart file
Close the multipart stream with a separate using declaration after the
block instead of rewriting it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ExtractWiseOverlay (and ExtractWise for NE) opened a second stream on
the executable for multi-part Wise installers before checking for a
Wise overlay header at all. For any other executable that stream was
never closed, so the file stayed open until the stream was finalized.
On Windows such a file cannot be deleted, so an extraction folder that
contains it is left behind in TEMP.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Locate the PKZIP file data instead of reading it into the model
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Keep only the offset of the PKZIP file data
The length is the compressed size from the local file header or the ZIP64
extended field, which the printer already shows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Keep the file data property as a comment for documentation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The DAT writers and the filter formatted Refresh and Freq with the
current culture, so a German or French system wrote "123,450000".
SabreTools.IO parses these values with the invariant culture.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ParseDirectory parsed the big-endian extent when the extent location
was valid (both values equal) instead of when it was ambiguous, so
every directory was parsed again, once per directory level.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>