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) { ...@@ -962,13 +962,22 @@ func Readlink(path string, buf []byte) (n int, err error) {
} }
rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0])) rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
if uintptr(bytesReturned) < unsafe.Sizeof(*rdb) || var s string
rdb.ReparseTag != IO_REPARSE_TAG_SYMLINK { switch rdb.ReparseTag {
// the path is not a symlink but another type of reparse point 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 return -1, syscall.ENOENT
} }
s := UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rdb.PathBuffer[0]))[:rdb.PrintNameLength/2])
n = copy(buf, []byte(s)) n = copy(buf, []byte(s))
return n, nil return n, nil
} }
...@@ -1089,12 +1089,7 @@ type TCPKeepalive struct { ...@@ -1089,12 +1089,7 @@ type TCPKeepalive struct {
Interval uint32 Interval uint32
} }
type reparseDataBuffer struct { type symbolicLinkReparseBuffer struct {
ReparseTag uint32
ReparseDataLength uint16
Reserved uint16
// SymbolicLinkReparseBuffer
SubstituteNameOffset uint16 SubstituteNameOffset uint16
SubstituteNameLength uint16 SubstituteNameLength uint16
PrintNameOffset uint16 PrintNameOffset uint16
...@@ -1103,9 +1098,27 @@ type reparseDataBuffer struct { ...@@ -1103,9 +1098,27 @@ type reparseDataBuffer struct {
PathBuffer [1]uint16 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 ( const (
FSCTL_GET_REPARSE_POINT = 0x900A8 FSCTL_GET_REPARSE_POINT = 0x900A8
MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024 MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024
IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003
IO_REPARSE_TAG_SYMLINK = 0xA000000C IO_REPARSE_TAG_SYMLINK = 0xA000000C
SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1 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