]> Cypherpunks repositories - gostls13.git/commitdiff
os: handle relative symlinks correctly in Stat on windows
authorHiroshi Ioka <hirochachacha@gmail.com>
Fri, 7 Apr 2017 11:32:46 +0000 (20:32 +0900)
committerAlex Brainman <alex.brainman@gmail.com>
Mon, 10 Apr 2017 05:13:18 +0000 (05:13 +0000)
Walk relative symlinks in windows os.Stat from
symlink path instead of from current directory.

Fixes #19870

Change-Id: I0a27473d11485f073084b1f19b30c5b3a2fbc0f7
Reviewed-on: https://go-review.googlesource.com/39932
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/os/os_test.go
src/os/stat_windows.go

index a88ba548212677c4acfd04339639d7901500d865..ee9e0cf767355bb914704320372640711a5863cc 100644 (file)
@@ -1705,6 +1705,43 @@ func TestStatStdin(t *testing.T) {
        }
 }
 
+func TestStatRelativeSymlink(t *testing.T) {
+       testenv.MustHaveSymlink(t)
+
+       tmpdir, err := ioutil.TempDir("", "TestStatRelativeSymlink")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer RemoveAll(tmpdir)
+
+       target := filepath.Join(tmpdir, "target")
+       f, err := Create(target)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer f.Close()
+
+       st, err := f.Stat()
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       link := filepath.Join(tmpdir, "link")
+       err = Symlink(filepath.Base(target), link)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       st1, err := Stat(link)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       if !SameFile(st, st1) {
+               t.Error("Stat doesn't follow relative symlink")
+       }
+}
+
 func TestReadAtEOF(t *testing.T) {
        f := newFile("TestReadAtEOF", t)
        defer Remove(f.Name())
index 0b8132f5c86c93d1ea5b8d32ee503794bcbe1a8b..fe0ca8d1b257affeef90b33d060da3c14e58d0b3 100644 (file)
@@ -71,10 +71,15 @@ func Stat(name string) (FileInfo, error) {
                if fi.Mode()&ModeSymlink == 0 {
                        return fi, nil
                }
-               name, err = Readlink(name)
+               newname, err := Readlink(name)
                if err != nil {
                        return fi, err
                }
+               if isAbs(newname) {
+                       name = newname
+               } else {
+                       name = dirname(name) + `\` + newname
+               }
        }
        return nil, &PathError{"Stat", name, syscall.ELOOP}
 }