Refactor LX symlink logic into dedicated functions

Extract LX symlink encode/decode into separate functions for better
maintainability and cleaner separation of concerns.

Signed-off-by: Varun Gokulnath <vagokuln@microsoft.com>
Signed-off-by: Varun Gokulnath <gvarun22@outlook.com>
This commit is contained in:
Varun Gokulnath
2025-12-17 11:16:26 -08:00
committed by Varun Gokulnath
parent 3ffe560692
commit 4efa80daf1
+31 -16
View File
@@ -53,12 +53,33 @@ func DecodeReparsePoint(b []byte) (*ReparsePoint, error) {
}
func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
isMountPoint := false
switch tag {
case reparseTagMountPoint:
isMountPoint = true
return decodeWindowsReparsePointData(b, true)
case reparseTagSymlink:
return decodeWindowsReparsePointData(b, false)
case reparseTagLxSymlink:
return decodeLxReparsePointData(b)
default:
return nil, &UnsupportedReparsePointError{tag}
}
}
func decodeWindowsReparsePointData(b []byte, isMountPoint bool) (*ReparsePoint, error) {
nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6])
if !isMountPoint {
nameOffset += 4
}
nameLength := binary.LittleEndian.Uint16(b[6:8])
name := make([]uint16, nameLength/2)
err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name)
if err != nil {
return nil, err
}
return &ReparsePoint{Target: string(utf16.Decode(name)), IsMountPoint: isMountPoint, IsLxSymlink: false}, nil
}
func decodeLxReparsePointData(b []byte) (*ReparsePoint, error) {
// LX symlinks store the target as UTF-8 after a 4-byte version field
if len(b) < 4 {
return nil, errors.New("LX symlink buffer too short")
@@ -72,20 +93,6 @@ func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
}
target := string(targetBytes)
return &ReparsePoint{Target: target, IsMountPoint: false, IsLxSymlink: true}, nil
default:
return nil, &UnsupportedReparsePointError{tag}
}
nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6])
if !isMountPoint {
nameOffset += 4
}
nameLength := binary.LittleEndian.Uint16(b[6:8])
name := make([]uint16, nameLength/2)
err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name)
if err != nil {
return nil, err
}
return &ReparsePoint{string(utf16.Decode(name)), isMountPoint, false}, nil
}
func isDriveLetter(c byte) bool {
@@ -96,6 +103,12 @@ func isDriveLetter(c byte) bool {
// mount point, or LX symlink.
func EncodeReparsePoint(rp *ReparsePoint) []byte {
if rp.IsLxSymlink {
return encodeLxReparsePoint(rp)
}
return encodeWindowsReparsePoint(rp)
}
func encodeLxReparsePoint(rp *ReparsePoint) []byte {
// LX symlink: 4-byte version + UTF-8 target
version := uint32(2)
targetBytes := []byte(rp.Target)
@@ -110,6 +123,8 @@ func EncodeReparsePoint(rp *ReparsePoint) []byte {
return b.Bytes()
}
func encodeWindowsReparsePoint(rp *ReparsePoint) []byte {
// Generate an NT path and determine if this is a relative path.
var ntTarget string
relative := false