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) {
Remove(from) // Just in case.
file, err := Create(to)
if err != nil {
t.Fatalf("open %q failed: %v", to, err)
t.Fatalf("Create(%q) failed: %v", to, err)
}
defer Remove(to)
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)
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)
tostat, err := Lstat(to)
if err != nil {
t.Fatalf("stat %q failed: %v", to, err)
t.Fatalf("Lstat(%q) failed: %v", to, err)
}
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)
if err != nil {
t.Fatalf("stat %q failed: %v", from, err)
t.Fatalf("Stat(%q) failed: %v", from, err)
}
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)
if err != nil {
t.Fatalf("lstat %q failed: %v", from, err)
t.Fatalf("Lstat(%q) failed: %v", from, err)
}
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)
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 {
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)
if err != nil {
t.Fatalf("readlink %q failed: %v", from, err)
t.Fatalf("Readlink(%q) failed: %v", from, err)
}
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)
if err != nil {
t.Fatalf("open %q failed: %v", from, err)
t.Fatalf("Open(%q) failed: %v", from, err)
}
file.Close()
}
......
......@@ -105,6 +105,10 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
if err != nil {
t.Fatal(err)
}
fi, err := os.Stat(dir)
if err != nil {
t.Fatal(err)
}
err = ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("abc"), 0644)
if err != nil {
t.Fatal(err)
......@@ -113,7 +117,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
link := filepath.Join(tmpdir, test.name+"_link")
err := test.mklink(link, dir)
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
}
......@@ -132,15 +136,21 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
continue
}
fi, err := os.Stat(link)
fi1, err := os.Stat(link)
if err != nil {
t.Errorf("failed to stat link %v: %v", link, err)
continue
}
expected := filepath.Base(dir)
got := fi.Name()
if !fi.IsDir() || expected != got {
t.Errorf("link should point to %v but points to %v instead", expected, got)
if !fi1.IsDir() {
t.Errorf("%q should be a directory", link)
continue
}
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
}
}
......
......@@ -63,25 +63,27 @@ func (file *File) Stat() (FileInfo, error) {
func Stat(name string) (FileInfo, error) {
var fi FileInfo
var err error
link := name
for i := 0; i < 255; i++ {
fi, err = Lstat(name)
fi, err = Lstat(link)
if err != nil {
return nil, err
}
if fi.Mode()&ModeSymlink == 0 {
fi.(*fileStat).name = basename(name)
return fi, nil
}
newname, err := Readlink(name)
newlink, err := Readlink(link)
if err != nil {
return nil, err
}
switch {
case isAbs(newname):
name = newname
case len(newname) > 0 && IsPathSeparator(newname[0]):
name = volumeName(name) + newname
case isAbs(newlink):
link = newlink
case len(newlink) > 0 && IsPathSeparator(newlink[0]):
link = volumeName(link) + newlink
default:
name = dirname(name) + `\` + newname
link = dirname(link) + `\` + newlink
}
}
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