1
0
mirror of https://github.com/golang/go synced 2024-11-17 04:24:47 -07:00

os: return an error when the argument of Mkdir on Windows is os.DevNull

Test added.

Fixes #24556

Change-Id: I4d1cd4513142edeea1a983fbfde46c2fccecab2a
Reviewed-on: https://go-review.googlesource.com/c/go/+/186139
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
Constantin Konstantinidis 2019-07-15 06:32:40 +02:00 committed by Alex Brainman
parent cb325fed43
commit 5cf5a6fc5e
3 changed files with 39 additions and 20 deletions

View File

@ -228,6 +228,9 @@ func (f *File) WriteString(s string) (n int, err error) {
// bits (before umask). // bits (before umask).
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func Mkdir(name string, perm FileMode) error { func Mkdir(name string, perm FileMode) error {
if runtime.GOOS == "windows" && isWindowsNulName(name) {
return &PathError{"mkdir", name, syscall.ENOTDIR}
}
e := syscall.Mkdir(fixLongPath(name), syscallMode(perm)) e := syscall.Mkdir(fixLongPath(name), syscallMode(perm))
if e != nil { if e != nil {
@ -560,3 +563,21 @@ func (f *File) SyscallConn() (syscall.RawConn, error) {
} }
return newRawConn(f) return newRawConn(f)
} }
// isWindowsNulName reports whether name is os.DevNull ('NUL') on Windows.
// True is returned if name is 'NUL' whatever the case.
func isWindowsNulName(name string) bool {
if len(name) != 3 {
return false
}
if name[0] != 'n' && name[0] != 'N' {
return false
}
if name[1] != 'u' && name[1] != 'U' {
return false
}
if name[2] != 'l' && name[2] != 'L' {
return false
}
return true
}

View File

@ -1168,3 +1168,19 @@ func TestWindowsReadlink(t *testing.T) {
mklink(t, "relfilelink", "file") mklink(t, "relfilelink", "file")
testReadlink(t, "relfilelink", "file") testReadlink(t, "relfilelink", "file")
} }
// os.Mkdir(os.DevNull) fails.
func TestMkdirDevNull(t *testing.T) {
err := os.Mkdir(os.DevNull, 777)
oserr, ok := err.(*os.PathError)
if !ok {
t.Fatalf("error (%T) is not *os.PathError", err)
}
errno, ok := oserr.Err.(syscall.Errno)
if !ok {
t.Fatalf("error (%T) is not syscall.Errno", oserr)
}
if errno != syscall.ENOTDIR {
t.Fatalf("error %d is not syscall.ENOTDIR", errno)
}
}

View File

@ -10,24 +10,6 @@ import (
"unsafe" "unsafe"
) )
// isNulName reports whether name is NUL file name.
// For example, it returns true for both "NUL" and "nul".
func isNulName(name string) bool {
if len(name) != 3 {
return false
}
if name[0] != 'n' && name[0] != 'N' {
return false
}
if name[1] != 'u' && name[1] != 'U' {
return false
}
if name[2] != 'l' && name[2] != 'L' {
return false
}
return true
}
// Stat returns the FileInfo structure describing file. // Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (file *File) Stat() (FileInfo, error) { func (file *File) Stat() (FileInfo, error) {
@ -39,7 +21,7 @@ func (file *File) Stat() (FileInfo, error) {
// I don't know any better way to do that for directory // I don't know any better way to do that for directory
return Stat(file.dirinfo.path) return Stat(file.dirinfo.path)
} }
if isNulName(file.name) { if isWindowsNulName(file.name) {
return &devNullStat, nil return &devNullStat, nil
} }
@ -65,7 +47,7 @@ func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) {
if len(name) == 0 { if len(name) == 0 {
return nil, &PathError{funcname, name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)} return nil, &PathError{funcname, name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
} }
if isNulName(name) { if isWindowsNulName(name) {
return &devNullStat, nil return &devNullStat, nil
} }
namep, err := syscall.UTF16PtrFromString(fixLongPath(name)) namep, err := syscall.UTF16PtrFromString(fixLongPath(name))