diff --git a/src/os/file.go b/src/os/file.go index c13babe5f7fad8ee418dc1783fc8e7e7413aea4e..46ae1a46aa56b68afe8cf9dd9a3e9e52d63f2134 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -228,6 +228,9 @@ func (f *File) WriteString(s string) (n int, err error) { // bits (before umask). // If there is an error, it will be of type *PathError. 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)) if e != nil { @@ -560,3 +563,21 @@ func (f *File) SyscallConn() (syscall.RawConn, error) { } 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 +} diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go index 326670cc9da2d8131a1c666b05456c0d92f84cd4..2693904e5618f6ee9efafc3da89694768dfefbb2 100644 --- a/src/os/os_windows_test.go +++ b/src/os/os_windows_test.go @@ -1168,3 +1168,19 @@ func TestWindowsReadlink(t *testing.T) { mklink(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) + } +} \ No newline at end of file diff --git a/src/os/stat_windows.go b/src/os/stat_windows.go index fd22ef21ab312b79ed675fa54321d09cdb7c55b8..3e0e0a59ede90e3f002a9b877b535da7cc4da25f 100644 --- a/src/os/stat_windows.go +++ b/src/os/stat_windows.go @@ -10,24 +10,6 @@ import ( "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. // If there is an error, it will be of type *PathError. 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 return Stat(file.dirinfo.path) } - if isNulName(file.name) { + if isWindowsNulName(file.name) { return &devNullStat, nil } @@ -65,7 +47,7 @@ func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) { if len(name) == 0 { return nil, &PathError{funcname, name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)} } - if isNulName(name) { + if isWindowsNulName(name) { return &devNullStat, nil } namep, err := syscall.UTF16PtrFromString(fixLongPath(name))