Commit 94dd0f02 authored by Hiroshi Ioka's avatar Hiroshi Ioka Committed by Alex Brainman

os: don't use a symlink's target path for FileInfo#Name on windows

Use an original name instead of a symlink's target path.

Fixes #20064

Change-Id: I9be3837a156bdcda0e9e065abbb425d535b27be3
Reviewed-on: https://go-review.googlesource.com/41310Reviewed-by: default avatarAlex Brainman <alex.brainman@gmail.com>
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 67399c62
...@@ -712,55 +712,58 @@ func TestSymlink(t *testing.T) { ...@@ -712,55 +712,58 @@ func TestSymlink(t *testing.T) {
Remove(from) // Just in case. Remove(from) // Just in case.
file, err := Create(to) file, err := Create(to)
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", to, err) t.Fatalf("Create(%q) failed: %v", to, err)
} }
defer Remove(to) defer Remove(to)
if err = file.Close(); err != nil { if err = file.Close(); err != nil {
t.Errorf("close %q failed: %v", to, err) t.Errorf("Close(%q) failed: %v", to, err)
} }
err = Symlink(to, from) err = Symlink(to, from)
if err != nil { if err != nil {
t.Fatalf("symlink %q, %q failed: %v", to, from, err) t.Fatalf("Symlink(%q, %q) failed: %v", to, from, err)
} }
defer Remove(from) defer Remove(from)
tostat, err := Lstat(to) tostat, err := Lstat(to)
if err != nil { if err != nil {
t.Fatalf("stat %q failed: %v", to, err) t.Fatalf("Lstat(%q) failed: %v", to, err)
} }
if tostat.Mode()&ModeSymlink != 0 { if tostat.Mode()&ModeSymlink != 0 {
t.Fatalf("stat %q claims to have found a symlink", to) t.Fatalf("Lstat(%q).Mode()&ModeSymlink = %v, want 0", to, tostat.Mode()&ModeSymlink)
} }
fromstat, err := Stat(from) fromstat, err := Stat(from)
if err != nil { if err != nil {
t.Fatalf("stat %q failed: %v", from, err) t.Fatalf("Stat(%q) failed: %v", from, err)
} }
if !SameFile(tostat, fromstat) { if !SameFile(tostat, fromstat) {
t.Errorf("symlink %q, %q did not create symlink", to, from) t.Errorf("Symlink(%q, %q) did not create symlink", to, from)
} }
fromstat, err = Lstat(from) fromstat, err = Lstat(from)
if err != nil { if err != nil {
t.Fatalf("lstat %q failed: %v", from, err) t.Fatalf("Lstat(%q) failed: %v", from, err)
} }
if fromstat.Mode()&ModeSymlink == 0 { if fromstat.Mode()&ModeSymlink == 0 {
t.Fatalf("symlink %q, %q did not create symlink", to, from) t.Fatalf("Lstat(%q).Mode()&ModeSymlink = 0, want %v", from, ModeSymlink)
} }
fromstat, err = Stat(from) fromstat, err = Stat(from)
if err != nil { if err != nil {
t.Fatalf("stat %q failed: %v", from, err) t.Fatalf("Stat(%q) failed: %v", from, err)
}
if fromstat.Name() != from {
t.Errorf("Stat(%q).Name() = %q, want %q", from, fromstat.Name(), from)
} }
if fromstat.Mode()&ModeSymlink != 0 { if fromstat.Mode()&ModeSymlink != 0 {
t.Fatalf("stat %q did not follow symlink", from) t.Fatalf("Stat(%q).Mode()&ModeSymlink = %v, want 0", from, fromstat.Mode()&ModeSymlink)
} }
s, err := Readlink(from) s, err := Readlink(from)
if err != nil { if err != nil {
t.Fatalf("readlink %q failed: %v", from, err) t.Fatalf("Readlink(%q) failed: %v", from, err)
} }
if s != to { if s != to {
t.Fatalf("after symlink %q != %q", s, to) t.Fatalf("Readlink(%q) = %q, want %q", from, s, to)
} }
file, err = Open(from) file, err = Open(from)
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", from, err) t.Fatalf("Open(%q) failed: %v", from, err)
} }
file.Close() file.Close()
} }
......
...@@ -105,6 +105,10 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) { ...@@ -105,6 +105,10 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
fi, err := os.Stat(dir)
if err != nil {
t.Fatal(err)
}
err = ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("abc"), 0644) err = ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("abc"), 0644)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -113,7 +117,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) { ...@@ -113,7 +117,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
link := filepath.Join(tmpdir, test.name+"_link") link := filepath.Join(tmpdir, test.name+"_link")
err := test.mklink(link, dir) err := test.mklink(link, dir)
if err != nil { if err != nil {
t.Errorf("creating link for %s test failed: %v", test.name, err) t.Errorf("creating link for %q test failed: %v", test.name, err)
continue continue
} }
...@@ -132,15 +136,21 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) { ...@@ -132,15 +136,21 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
continue continue
} }
fi, err := os.Stat(link) fi1, err := os.Stat(link)
if err != nil { if err != nil {
t.Errorf("failed to stat link %v: %v", link, err) t.Errorf("failed to stat link %v: %v", link, err)
continue continue
} }
expected := filepath.Base(dir) if !fi1.IsDir() {
got := fi.Name() t.Errorf("%q should be a directory", link)
if !fi.IsDir() || expected != got { continue
t.Errorf("link should point to %v but points to %v instead", expected, got) }
if fi1.Name() != filepath.Base(link) {
t.Errorf("Stat(%q).Name() = %q, want %q", link, fi1.Name(), filepath.Base(link))
continue
}
if !os.SameFile(fi, fi1) {
t.Errorf("%q should point to %q", link, dir)
continue continue
} }
} }
......
...@@ -63,25 +63,27 @@ func (file *File) Stat() (FileInfo, error) { ...@@ -63,25 +63,27 @@ func (file *File) Stat() (FileInfo, error) {
func Stat(name string) (FileInfo, error) { func Stat(name string) (FileInfo, error) {
var fi FileInfo var fi FileInfo
var err error var err error
link := name
for i := 0; i < 255; i++ { for i := 0; i < 255; i++ {
fi, err = Lstat(name) fi, err = Lstat(link)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if fi.Mode()&ModeSymlink == 0 { if fi.Mode()&ModeSymlink == 0 {
fi.(*fileStat).name = basename(name)
return fi, nil return fi, nil
} }
newname, err := Readlink(name) newlink, err := Readlink(link)
if err != nil { if err != nil {
return nil, err return nil, err
} }
switch { switch {
case isAbs(newname): case isAbs(newlink):
name = newname link = newlink
case len(newname) > 0 && IsPathSeparator(newname[0]): case len(newlink) > 0 && IsPathSeparator(newlink[0]):
name = volumeName(name) + newname link = volumeName(link) + newlink
default: default:
name = dirname(name) + `\` + newname link = dirname(link) + `\` + newlink
} }
} }
return nil, &PathError{"Stat", name, syscall.ELOOP} return nil, &PathError{"Stat", name, syscall.ELOOP}
......
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