os: Readlink returns garbage when symlink target is like \\?\Volume{XXXXX}\
Closed this issue · 4 comments
What version of Go are you using (go version)?
go version devel +8ee9bca272 Wed Feb 27 08:22:03 2019 +0000 windows/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env)?
go env Output
set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users\Alex\AppData\Local\go-build set GOEXE=.exe set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOOS=windows set GOPATH=c:\users\alex\dev set GOPROXY= set GORACE= set GOROOT=c:\users\alex\dev\go set GOTMPDIR= set GOTOOLDIR=c:\users\alex\dev\go\pkg\tool\windows_amd64 set GCCGO=gccgo set CC=gcc set CXX=g++ set CGO_ENABLED=1 set GOMOD= set CGO_CFLAGS=-g -O2 set CGO_CPPFLAGS= set CGO_CXXFLAGS=-g -O2 set CGO_FFLAGS=-g -O2 set CGO_LDFLAGS=-g -O2 set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\Alex\AppData\Local\Temp\go-build403512930=/tmp/go-build -gno-record-gcc-switches
What did you do?
I run go test command against this main_test.go file
package main_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
func TestReadlink(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "TestReadlink")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
vol := filepath.VolumeName(tmpdir)
output, err := exec.Command("cmd", "/c", "mountvol", vol, "/L").CombinedOutput()
if err != nil {
t.Fatalf("failed to run mountvol %v /L: %v %q", vol, err, output)
}
target := strings.Trim(string(output), " \n\r")
dirlink := filepath.Join(tmpdir, "dirlink")
output, err = exec.Command("cmd", "/c", "mklink", "/J", dirlink, target).CombinedOutput()
if err != nil {
t.Fatalf("failed to run mklink %v %v: %v %q", dirlink, target, err, output)
}
got, err := os.Readlink(dirlink)
if err != nil {
t.Fatal(err)
}
if want := vol + `\`; got != want {
t.Errorf(`os.Readlink(%q): got %q, want %q`, dirlink, got, want)
}
}What did you expect to see?
I expected test to pass.
What did you see instead?
Test fails with this error:
--- FAIL: TestReadlink (0.17s)
main_test.go:37: os.Readlink("C:\\Users\\Alex\\AppData\\Local\\Temp\\TestReadlink551162827\\dirlink"): got "Volume{ea961e77-0000-0000-0000-501f00000000}\\", want "C:\\"
FAIL
The problem here is that os.Readlink does not handle links where target looks like this \\?\Volume{XXXXX}\. Volume{ea961e77-0000-0000-0000-501f00000000}\\ that os.Readlink returns is not useful for anything.
We have to handle symlinks, like that, because, for example, windows-arm TMP directory is such link (see #29746 (comment) for details). So it will be quite common at least on windows-arm.
Alex
Change https://golang.org/cl/164201 mentions this issue: os: make Readlink work with symlinks with target like \??\Volume{ABCD}\
@jhowardmsft FYI, please, see https://golang.org/cl/164201 - hopefully it will be part of go1.13.
Alex
@alexbrainman Thanks for pinging me on this. @jiria FYI
containerd/continuity@8100e75 referred to this issue, but I believe its use of Readlink was (and still is) incorrect; see containerd/continuity#232.