506 Commits

Author SHA1 Message Date
Matt Nadareski
9aeaac1b9d Change test frameworks to .NET 10 and 11 only rolling 2026-11-13 16:23:21 +01:00
Matt Nadareski
b325212664 Bump version 2.4.0 2026-11-11 11:18:54 +01:00
Matt Nadareski
70e6bdd41c Add .NET 11 support 2026-11-11 10:29:50 +01:00
gmipf
6dddf7db37 Do not follow linked directories in SafeGetFiles outside of Windows (#8)
* Do not follow linked directories in SafeGetFiles outside of Windows

SafeGetFiles with SearchOption.AllDirectories follows directory symlinks.
On Linux, the UDF view of some PC/Mac hybrid discs has symlinks whose
target reads as empty, and each one resolves to its own folder, so the
recursion never ends (fixes #2, SabreTools/BinaryObjectScanner#276).

Outside of Windows, walk the tree one directory at a time and do not enter
directories that carry FileAttributes.ReparsePoint. Files are matched with
Directory.GetFiles per directory, so the pattern behaves as before, and the
order is the same breadth-first order. Windows keeps Directory.GetFiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Do not follow linked directories in the other AllDirectories overloads

SafeGetDirectories and the SafeEnumerateDirectories, SafeEnumerateFiles
and SafeEnumerateFileSystemEntries wrappers follow directory symlinks in
the same way. On Linux, with one directory linked to itself,
SafeEnumerateFiles returns 43 files instead of 2, and with three such
links it is still running after 10 seconds.

The walk from SafeGetFiles is now a lazy iterator that all of them share,
so the Enumerate wrappers stay lazy. Each directory is listed with the
matching overload without SearchOption (Directory.GetFiles,
SafeEnumerateFiles and so on), so patterns and inaccessible directories
behave as in the recursive search. If the attributes of a subdirectory
cannot be read, such as below a directory without execute permission, it
is entered anyway, so it fails in the same way as in the recursive search.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Check for linked directories without catching exceptions

DirectoryInfo.Exists returns false where the attributes cannot be read, and the criteria for the walk are checked one at a time with their reasons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:52:11 +01:00
Matt Nadareski
e4728b3809 Update GrindCore to 0.10.0 2026-11-07 05:24:31 -05:00
Matt Nadareski
edd6b36826 Mount points should be left alone 2026-11-04 07:13:45 -05:00
Matt Nadareski
118e2078ea Handle space encoding in mount points and volume labels 2026-11-03 21:29:56 -05:00
Matt Nadareski
804f87e1a8 Fix incorrect replacement path 2026-11-03 20:52:14 -05:00
Matt Nadareski
8afc57b709 Relative paths don't resolve on Linux properly 2026-11-03 20:47:55 -05:00
Matt Nadareski
7f2d2e7ada Add label-finding extensions for Linux in .NET 6 and above 2026-11-03 20:20:13 -05:00
Matt Nadareski
9e25afe28b Simplify remaining device extensions tests 2026-11-02 08:46:06 -05:00
Matt Nadareski
e01891e779 Reduce surface area of tests and issues in device extensions 2026-11-02 08:05:15 -05:00
Matt Nadareski
77be01db2d This can be a List on all .NET versions 2026-11-02 07:50:59 -05:00
Matt Nadareski
17af1318b2 Move some information from summary to remarks 2026-11-02 07:48:10 -05:00
Matt Nadareski
1b1bea3a17 Separate out device extensions 2026-11-02 07:43:13 -05:00
Matt Nadareski
1ffc627d8a Port mount point methods from MPF 2026-11-02 07:36:25 -05:00
gmipf
e818a322ac Fix MS-ZIP blocks that end with short codes or copy from 32 KiB back (#7)
* Decode short codes at the end of the inflate input

InflateCodes waited for as many bits as its lookup table uses before
it decoded a literal, length or distance code. When the input ended
with fewer bits than that, the last codes were not decoded, even though
they were complete. An MS-ZIP block is a deflate stream on its own, so
its last match was lost and the block came out short (#1).

When no more input is there, the code is now looked up with the bits
that are left and used if it is not longer than those.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep a full 32 KiB inflate dictionary

SetDictionary kept only the last 32767 bytes of a 32 KiB dictionary,
because the window needs one free byte between its read and write
positions. MS-ZIP sets the previous 32 KiB block as the dictionary,
and a match at the start of a block can copy from 32768 bytes back,
which then read a byte that was not in the window.

A dictionary that fills the window now starts with the read and write
positions at 0, so the first byte written replaces the oldest byte of
the dictionary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 21:35:22 -04:00
gmipf
840b7e2d8a Dispose the streams of a ReadOnlyCompositeStream (#6)
Disposing a ReadOnlyCompositeStream did not dispose the streams it
reads from, so files opened only for the composite stayed open until
their streams were finalized. WiseOverlayHeader.OpenFile in
SabreTools.Serialization opens a Wise installer and all of its parts
this way.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 09:40:57 -04:00
gmipf
19d73bd170 Parse doubles with the invariant culture in ConvertToDouble (#5)
* Parse doubles with the invariant culture

ConvertToDouble used double.TryParse with the current culture, so a
value like "59.940000" became 59940000 on a German system and null on a
French one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Drop the culture reset from the ConvertToDouble test

A culture set inside a test does not carry over to the next test, so
the reset and the try/finally around it are not needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 11:14:53 -04:00
Matt Nadareski
f1d745471b Fix prefixed string reading, add more tests (fixes #4) 2026-10-15 09:16:01 -04:00
Matt Nadareski
0d0d73e6f9 Add GetAppDataDirectory due to OSX need 2026-10-14 21:40:37 -04:00
Matt Nadareski
04aa537d88 Forgot about .NET Standard 2026-10-14 21:27:10 -04:00
Matt Nadareski
ffd0d22402 Port SystemEnvironment helpers from MPF 2026-10-14 21:21:04 -04:00
gmipf
f6b6aa1e14 Allow 0-byte reads at the end of a byte array (#3)
* Allow 0-byte reads at the end of a byte array

ReadBytes(ref offset, 0) threw ArgumentOutOfRangeException when offset
was equal to the array length, before the 0-byte case was handled. The
same happened for a 0-byte read from an empty array, and TryReadBytes
with a count of 0 at the end threw instead of returning true. The offset
check now accepts the end of the array for a 0-byte read only; reads past
the end still throw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Handle 0-byte reads before the offset check

Same order as the stream version of ReadExactlyToBuffer, applied to
both byte array copies (Numerics.Extensions and IO.Extensions).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:20:30 -04:00
Matt Nadareski
4235315f58 Unix IO stuff ported/opnened from MPF 2026-10-12 11:00:43 -04:00
Matt Nadareski
115cbf3f2b Update packages 2026-10-12 09:47:53 -04:00
Matt Nadareski
8695e58c27 Bump version 2.3.0 2026-08-28 13:00:14 -04:00
Matt Nadareski
c80fae5506 Fix compression readme 2026-08-27 15:22:33 -04:00
Matt Nadareski
42aa3791ba Add GrindCore notes 2026-08-27 14:21:52 -04:00
Matt Nadareski
b90312512b Remove older zlib implementation in lieu of GrindCore 2026-08-27 09:38:56 -04:00
Matt Nadareski
78eec76d25 Update Hashing to 2.1.0 2026-08-27 09:25:20 -04:00
Matt Nadareski
636bac5e1b Replace internal version of BZip2 with GrindCore 2026-08-26 18:04:21 -04:00
Matt Nadareski
a85242a7d9 Update GrindCore to 0.9.0 2026-08-26 16:33:06 -04:00
Matt Nadareski
0b9c4559a1 Update packages 2026-08-20 11:40:02 -04:00
Matt Nadareski
c4b41e1f2c Add local appdata PathTool method 2026-07-12 09:14:57 -04:00
Matt Nadareski
78c6c1b6f6 Bump version 2.2.0 2026-07-10 11:10:33 -04:00
Matt Nadareski
9d04185b21 Use explicit enum values matching automatic values
This is being done to avoid any API-breaking changes in the future. If the values are set explicitly, added values either need to force a major version update or get added as the next-highest values.
2026-07-10 09:58:04 -04:00
Matt Nadareski
67d3e1f5c0 Update copyright dates 2026-07-10 09:54:37 -04:00
Matt Nadareski
a2598c85ed Relax requirements 2026-07-10 09:54:19 -04:00
Matt Nadareski
e07da60916 These helpers should be private 2026-07-09 16:03:47 -04:00
Matt Nadareski
72c523595e Give reasonable defaults to recent helpers 2026-07-09 16:01:55 -04:00
Matt Nadareski
c60f45073d Fix some tests that broke last minute 2026-07-09 15:58:03 -04:00
Matt Nadareski
486c95582f Port *nix device methods, update tests 2026-07-09 15:45:00 -04:00
Matt Nadareski
bf4c6bf703 Rename some type parameters to be more descriptive 2026-07-09 09:55:39 -04:00
Matt Nadareski
6045830bbb Add generic version of dictionary merge 2026-07-09 09:52:40 -04:00
Matt Nadareski
433f37a789 Handle some "== null" replacements 2026-07-09 09:45:09 -04:00
Matt Nadareski
871422ad23 Update test packages 2026-07-09 09:39:09 -04:00
Matt Nadareski
9281796251 ResolvePath should always return an aboslute path 2026-07-02 10:21:15 -04:00
Matt Nadareski
a893de700a Add ResolvePath extension from MPF 2026-07-02 10:01:18 -04:00
Matt Nadareski
99caebd49b Remove CONTRIBUTING due to org-level version 2026-05-16 15:04:34 -04:00