Skip to content

Instantly share code, notes, and snippets.

@hymkor
Created March 24, 2019 00:31
Show Gist options
  • Save hymkor/19a2f425b53ce21e6bcbe4a95e39e8c3 to your computer and use it in GitHub Desktop.
Save hymkor/19a2f425b53ce21e6bcbe4a95e39e8c3 to your computer and use it in GitHub Desktop.
Go で Windows のジャンクションを作ろうとしているけれども、なんかうまくいかないソース
package main
import (
"os"
"unsafe"
"errors"
"golang.org/x/sys/windows"
"golang.org/x/xerrors"
)
const (
_MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384
_FSCTL_SET_REPARSE_POINT = 589988
_INVALID_HANDLE_VALUE = ^windows.Handle(0)
)
type _MountPointInfo struct {
Tag uint32
DataLength uint16
Reserved uint16
TargetOffset uint16
TargetByteLength uint16
DescriptionOffset uint16
DescriptionByteLength uint16
Buffer [(_MAXIMUM_REPARSE_DATA_BUFFER_SIZE - 4 - 2*6) / 2]uint16
}
func MountPointCreate(mountPointPath, target string) error {
_mountPointPath, err := windows.UTF16FromString(mountPointPath)
if err != nil {
return xerrors.Errorf("UTF16FromString(%s): %v", mountPointPath, err)
}
_target, err := windows.UTF16FromString(target)
if err != nil {
return xerrors.Errorf("UTF16FromString(%s): %v", target, err)
}
var info _MountPointInfo
info.Tag = windows.IO_REPARSE_TAG_MOUNT_POINT
info.TargetOffset = 0
info.TargetByteLength = uint16(len(_target) * 2 )
for i := 0 ; i < len(_target) ; i++ {
info.Buffer[i] = _target[i]
}
// copy(info.Buffer[:], _target)
info.Buffer[len(_target)] = 0
info.DescriptionOffset = uint16((len(_target)+1) * 2)
info.DescriptionByteLength = 0
info.DataLength = uint16(8 + (len(_target)+1+1)*2)
err = windows.CreateDirectory(&_mountPointPath[0], nil)
if err != nil {
return xerrors.Errorf("windows.CreateDirectory(%s): %v", mountPointPath, err)
}
handle, err := windows.CreateFile(&_mountPointPath[0],
windows.GENERIC_WRITE,
0,
nil,
windows.OPEN_EXISTING,
windows.FILE_FLAG_BACKUP_SEMANTICS,
0)
if err != nil {
return xerrors.Errorf("windows.CreateFile(%s): %v", mountPointPath, err)
}
if handle == _INVALID_HANDLE_VALUE {
return errors.New("windows.CreateFile: invalid handle value")
}
defer windows.CloseHandle(handle)
var size uint32
err = windows.DeviceIoControl(
handle,
_FSCTL_SET_REPARSE_POINT,
(*byte)(unsafe.Pointer(&info)),
uint32(8+info.DataLength),
nil,
0,
&size,
nil)
if err != nil {
return xerrors.Errorf("windows.DeviceIoControl: %v", err)
}
return nil
}
func main() {
if len(os.Args) < 3 {
println("go run junction.go DST SRC")
return
}
if err := MountPointCreate(os.Args[1], os.Args[2]); err != nil {
println(err.Error())
os.Exit(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment