Skip to content

Tar: Only treat reparse points marked as junctions or symlinks as actual tar symlinks#124753

Open
rzikm wants to merge 3 commits intodotnet:mainfrom
rzikm:fix/tar-reparse-point-82949
Open

Tar: Only treat reparse points marked as junctions or symlinks as actual tar symlinks#124753
rzikm wants to merge 3 commits intodotnet:mainfrom
rzikm:fix/tar-reparse-point-82949

Conversation

@rzikm
Copy link
Member

@rzikm rzikm commented Feb 23, 2026

Fixes #82949

Problem

On Windows, TarWriter.ConstructEntryForWriting classifies ALL files with the ReparsePoint file attribute as symbolic links. This is incorrect for files with non-symlink reparse points such as:

  • Deduplicated files (IO_REPARSE_TAG_DEDUP) - content is transparently accessible
  • OneDrive synced files - content is transparently accessible
  • AppExecLinks (IO_REPARSE_TAG_APPEXECLINK) - content is NOT accessible as a regular file

Solution

Use FileSystemInfo.LinkTarget to distinguish symlinks and junctions from other reparse point types. LinkTarget returns non-null only for IO_REPARSE_TAG_SYMLINK and IO_REPARSE_TAG_MOUNT_POINT (verified in FileSystem.Windows.cs:GetImmediateLinkTarget).

Classification logic:

  • Symlinks/junctions (LinkTarget is not null) - TarEntryType.SymbolicLink with the link target path
  • Non-symlink directory reparse points (e.g., OneDrive dirs) - TarEntryType.Directory
  • Non-symlink file reparse points with Normal/Archive (e.g., dedup files) - Regular file entry, content read via FileStream
  • Non-symlink reparse points where FileStream fails (e.g., AppExecLinks) - IOException with TarUnsupportedFile message
  • Other reparse points (no Normal/Archive/Directory attributes) - IOException with TarUnsupportedFile message

Changes

  • TarWriter.Windows.cs: Core fix - use LinkTarget for symlink/junction detection, let other reparse points fall through to attribute-based classification, catch FileStream failures for opaque reparse points
  • TarHelpers.cs: Added GetRegularFileEntryTypeForFormat helper
  • TarWriter.Unix.cs: Use new helper (consistency)
  • New Windows-only tests: Junction and AppExecLink scenarios (sync + async)
  • Test infrastructure: Moved GetAppExecLinkPath to shared ReparsePointUtilities.cs
  • 8 test files: Use GetRegularFileEntryTypeForFormat helper

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a critical bug where TarWriter on Windows incorrectly classified all reparse points (including data deduplication, OneDrive placeholders, and AppExecLinks) as symbolic links. The fix leverages the FileSystemInfo.LinkTarget property which only returns a non-null value for true symbolic links (IO_REPARSE_TAG_SYMLINK) and junctions (IO_REPARSE_TAG_MOUNT_POINT), allowing other reparse point types to be correctly classified as regular files or directories.

Changes:

  • Modified TarWriter.Windows.cs to check LinkTarget property instead of just the ReparsePoint attribute
  • Extracted GetRegularFileEntryTypeForFormat helper to TarHelpers.cs to eliminate duplication
  • Added comprehensive tests for junctions and non-symlink reparse points (using AppExecLinks)
  • Moved GetAppExecLinkPath utility to shared ReparsePointUtilities.cs for reuse across test projects

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
TarWriter.Windows.cs Core fix: checks LinkTarget is not null to distinguish symlinks/junctions from other reparse points; caches LinkTarget value to avoid redundant I/O
TarHelpers.cs Adds GetRegularFileEntryTypeForFormat helper method to centralize V7 vs regular file type selection logic
TarWriter.Unix.cs Refactored to use new helper method; removed unused using directives
TarWriter.WriteEntry.File.Tests.Windows.cs New test file with junction test and non-symlink reparse point test (sync version)
TarWriter.WriteEntryAsync.File.Tests.Windows.cs New test file with junction test and non-symlink reparse point test (async version)
System.Formats.Tar.Tests.csproj Registers new Windows-specific test files
TarTestsBase.cs Adds GetRegularFileEntryTypeForFormat helper for test code reuse
Various test files Replace inline ternary expressions with GetRegularFileEntryTypeForFormat helper for consistency
ReparsePointUtilities.cs Adds GetAppExecLinkPath method migrated from FileSystem tests for cross-project reuse
File/FileInfo SymbolicLinks.cs Updated to use MountHelper.GetAppExecLinkPath() instead of local method
BaseSymbolicLinks.FileSystem.cs Removed GetAppExecLinkPath (migrated to shared utilities); removed unused using directive

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.

…n Windows

Only treat reparse points as symbolic links when FileSystemInfo.LinkTarget
returns a non-null value, indicating the reparse point is a true symlink or
junction. Other reparse points (e.g., deduplication, OneDrive) now fall
through to be handled as regular files or directories.

Added GetRegularFileEntryTypeForFormat helper to reduce duplication of the
V7/regular file entry type check pattern across source and test files.

Moved GetAppExecLinkPath to shared ReparsePointUtilities so it can be used
by both FileSystem and Tar tests.

Added tests verifying junctions are correctly written as symbolic link
entries and that non-symlink reparse points are not misidentified.

Fixes dotnet#82949

Co-authored-by: Copilot <[email protected]>
@rzikm rzikm force-pushed the fix/tar-reparse-point-82949 branch from 926b2fd to 1e1492f Compare February 24, 2026 15:30
Copilot AI review requested due to automatic review settings February 24, 2026 15:43
@rzikm rzikm changed the title Fix TarWriter treating non-symlink reparse points as symbolic links on Windows Tar: Only treat reparse points marked as junctions or symlinks as actual tar symlinks Feb 24, 2026
@rzikm rzikm requested review from a team and removed request for a team February 24, 2026 15:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.

Remove FindFirstFile/GetFindData interop and use FileSystemInfo.LinkTarget
to detect symlinks and junctions. Non-symlink reparse points with file
attributes (e.g., dedup, OneDrive) fall through to be classified as regular
files or directories based on their attributes. Opaque reparse points (e.g.,
AppExecLinks) that cannot be read are caught at FileStream open and rethrown
with TarUnsupportedFile message.

Co-authored-by: Copilot <[email protected]>
@rzikm
Copy link
Member Author

rzikm commented Feb 25, 2026

@copilot run the code review skill

using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
#if !NETFRAMEWORK
Copy link
Member

Choose a reason for hiding this comment

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

why do we need the guards for io.enumeration? i see it was not used previously

Copy link
Member Author

Choose a reason for hiding this comment

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

System.IO.Enumeration is not available on .NET Framework, the build results from the previous PR are not available but I expect the build to have failed on .NET Framework then.

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.

TarWriter on Windows Server treats File Deduplication reparse point flag as symbolic links

3 participants