Skip to content

Conversation

@vagokuln-msft
Copy link

Summary

Adds support for LX symlinks (IO_REPARSE_TAG_LX_SYMLINK, tag 0xA000001D) used by WSL and MSYS2 for native Unix-style symlinks.

Problem

Docker builds using MSYS2 with native symlinks (MSYS=winsymlinks:native) fail with error "unsupported reparse point a000001d" because go-winio doesn't recognize LX symlink reparse tags.

Solution

  • Added reparseTagLxSymlink constant (0xA000001D)
  • Implemented decode for LX symlinks (UTF-8 format with 4-byte version prefix)
  • Added IsLxSymlink field to preserve symlink type through encode/decode cycles
  • Implemented encode to recreate LX symlinks in native format

Testing

  • Unit tests for encode/decode round-trip
  • Validated with Docker MSYS2 container builds
  • Tested docker commit, save/load cycles preserve LX symlinks correctly

@vagokuln-msft vagokuln-msft requested a review from a team as a code owner November 11, 2025 22:57
@vagokuln-msft
Copy link
Author

@microsoft-github-policy-service agree company="Microsoft"

- Add reparseTagLxSymlink constant (0xA000001D)
- Implement decode logic for LX symlinks (UTF-8 format)
- Add IsLxSymlink field to ReparsePoint struct to preserve symlink type
- Implement encode logic to recreate LX symlinks on import
- Add unit tests for LX symlink round-trip validation

Fixes issue where Docker builds with MSYS2 failed with 'unsupported reparse point a000001d' error.

Signed-off-by: Varun Gokulnath <[email protected]>
Extract LX symlink encode/decode into separate functions for better
maintainability and cleaner separation of concerns.

Signed-off-by: Varun Gokulnath <[email protected]>
@msscotb msscotb assigned msscotb and Kishon-Microsoft and unassigned msscotb Nov 14, 2025
@vagokuln-msft
Copy link
Author

@msscotb @Kishon-Microsoft, could you please review this change? We hope to get this merged soon as it has been a few weeks since the PR was opened. Thanks!

dataLength := 4 + len(targetBytes)

var b bytes.Buffer
_ = binary.Write(&b, binary.LittleEndian, uint32(reparseTagLxSymlink))

Choose a reason for hiding this comment

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

Any specific reason for discarding the errors?

// mount point.
// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink,
// mount point, or LX symlink.
func EncodeReparsePoint(rp *ReparsePoint) []byte {

Choose a reason for hiding this comment

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

Can we guard against passing a nil value?

"testing"
)

func TestLxSymlinkRoundTrip(t *testing.T) {

Choose a reason for hiding this comment

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

Can we add tests for other scenarios? atleast with empty Target?


func encodeLxReparsePoint(rp *ReparsePoint) []byte {
// LX symlink: 4-byte version + UTF-8 target
version := uint32(2)

Choose a reason for hiding this comment

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

Adding something like const lxSymlinkVersion = 2 and then using it here would be clean.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants