mirror of
https://github.com/rwinkhart/go-winio.git
synced 2026-09-06 00:57:19 -04:00
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:
committed by
Varun Gokulnath
parent
3ffe560692
commit
4efa80daf1
+43
-28
@@ -53,28 +53,19 @@ func DecodeReparsePoint(b []byte) (*ReparsePoint, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
|
func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
|
||||||
isMountPoint := false
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case reparseTagMountPoint:
|
case reparseTagMountPoint:
|
||||||
isMountPoint = true
|
return decodeWindowsReparsePointData(b, true)
|
||||||
case reparseTagSymlink:
|
case reparseTagSymlink:
|
||||||
|
return decodeWindowsReparsePointData(b, false)
|
||||||
case reparseTagLxSymlink:
|
case reparseTagLxSymlink:
|
||||||
// LX symlinks store the target as UTF-8 after a 4-byte version field
|
return decodeLxReparsePointData(b)
|
||||||
if len(b) < 4 {
|
|
||||||
return nil, errors.New("LX symlink buffer too short")
|
|
||||||
}
|
|
||||||
targetBytes := b[4:]
|
|
||||||
for i, c := range targetBytes {
|
|
||||||
if c == 0 {
|
|
||||||
targetBytes = targetBytes[:i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target := string(targetBytes)
|
|
||||||
return &ReparsePoint{Target: target, IsMountPoint: false, IsLxSymlink: true}, nil
|
|
||||||
default:
|
default:
|
||||||
return nil, &UnsupportedReparsePointError{tag}
|
return nil, &UnsupportedReparsePointError{tag}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeWindowsReparsePointData(b []byte, isMountPoint bool) (*ReparsePoint, error) {
|
||||||
nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6])
|
nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6])
|
||||||
if !isMountPoint {
|
if !isMountPoint {
|
||||||
nameOffset += 4
|
nameOffset += 4
|
||||||
@@ -85,7 +76,23 @@ func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ReparsePoint{string(utf16.Decode(name)), isMountPoint, false}, nil
|
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")
|
||||||
|
}
|
||||||
|
targetBytes := b[4:]
|
||||||
|
for i, c := range targetBytes {
|
||||||
|
if c == 0 {
|
||||||
|
targetBytes = targetBytes[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target := string(targetBytes)
|
||||||
|
return &ReparsePoint{Target: target, IsMountPoint: false, IsLxSymlink: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isDriveLetter(c byte) bool {
|
func isDriveLetter(c byte) bool {
|
||||||
@@ -96,19 +103,27 @@ func isDriveLetter(c byte) bool {
|
|||||||
// mount point, or LX symlink.
|
// mount point, or LX symlink.
|
||||||
func EncodeReparsePoint(rp *ReparsePoint) []byte {
|
func EncodeReparsePoint(rp *ReparsePoint) []byte {
|
||||||
if rp.IsLxSymlink {
|
if rp.IsLxSymlink {
|
||||||
// LX symlink: 4-byte version + UTF-8 target
|
return encodeLxReparsePoint(rp)
|
||||||
version := uint32(2)
|
|
||||||
targetBytes := []byte(rp.Target)
|
|
||||||
dataLength := 4 + len(targetBytes)
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
|
||||||
_ = binary.Write(&b, binary.LittleEndian, uint32(reparseTagLxSymlink))
|
|
||||||
_ = binary.Write(&b, binary.LittleEndian, uint16(dataLength))
|
|
||||||
_ = binary.Write(&b, binary.LittleEndian, uint16(0))
|
|
||||||
_ = binary.Write(&b, binary.LittleEndian, version)
|
|
||||||
_, _ = b.Write(targetBytes)
|
|
||||||
return b.Bytes()
|
|
||||||
}
|
}
|
||||||
|
return encodeWindowsReparsePoint(rp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeLxReparsePoint(rp *ReparsePoint) []byte {
|
||||||
|
// LX symlink: 4-byte version + UTF-8 target
|
||||||
|
version := uint32(2)
|
||||||
|
targetBytes := []byte(rp.Target)
|
||||||
|
dataLength := 4 + len(targetBytes)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
_ = binary.Write(&b, binary.LittleEndian, uint32(reparseTagLxSymlink))
|
||||||
|
_ = binary.Write(&b, binary.LittleEndian, uint16(dataLength))
|
||||||
|
_ = binary.Write(&b, binary.LittleEndian, uint16(0))
|
||||||
|
_ = binary.Write(&b, binary.LittleEndian, version)
|
||||||
|
_, _ = b.Write(targetBytes)
|
||||||
|
return b.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeWindowsReparsePoint(rp *ReparsePoint) []byte {
|
||||||
|
|
||||||
// Generate an NT path and determine if this is a relative path.
|
// Generate an NT path and determine if this is a relative path.
|
||||||
var ntTarget string
|
var ntTarget string
|
||||||
|
|||||||
Reference in New Issue
Block a user