fix: skip named pipes, sockets and device nodes when scanning [patch] - #148
Merged
Merged
Conversation
On Unix, Directory.EnumerateFiles yields every entry that is not a directory, and .NET marks named pipes, sockets and device nodes with the same Normal attribute as a regular file. The hasher then opened a named pipe for reading, which blocks until a writer appears, so a single pipe anywhere in the tree hung Scan, DryRun, Stats and Deduplicate. ScanForFiles now keeps only regular files. The file type is read through the runtime's SystemNative_LStat shim, whose FileStatus layout the runtime defines with fixed-width fields and normalized type bits on every Unix, so no per-platform struct stat layout is involved. Fixes #136 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PNmrp6FP3tBU47owLsiovc
|
This was referenced Sep 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Scan, DryRun, Stats and Deduplicate no longer hang when the tree contains a named pipe. The scan now keeps only regular files, so pipes, sockets and device nodes never reach the hasher.
Cause
On Unix,
Directory.EnumerateFilesreturns every entry that isn't a directory. .NET gives named pipes, sockets and device nodes the sameNormalattribute as a regular file (checked on .NET 10), soWalkOptionscan't filter them.FileHasher.ComputeHashthen calledFile.OpenReadon the pipe, and that call blocks until a writer appears.Fix
FileType.IsRegularFile, called fromFileScanner.ScanForFilesnext to the existingReparsePointpolicy. Every verb shares that scan, so all four are fixed in one place.SystemNative_LStat, the runtime's own shim that backsFileInfoon Unix. This avoids thestruct statlayout problem raised on Hardlinked files are deduplicated like independent copies, risking silent data loss in snapshot/backup trees #132. The runtime definesFileStatuswith fixed-width fields, and the shim normalizes the type bits to the same values on every Unix. OnlyModeis read, at offset 4 after the 32-bitFlagsfield. The buffer is oversized so a field the runtime appends later can't overrun it.AllowUnsafeBlocks, because theLibraryImportsource generator needs it.Tests
ScanLeavesOutANamedPipe: amkfifoinside aTempTreeis left out, and an empty regular file next to it is still found.ScanAndHashFinishWhenTheTreeHoldsANamedPipe: scan and hash finish within 30 s, so a hang fails the test instead of stalling the run.FileScanner/FileTypechange, both tests fail. The second one hits the 30 s timeout. With the change, the full suite passes: 55 passed, plus 2 privilege-dependent tests that were already inconclusive because the environment runs as root.Scanover a directory holding two copies, a FIFO and a Unix socket now finishes and reports the one duplicate group. Onmainthe same run stops afterHashed: a -> ....Risk
SystemNative_LStatis a runtime export, not a documented public API. It has shipped since .NET Core 1.0, andFlagsandModehave always been its first two fields. If the export ever disappeared, the call would throw at scan time and the new tests would fail on every Unix leg.Relates to #132 (hardlinks). The same shim also returns
DevandIno, which may be a way past that issue's interop blocker. Deciding that is left to #132.Fixes #136
🤖 Generated with Claude Code
https://claude.ai/code/session_01PNmrp6FP3tBU47owLsiovc
Generated by Claude Code