Skip to content

Add FileHandleType enum and SafeFileHandle.Type property#124561

Merged
adamsitnik merged 33 commits intomainfrom
copilot/add-filetype-enum-and-getfiletype-method
Mar 9, 2026
Merged

Add FileHandleType enum and SafeFileHandle.Type property#124561
adamsitnik merged 33 commits intomainfrom
copilot/add-filetype-enum-and-getfiletype-method

Conversation

Copy link
Contributor

Copilot AI commented Feb 18, 2026

Description

Adds System.IO.FileHandleType enum and SafeFileHandle.Type property for efficient runtime detection of file handle types. POC implementation to validate API feasibility before formal proposal (issue #122806).

Changes

API Surface

  • System.IO.FileHandleType enum: 8 values (Unknown, RegularFile, Pipe, Socket, CharacterDevice, Directory, SymbolicLink, BlockDevice). All values supported cross-platform; BlockDevice returns Unknown on Windows.

  • SafeFileHandle.Type property: Returns cached FileHandleType. Throws ObjectDisposedException when closed. Single syscall per handle lifetime via volatile int _cachedFileType.

Implementation

Windows (SafeFileHandle.Windows.cs):

  • GetFileTypeCore(): Maps GetFileType() result to enum values
  • FILE_TYPE_PIPE: Calls GetNamedPipeInfo; success → Pipe, ERROR_PIPE_NOT_CONNECTED → Pipe, else → Socket
  • FILE_TYPE_DISK: Queries attributes + reparse tag via GetFileInformationByHandleEx; only IO_REPARSE_TAG_SYMLINK → SymbolicLink, other reparse points → Unknown
  • CanSeek: Now checks Type == RegularFile (excludes directories/symlinks, was FILE_TYPE_DISK)

Unix (SafeFileHandle.Unix.cs):

  • GetFileTypeCore(): fstat + S_IFMT mode bit mapping
  • Init(): Opportunistically caches type when fstat already performed (line 343)
  • Exceptions include Path parameter for diagnostics

Interop:

  • Interop.GetNamedPipeInfo.cs: Parameter changed SafePipeHandle → SafeHandle (CoreLib cannot reference SafePipeHandle)
  • Interop.FILE_ATTRIBUTE_TAG_INFO.cs: New struct + FileAttributeTagInfo constant for reparse tag queries
  • Interop.GetFileType_SafeHandle.cs: Added to System.IO.Ports for downlevel multi-targeting

System.IO.Ports:

  • SerialStream.Windows.cs: Uses Type property on NET11_0_OR_GREATER, falls back to GetFileType() on older targets

Example

using SafeFileHandle handle = File.OpenHandle("file.txt", FileMode.Open);
FileHandleType type = handle.Type;  // FileHandleType.RegularFile (cached)

using SafeFileHandle console = Console.OpenStandardInputHandle();
console.Type;  // FileHandleType.CharacterDevice

Notes

  • All code review feedback addressed: error code handling, reparse tag checking, exception diagnostics, nullable annotations
  • Comprehensive test coverage: 9,195 tests pass, 0 failures
  • CanSeek behavior tightened on Windows (now excludes directories/symlinks)
  • Multi-targeting in System.IO.Ports demonstrates backward compatibility pattern

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits February 18, 2026 17:13
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

Copilot AI changed the title [WIP] Add FileType enum and extend SafeFileHandle with GetFileType Add FileType enum and SafeFileHandle.GetFileType() method Feb 18, 2026
Copilot AI requested a review from adamsitnik February 18, 2026 17:36
Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 18, 2026

@copilot please address my feedback

All feedback has been addressed in commit 9edcc96.

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

…API in CanSeek

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 18, 2026

@copilot address my feedback

All feedback addressed in commit 1f0655f.

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 18, 2026

@copilot please address my feedback

All feedback addressed in commit 8994464.

@adamsitnik
Copy link
Member

⚠️ CanSeek Behavior Change
Changed from FILE_TYPE_DISK (includes dirs/symlinks) to RegularFile (excludes them). Semantically correct but is a behavioral change. Verify ~46 callsites handle this.

@adamsitnik what can you tell me about this? Is it correct or incorrect, and if correct, is this expected?

So far, CanSeek was returning true for file, directories and symlinks. But we don't allow opening directories with our File APIs (as handles) and even if we did, it's not possible to read from directory using File/FileStream/RandomAccess APIs. For symlinks, we always resolve the symlinks and all our APIs for reading file content deal with the resolved file rather than symlink.

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@adamsitnik adamsitnik requested review from jkotas and stephentoub March 4, 2026 19:15
Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants