Commit a156fc08 authored by Richard Miller's avatar Richard Miller Committed by David du Colombier

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/94777Reviewed-by: default avatarDavid du Colombier <0intro@gmail.com>
parent 9b7f221a
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"time" "time"
) )
const _BIT16SZ = 2 const bitSize16 = 2
func fileInfoFromStat(d *syscall.Dir) FileInfo { func fileInfoFromStat(d *syscall.Dir) FileInfo {
fs := &fileStat{ fs := &fileStat{
...@@ -46,7 +46,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) { ...@@ -46,7 +46,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) {
size := syscall.STATFIXLEN + 16*4 size := syscall.STATFIXLEN + 16*4
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
buf := make([]byte, _BIT16SZ+size) buf := make([]byte, bitSize16+size)
var n int var n int
switch a := arg.(type) { switch a := arg.(type) {
...@@ -60,7 +60,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) { ...@@ -60,7 +60,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) {
panic("phase error in dirstat") panic("phase error in dirstat")
} }
if n < _BIT16SZ { if n < bitSize16 {
return nil, &PathError{"stat", name, err} return nil, &PathError{"stat", name, err}
} }
......
...@@ -14,6 +14,7 @@ package syscall ...@@ -14,6 +14,7 @@ package syscall
import "unsafe" import "unsafe"
const ImplementsGetwd = true const ImplementsGetwd = true
const bitSize16 = 2
// ErrorString implements Error's String method by returning itself. // ErrorString implements Error's String method by returning itself.
type ErrorString string type ErrorString string
...@@ -164,6 +165,20 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { ...@@ -164,6 +165,20 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
} }
func Mkdir(path string, mode uint32) (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) fd, err := Create(path, O_RDONLY, DMDIR|mode)
if fd != -1 { if fd != -1 {
......
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