aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
authorqmuntal <quimmuntal@gmail.com>2025-11-26 12:11:50 +0100
committerGopher Robot <gobot@golang.org>2025-11-26 11:56:54 -0800
commitb194f5d24a71e34f147c90e4351d80ac75be55de (patch)
treea69e72966e451d77002282b19adfaa20210a9b83 /src/internal
parente0a4dffb0c0eff51bb5b170d4ae0492a43de153d (diff)
downloadgo-b194f5d24a71e34f147c90e4351d80ac75be55de.tar.xz
os,internal/syscall/windows: support O_* flags in Root.OpenFile
These file flags are supported by os.OpenFile since CL 699415. Closes #73676 Change-Id: Ib37102a565f538d394d2a94bd605d6c6004f3028 Reviewed-on: https://go-review.googlesource.com/c/go/+/724621 Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Damien Neil <dneil@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/syscall/windows/at_windows.go49
-rw-r--r--src/internal/syscall/windows/types_windows.go15
2 files changed, 54 insertions, 10 deletions
diff --git a/src/internal/syscall/windows/at_windows.go b/src/internal/syscall/windows/at_windows.go
index b7ca8433c2..de733c523c 100644
--- a/src/internal/syscall/windows/at_windows.go
+++ b/src/internal/syscall/windows/at_windows.go
@@ -5,6 +5,7 @@
package windows
import (
+ "internal/oserror"
"runtime"
"structs"
"syscall"
@@ -26,7 +27,6 @@ const (
// to avoid overlap.
const (
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
)
@@ -36,24 +36,54 @@ func Openat(dirfd syscall.Handle, name string, flag uint64, perm uint32) (_ sysc
}
var access, options uint32
+ // Map Win32 file flags to NT create options.
+ fileFlags := uint32(flag) & FileFlagsMask
+ if fileFlags&^ValidFileFlagsMask != 0 {
+ return syscall.InvalidHandle, oserror.ErrInvalid
+ }
+ if fileFlags&O_FILE_FLAG_OVERLAPPED == 0 {
+ options |= FILE_SYNCHRONOUS_IO_NONALERT
+ }
+ if fileFlags&O_FILE_FLAG_DELETE_ON_CLOSE != 0 {
+ access |= DELETE
+ }
+ setOptionFlag := func(ntFlag, win32Flag uint32) {
+ if fileFlags&win32Flag != 0 {
+ options |= ntFlag
+ }
+ }
+ setOptionFlag(FILE_NO_INTERMEDIATE_BUFFERING, O_FILE_FLAG_NO_BUFFERING)
+ setOptionFlag(FILE_WRITE_THROUGH, O_FILE_FLAG_WRITE_THROUGH)
+ setOptionFlag(FILE_SEQUENTIAL_ONLY, O_FILE_FLAG_SEQUENTIAL_SCAN)
+ setOptionFlag(FILE_RANDOM_ACCESS, O_FILE_FLAG_RANDOM_ACCESS)
+ setOptionFlag(FILE_OPEN_FOR_BACKUP_INTENT, O_FILE_FLAG_BACKUP_SEMANTICS)
+ setOptionFlag(FILE_SESSION_AWARE, O_FILE_FLAG_SESSION_AWARE)
+ setOptionFlag(FILE_DELETE_ON_CLOSE, O_FILE_FLAG_DELETE_ON_CLOSE)
+ setOptionFlag(FILE_OPEN_NO_RECALL, O_FILE_FLAG_OPEN_NO_RECALL)
+ setOptionFlag(FILE_OPEN_REPARSE_POINT, O_FILE_FLAG_OPEN_REPARSE_POINT)
+
switch flag & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) {
case syscall.O_RDONLY:
// FILE_GENERIC_READ includes FILE_LIST_DIRECTORY.
- access = FILE_GENERIC_READ
+ access |= FILE_GENERIC_READ
case syscall.O_WRONLY:
- access = FILE_GENERIC_WRITE
+ access |= FILE_GENERIC_WRITE
options |= FILE_NON_DIRECTORY_FILE
case syscall.O_RDWR:
- access = FILE_GENERIC_READ | FILE_GENERIC_WRITE
+ access |= FILE_GENERIC_READ | FILE_GENERIC_WRITE
options |= FILE_NON_DIRECTORY_FILE
default:
// Stat opens files without requesting read or write permissions,
// but we still need to request SYNCHRONIZE.
- access = SYNCHRONIZE
+ access |= SYNCHRONIZE
}
if flag&syscall.O_CREAT != 0 {
access |= FILE_GENERIC_WRITE
}
+ if fileFlags&O_FILE_FLAG_NO_BUFFERING != 0 {
+ // Disable buffering implies no implicit append access.
+ access &^= FILE_APPEND_DATA
+ }
if flag&syscall.O_APPEND != 0 {
access |= FILE_APPEND_DATA
// Remove FILE_WRITE_DATA access unless O_TRUNC is set,
@@ -82,14 +112,13 @@ func Openat(dirfd syscall.Handle, name string, flag uint64, perm uint32) (_ sysc
if flag&syscall.O_CLOEXEC == 0 {
objAttrs.Attributes |= OBJ_INHERIT
}
+ if fileFlags&O_FILE_FLAG_POSIX_SEMANTICS == 0 {
+ objAttrs.Attributes |= OBJ_CASE_INSENSITIVE
+ }
if err := objAttrs.init(dirfd, name); err != nil {
return syscall.InvalidHandle, err
}
- if flag&O_OPEN_REPARSE != 0 {
- options |= FILE_OPEN_REPARSE_POINT
- }
-
// We don't use FILE_OVERWRITE/FILE_OVERWRITE_IF, because when opening
// a file with FILE_ATTRIBUTE_READONLY these will replace an existing
// file with a new, read-only one.
@@ -121,7 +150,7 @@ func Openat(dirfd syscall.Handle, name string, flag uint64, perm uint32) (_ sysc
fileAttrs,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
disposition,
- FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_FOR_BACKUP_INTENT|options,
+ FILE_OPEN_FOR_BACKUP_INTENT|options,
nil,
0,
)
diff --git a/src/internal/syscall/windows/types_windows.go b/src/internal/syscall/windows/types_windows.go
index 49daf9b31b..568f94624c 100644
--- a/src/internal/syscall/windows/types_windows.go
+++ b/src/internal/syscall/windows/types_windows.go
@@ -210,6 +210,7 @@ const (
FILE_NO_COMPRESSION = 0x00008000
FILE_OPEN_REQUIRING_OPLOCK = 0x00010000
FILE_DISALLOW_EXCLUSIVE = 0x00020000
+ FILE_SESSION_AWARE = 0x00040000
FILE_RESERVE_OPFILTER = 0x00100000
FILE_OPEN_REPARSE_POINT = 0x00200000
FILE_OPEN_NO_RECALL = 0x00400000
@@ -286,3 +287,17 @@ const VER_NT_WORKSTATION = 0x0000001
type MemoryBasicInformation = windows.MemoryBasicInformation
type Context = windows.Context
+
+const FileFlagsMask = 0xFFF00000
+
+const ValidFileFlagsMask = O_FILE_FLAG_OPEN_REPARSE_POINT |
+ O_FILE_FLAG_BACKUP_SEMANTICS |
+ O_FILE_FLAG_OVERLAPPED |
+ O_FILE_FLAG_OPEN_NO_RECALL |
+ O_FILE_FLAG_SESSION_AWARE |
+ O_FILE_FLAG_POSIX_SEMANTICS |
+ O_FILE_FLAG_DELETE_ON_CLOSE |
+ O_FILE_FLAG_SEQUENTIAL_SCAN |
+ O_FILE_FLAG_NO_BUFFERING |
+ O_FILE_FLAG_RANDOM_ACCESS |
+ O_FILE_FLAG_WRITE_THROUGH