diff options
| author | qmuntal <quimmuntal@gmail.com> | 2025-11-26 12:11:50 +0100 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-11-26 11:56:54 -0800 |
| commit | b194f5d24a71e34f147c90e4351d80ac75be55de (patch) | |
| tree | a69e72966e451d77002282b19adfaa20210a9b83 /src/internal | |
| parent | e0a4dffb0c0eff51bb5b170d4ae0492a43de153d (diff) | |
| download | go-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.go | 49 | ||||
| -rw-r--r-- | src/internal/syscall/windows/types_windows.go | 15 |
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 |
