os: do not report ModeDir for symlinks on windows When using Lstat against symlinks that point to a directory, the function returns FileInfo with both ModeDir and ModeSymlink set. Change that to never set ModeDir if ModeSymlink is set. Fixes #10424 Fixes #17540 Fixes #17541 Change-Id: Iba280888aad108360b8c1f18180a24493fe7ad2b Reviewed-on: https://go-review.googlesource.com/41830 Reviewed-by: Daniel Martà <mvdan@mvdan.cc> Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Daniel Martà <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/archive/tar/tar_test.go b/src/archive/tar/tar_test.go index 10a16dd..1cb7ec2 100644 --- a/src/archive/tar/tar_test.go +++ b/src/archive/tar/tar_test.go
@@ -12,7 +12,6 @@ "path" "path/filepath" "reflect" - "runtime" "strings" "testing" "time" @@ -72,9 +71,6 @@ func TestFileInfoHeaderSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - if runtime.GOOS == "windows" { - t.Skip("skipping broken test: see issue 17541") - } tmpdir, err := ioutil.TempDir("", "TestFileInfoHeaderSymlink") if err != nil { t.Fatal(err)
diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go index 3e82f69..84066de 100644 --- a/src/os/os_windows_test.go +++ b/src/os/os_windows_test.go
@@ -153,6 +153,20 @@ t.Errorf("%q should point to %q", link, dir) continue } + + fi2, err := os.Lstat(link) + if err != nil { + t.Errorf("failed to lstat link %v: %v", link, err) + continue + } + if m := fi2.Mode(); m&os.ModeSymlink == 0 { + t.Errorf("%q should be a link, but is not (mode=0x%x)", link, uint32(m)) + continue + } + if m := fi2.Mode(); m&os.ModeDir != 0 { + t.Errorf("%q should be a link, not a directory (mode=0x%x)", link, uint32(m)) + continue + } } }
diff --git a/src/os/types_windows.go b/src/os/types_windows.go index 772b9e5..a0d6fa4 100644 --- a/src/os/types_windows.go +++ b/src/os/types_windows.go
@@ -32,16 +32,16 @@ if fs == &devNullStat { return ModeDevice | ModeCharDevice | 0666 } - if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - m |= ModeDir | 0111 - } if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 { m |= 0444 } else { m |= 0666 } if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 { - m |= ModeSymlink + return m | ModeSymlink + } + if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { + m |= ModeDir | 0111 } switch fs.filetype { case syscall.FILE_TYPE_PIPE:
diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go index d2a78f5..315f61e 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go
@@ -1377,8 +1377,5 @@ func TestWalkSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - if runtime.GOOS == "windows" { - t.Skip("skipping broken test: see issue 17540") - } testWalkSymlink(t, os.Symlink) }
diff --git a/src/path/filepath/path_windows_test.go b/src/path/filepath/path_windows_test.go index 0663778..d759a83 100644 --- a/src/path/filepath/path_windows_test.go +++ b/src/path/filepath/path_windows_test.go
@@ -451,12 +451,10 @@ func TestWalkDirectoryJunction(t *testing.T) { testenv.MustHaveSymlink(t) - t.Skip("skipping broken test: see issue 10424") testWalkMklink(t, "J") } func TestWalkDirectorySymlink(t *testing.T) { testenv.MustHaveSymlink(t) - t.Skip("skipping broken test: see issue 17540") testWalkMklink(t, "D") }