Commit 61f8ff32 authored by Yasuhiro Matsumoto's avatar Yasuhiro Matsumoto Committed by Alex Brainman

windows: change Readlink to handle junction

Related issue golang/go#10150

Change-Id: I38e3e13238624655bb828d501bc865ff8a4312e9
Reviewed-on: https://go-review.googlesource.com/7493Reviewed-by: 's avatarAlex Brainman <alex.brainman@gmail.com>
parent d008cdcf
......@@ -962,13 +962,22 @@ func Readlink(path string, buf []byte) (n int, err error) {
}
rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
if uintptr(bytesReturned) < unsafe.Sizeof(*rdb) ||
rdb.ReparseTag != IO_REPARSE_TAG_SYMLINK {
// the path is not a symlink but another type of reparse point
var s string
switch rdb.ReparseTag {
case IO_REPARSE_TAG_SYMLINK:
data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2])
case IO_REPARSE_TAG_MOUNT_POINT:
data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2])
default:
// the path is not a symlink or junction but another type of reparse
// point
return -1, syscall.ENOENT
}
s := UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rdb.PathBuffer[0]))[:rdb.PrintNameLength/2])
n = copy(buf, []byte(s))
return n, nil
}
......@@ -1089,12 +1089,7 @@ type TCPKeepalive struct {
Interval uint32
}
type reparseDataBuffer struct {
ReparseTag uint32
ReparseDataLength uint16
Reserved uint16
// SymbolicLinkReparseBuffer
type symbolicLinkReparseBuffer struct {
SubstituteNameOffset uint16
SubstituteNameLength uint16
PrintNameOffset uint16
......@@ -1103,9 +1098,27 @@ type reparseDataBuffer struct {
PathBuffer [1]uint16
}
type mountPointReparseBuffer struct {
SubstituteNameOffset uint16
SubstituteNameLength uint16
PrintNameOffset uint16
PrintNameLength uint16
PathBuffer [1]uint16
}
type reparseDataBuffer struct {
ReparseTag uint32
ReparseDataLength uint16
Reserved uint16
// GenericReparseBuffer
reparseBuffer byte
}
const (
FSCTL_GET_REPARSE_POINT = 0x900A8
MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024
IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003
IO_REPARSE_TAG_SYMLINK = 0xA000000C
SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1
)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment