]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: ensure Mkdir(path) on Plan 9 fails if path exists
authorRichard Miller <miller.research@gmail.com>
Mon, 19 Feb 2018 12:34:53 +0000 (12:34 +0000)
committerDavid du Colombier <0intro@gmail.com>
Tue, 20 Feb 2018 13:21:12 +0000 (13:21 +0000)
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>
src/os/stat_plan9.go
src/syscall/syscall_plan9.go

index 8057fd4a02de697e9467db396bfac42f455992e4..15999c001c7f3fcf097588920ff86b0126c0a68a 100644 (file)
@@ -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}
                }
 
index 12b61ee164a53786593366841485d046ff6904d7..7595126faa7b4a7f4b262ad0250fa626d1139c64 100644 (file)
@@ -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 {