aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Miller <miller.research@gmail.com>2018-02-19 12:34:53 +0000
committerDavid du Colombier <0intro@gmail.com>2018-02-20 13:21:12 +0000
commita156fc08b7fd289bfc9979c77445f9e4741a7dfd (patch)
treed44a8ea6f9fe3c86fc89dd608b90595ed34dbf92
parent9b7f221a3af2ee8495129621a5012647ffe15eb1 (diff)
downloadgo-a156fc08b7fd289bfc9979c77445f9e4741a7dfd.tar.xz
syscall: ensure Mkdir(path) on Plan 9 fails if path exists
On Plan 9, the underlying create() syscall with DMDIR flag, which is used to implement Mkdir, will fail silently if the path exists and is not a directory. Work around this by checking for existence first and rejecting Mkdir with error EEXIST if the path is found. Fixes #23918 Change-Id: I439115662307923c9f498d3e7b1f32c6d205e1ad Reviewed-on: https://go-review.googlesource.com/94777 Reviewed-by: David du Colombier <0intro@gmail.com>
-rw-r--r--src/os/stat_plan9.go6
-rw-r--r--src/syscall/syscall_plan9.go15
2 files changed, 18 insertions, 3 deletions
diff --git a/src/os/stat_plan9.go b/src/os/stat_plan9.go
index 8057fd4a02..15999c001c 100644
--- a/src/os/stat_plan9.go
+++ b/src/os/stat_plan9.go
@@ -9,7 +9,7 @@ import (
"time"
)
-const _BIT16SZ = 2
+const bitSize16 = 2
func fileInfoFromStat(d *syscall.Dir) FileInfo {
fs := &fileStat{
@@ -46,7 +46,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) {
size := syscall.STATFIXLEN + 16*4
for i := 0; i < 2; i++ {
- buf := make([]byte, _BIT16SZ+size)
+ buf := make([]byte, bitSize16+size)
var n int
switch a := arg.(type) {
@@ -60,7 +60,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) {
panic("phase error in dirstat")
}
- if n < _BIT16SZ {
+ if n < bitSize16 {
return nil, &PathError{"stat", name, err}
}
diff --git a/src/syscall/syscall_plan9.go b/src/syscall/syscall_plan9.go
index 12b61ee164..7595126faa 100644
--- a/src/syscall/syscall_plan9.go
+++ b/src/syscall/syscall_plan9.go
@@ -14,6 +14,7 @@ package syscall
import "unsafe"
const ImplementsGetwd = true
+const bitSize16 = 2
// ErrorString implements Error's String method by returning itself.
type ErrorString string
@@ -164,6 +165,20 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
}
func Mkdir(path string, mode uint32) (err error) {
+ // If path exists and is not a directory, Create will fail silently.
+ // Work around this by rejecting Mkdir if path exists.
+ statbuf := make([]byte, bitSize16)
+ // Remove any trailing slashes from path, otherwise the Stat will
+ // fail with ENOTDIR.
+ n := len(path)
+ for n > 1 && path[n-1] == '/' {
+ n--
+ }
+ _, err = Stat(path[0:n], statbuf)
+ if err == nil {
+ return EEXIST
+ }
+
fd, err := Create(path, O_RDONLY, DMDIR|mode)
if fd != -1 {