"unsafe"
)
+// Openat flags supported by syscall.Open.
+const (
+ O_DIRECTORY = 0x04000 // target must be a directory
+)
+
// Openat flags not supported by syscall.Open.
//
// These are invented values, use values in the 33-63 bit range
// the set of invented O_ values in syscall/types_windows.go
// to avoid overlap.
const (
- O_DIRECTORY = 0x100000000 // target must be a directory
O_NOFOLLOW_ANY = 0x200000000 // disallow symlinks anywhere in the path
O_OPEN_REPARSE = 0x400000000 // FILE_OPEN_REPARSE_POINT, used by Lstat
O_WRITE_ATTRS = 0x800000000 // FILE_WRITE_ATTRIBUTES, used by Chmod
}
func openDirNolog(name string) (*File, error) {
- return openFileNolog(name, O_RDONLY, 0)
+ return openFileNolog(name, O_RDONLY|windows.O_DIRECTORY, 0)
}
func (file *file) close() error {
import (
"bytes"
+ "errors"
. "os"
"path/filepath"
"runtime"
+ "syscall"
"testing"
)
t.Parallel()
dirname := "rumpelstilzchen"
- _, err := ReadDir(dirname)
- if err == nil {
+ if _, err := ReadDir(dirname); err == nil {
t.Fatalf("ReadDir %s: error expected, none found", dirname)
}
+ filename := filepath.Join(t.TempDir(), "foo")
+ f, err := Create(filename)
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
+ if list, err := ReadDir(filename); list != nil || !errors.Is(err, syscall.ENOTDIR) {
+ t.Fatalf("ReadDir %s: (nil, ENOTDIR) expected, got (%v, %v)", filename, list, err)
+ }
+
dirname = "."
list, err := ReadDir(dirname)
if err != nil {
}
return h, err
}
+ if flag&o_DIRECTORY != 0 {
+ // Check if the file is a directory, else return ENOTDIR.
+ var fi ByHandleFileInformation
+ if err := GetFileInformationByHandle(h, &fi); err != nil {
+ CloseHandle(h)
+ return InvalidHandle, err
+ }
+ if fi.FileAttributes&FILE_ATTRIBUTE_DIRECTORY == 0 {
+ CloseHandle(h)
+ return InvalidHandle, ENOTDIR
+ }
+ }
// Ignore O_TRUNC if the file has just been created.
if flag&O_TRUNC == O_TRUNC &&
(createmode == OPEN_EXISTING || (createmode == OPEN_ALWAYS && err == ERROR_ALREADY_EXISTS)) {
O_APPEND = 0x00400
O_SYNC = 0x01000
O_ASYNC = 0x02000
+ o_DIRECTORY = 0x04000
O_CLOEXEC = 0x80000
- o_DIRECTORY = 0x100000000 // used by internal/syscall/windows
o_NOFOLLOW_ANY = 0x200000000 // used by internal/syscall/windows
o_OPEN_REPARSE = 0x400000000 // used by internal/syscall/windows
o_WRITE_ATTRS = 0x800000000 // used by internal/syscall/windows