aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/path
diff options
context:
space:
mode:
authorMichael Fraenkel <michael.fraenkel@gmail.com>2014-07-17 17:02:46 +1000
committerAlex Brainman <alex.brainman@gmail.com>2014-07-17 17:02:46 +1000
commitcf521ce64f50c4f300294d6b649f34eca87bb8a3 (patch)
treea7f4a5612448eae5076254bd2c2193dc87727b34 /src/pkg/path
parent47fd6bd9b62c8c028f03fc9407e3ce261fb8ed6d (diff)
downloadgo-cf521ce64f50c4f300294d6b649f34eca87bb8a3.tar.xz
os: Implement symlink support for Windows
Fixes #5750. https://code.google.com/p/go/issues/detail?id=5750 os: Separate windows from posix. Implement windows support. path/filepath: Use the same implementation as other platforms syscall: Add/rework new APIs for Windows LGTM=alex.brainman R=golang-codereviews, alex.brainman, gobot, rsc, minux CC=golang-codereviews https://golang.org/cl/86160044
Diffstat (limited to 'src/pkg/path')
-rw-r--r--src/pkg/path/filepath/match_test.go7
-rw-r--r--src/pkg/path/filepath/path_test.go12
-rw-r--r--src/pkg/path/filepath/path_windows_test.go20
-rw-r--r--src/pkg/path/filepath/symlink.go19
-rw-r--r--src/pkg/path/filepath/symlink_unix.go7
-rw-r--r--src/pkg/path/filepath/symlink_windows.go5
6 files changed, 57 insertions, 13 deletions
diff --git a/src/pkg/path/filepath/match_test.go b/src/pkg/path/filepath/match_test.go
index 382692eaa4..20ec5aa2a1 100644
--- a/src/pkg/path/filepath/match_test.go
+++ b/src/pkg/path/filepath/match_test.go
@@ -167,8 +167,13 @@ var globSymlinkTests = []struct {
func TestGlobSymlink(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "nacl", "plan9":
t.Skipf("skipping on %s", runtime.GOOS)
+ case "windows":
+ if !supportsSymlinks {
+ t.Skipf("skipping on %s", runtime.GOOS)
+ }
+
}
tmpDir, err := ioutil.TempDir("", "globsymlink")
diff --git a/src/pkg/path/filepath/path_test.go b/src/pkg/path/filepath/path_test.go
index 819bd217cc..17b53bdf92 100644
--- a/src/pkg/path/filepath/path_test.go
+++ b/src/pkg/path/filepath/path_test.go
@@ -15,6 +15,8 @@ import (
"testing"
)
+var supportsSymlinks = true
+
type PathTest struct {
path, result string
}
@@ -716,7 +718,7 @@ func TestEvalSymlinks(t *testing.T) {
if d.dest == "" {
err = os.Mkdir(path, 0755)
} else {
- if runtime.GOOS != "windows" {
+ if supportsSymlinks {
err = os.Symlink(d.dest, path)
}
}
@@ -726,7 +728,9 @@ func TestEvalSymlinks(t *testing.T) {
}
var tests []EvalSymlinksTest
- if runtime.GOOS == "windows" {
+ if supportsSymlinks {
+ tests = EvalSymlinksTests
+ } else {
for _, d := range EvalSymlinksTests {
if d.path == d.dest {
// will test only real files and directories
@@ -739,15 +743,13 @@ func TestEvalSymlinks(t *testing.T) {
tests = append(tests, d2)
}
}
- } else {
- tests = EvalSymlinksTests
}
// Evaluate the symlink farm.
for _, d := range tests {
path := simpleJoin(tmpDir, d.path)
dest := simpleJoin(tmpDir, d.dest)
- if filepath.IsAbs(d.dest) {
+ if filepath.IsAbs(d.dest) || os.IsPathSeparator(d.dest[0]) {
dest = d.dest
}
if p, err := filepath.EvalSymlinks(path); err != nil {
diff --git a/src/pkg/path/filepath/path_windows_test.go b/src/pkg/path/filepath/path_windows_test.go
index 8a9be8e896..100cf30a45 100644
--- a/src/pkg/path/filepath/path_windows_test.go
+++ b/src/pkg/path/filepath/path_windows_test.go
@@ -10,9 +10,29 @@ import (
"os/exec"
"path/filepath"
"reflect"
+ "syscall"
"testing"
)
+func init() {
+ tmpdir, err := ioutil.TempDir("", "symtest")
+ if err != nil {
+ panic("failed to create temp directory: " + err.Error())
+ }
+ defer os.RemoveAll(tmpdir)
+
+ err = os.Symlink("target", filepath.Join(tmpdir, "symlink"))
+ if err == nil {
+ return
+ }
+
+ err = err.(*os.LinkError).Err
+ switch err {
+ case syscall.EWINDOWS, syscall.ERROR_PRIVILEGE_NOT_HELD:
+ supportsSymlinks = false
+ }
+}
+
func TestWinSplitListTestsAreValid(t *testing.T) {
comspec := os.Getenv("ComSpec")
if comspec == "" {
diff --git a/src/pkg/path/filepath/symlink.go b/src/pkg/path/filepath/symlink.go
index 307dd0f8fe..df0a9e0c2b 100644
--- a/src/pkg/path/filepath/symlink.go
+++ b/src/pkg/path/filepath/symlink.go
@@ -2,18 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !windows
-
package filepath
import (
"bytes"
"errors"
"os"
- "strings"
)
-func evalSymlinks(path string) (string, error) {
+const utf8RuneSelf = 0x80
+
+func walkSymlinks(path string) (string, error) {
const maxIter = 255
originalPath := path
// consume path by taking each frontmost path element,
@@ -25,7 +24,13 @@ func evalSymlinks(path string) (string, error) {
}
// find next path component, p
- i := strings.IndexRune(path, Separator)
+ var i = -1
+ for j, c := range path {
+ if c < utf8RuneSelf && os.IsPathSeparator(uint8(c)) {
+ i = j
+ break
+ }
+ }
var p string
if i == -1 {
p, path = path, ""
@@ -47,7 +52,7 @@ func evalSymlinks(path string) (string, error) {
}
if fi.Mode()&os.ModeSymlink == 0 {
b.WriteString(p)
- if path != "" {
+ if path != "" || (b.Len() == 2 && len(p) == 2 && p[1] == ':') {
b.WriteRune(Separator)
}
continue
@@ -58,7 +63,7 @@ func evalSymlinks(path string) (string, error) {
if err != nil {
return "", err
}
- if IsAbs(dest) {
+ if IsAbs(dest) || os.IsPathSeparator(dest[0]) {
b.Reset()
}
path = dest + string(Separator) + path
diff --git a/src/pkg/path/filepath/symlink_unix.go b/src/pkg/path/filepath/symlink_unix.go
new file mode 100644
index 0000000000..d20e63a987
--- /dev/null
+++ b/src/pkg/path/filepath/symlink_unix.go
@@ -0,0 +1,7 @@
+// +build !windows
+
+package filepath
+
+func evalSymlinks(path string) (string, error) {
+ return walkSymlinks(path)
+}
diff --git a/src/pkg/path/filepath/symlink_windows.go b/src/pkg/path/filepath/symlink_windows.go
index 9adc8a48af..327c2c89a3 100644
--- a/src/pkg/path/filepath/symlink_windows.go
+++ b/src/pkg/path/filepath/symlink_windows.go
@@ -50,6 +50,11 @@ func toLong(path string) (string, error) {
}
func evalSymlinks(path string) (string, error) {
+ path, err := walkSymlinks(path)
+ if err != nil {
+ return "", err
+ }
+
p, err := toShort(path)
if err != nil {
return "", err