if err != nil {
return InvalidHandle, err
}
+ accessFlags := flag & (O_RDONLY | O_WRONLY | O_RDWR)
var access uint32
- switch flag & (O_RDONLY | O_WRONLY | O_RDWR) {
+ switch accessFlags {
case O_RDONLY:
access = GENERIC_READ
case O_WRONLY:
if perm&S_IWRITE == 0 {
attrs = FILE_ATTRIBUTE_READONLY
}
- if flag&O_WRONLY == 0 && flag&O_RDWR == 0 {
- // We might be opening or creating a directory.
- // CreateFile requires FILE_FLAG_BACKUP_SEMANTICS
+ switch accessFlags {
+ case O_WRONLY, O_RDWR:
+ // Unix doesn't allow opening a directory with O_WRONLY
+ // or O_RDWR, so we don't set the flag in that case,
+ // which will make CreateFile fail with ERROR_ACCESS_DENIED.
+ // We will map that to EISDIR if the file is a directory.
+ default:
+ // We might be opening a directory for reading,
+ // and CreateFile requires FILE_FLAG_BACKUP_SEMANTICS
// to work with directories.
attrs |= FILE_FLAG_BACKUP_SEMANTICS
}
}
h, err := createFile(namep, access, sharemode, sa, createmode, attrs, 0)
if h == InvalidHandle {
- if err == ERROR_ACCESS_DENIED && (flag&O_WRONLY != 0 || flag&O_RDWR != 0) {
+ if err == ERROR_ACCESS_DENIED && (attrs&FILE_FLAG_BACKUP_SEMANTICS == 0) {
// We should return EISDIR when we are trying to open a directory with write access.
fa, e1 := GetFileAttributes(namep)
if e1 == nil && fa&FILE_ATTRIBUTE_DIRECTORY != 0 {
{dir, syscall.O_RDONLY | syscall.O_CREAT, nil},
{file, syscall.O_APPEND | syscall.O_WRONLY | os.O_CREATE, nil},
{file, syscall.O_APPEND | syscall.O_WRONLY | os.O_CREATE | os.O_TRUNC, nil},
+ {file, syscall.O_WRONLY | syscall.O_RDWR, nil},
+ {dir, syscall.O_WRONLY | syscall.O_RDWR, nil},
{dir, syscall.O_RDONLY | syscall.O_TRUNC, syscall.ERROR_ACCESS_DENIED},
- {dir, syscall.O_WRONLY | syscall.O_RDWR, syscall.EISDIR},
{dir, syscall.O_WRONLY, syscall.EISDIR},
{dir, syscall.O_RDWR, syscall.EISDIR},
}