Skip to content

Commit 6853d89

Browse files
committed
syscall: keep write access when O_TRUNC is used on Windows
CL 618836 introduces a regression where O_APPEND and O_TRUNC could not be used together on Windows. This CL fixes the issue by keeping the write access when O_TRUNC is used , which is required when overwriting data (as per the file access rights docs: https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants). Fixes #69902. Change-Id: I77ec60ca6929124dd4490bdad6c3280c4db3efcb Reviewed-on: https://go-review.googlesource.com/c/go/+/620575 Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Alex Brainman <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Damien Neil <[email protected]>
1 parent e45c125 commit 6853d89

File tree

2 files changed

+25
-11
lines changed

2 files changed

+25
-11
lines changed

src/syscall/syscall_windows.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,12 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
362362
access |= GENERIC_WRITE
363363
}
364364
if flag&O_APPEND != 0 {
365-
access &^= GENERIC_WRITE
366365
access |= FILE_APPEND_DATA
366+
// Remove GENERIC_WRITE access unless O_TRUNC is set,
367+
// in which case we need it to truncate the file.
368+
if flag&O_TRUNC == 0 {
369+
access &^= GENERIC_WRITE
370+
}
367371
}
368372
sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
369373
var sa *SecurityAttributes

src/syscall/syscall_windows_test.go

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,39 @@ import (
1515
"testing"
1616
)
1717

18-
func TestOpen_Dir(t *testing.T) {
18+
func TestOpen(t *testing.T) {
1919
t.Parallel()
2020

2121
dir := t.TempDir()
22+
file := filepath.Join(dir, "a")
23+
f, err := os.Create(file)
24+
if err != nil {
25+
t.Fatal(err)
26+
}
27+
f.Close()
28+
2229
tests := []struct {
30+
path string
2331
flag int
2432
err error
2533
}{
26-
{syscall.O_RDONLY, nil},
27-
{syscall.O_CREAT, nil},
28-
{syscall.O_RDONLY | syscall.O_CREAT, nil},
29-
{syscall.O_RDONLY | syscall.O_TRUNC, syscall.ERROR_ACCESS_DENIED},
30-
{syscall.O_WRONLY | syscall.O_RDWR, syscall.EISDIR},
31-
{syscall.O_WRONLY, syscall.EISDIR},
32-
{syscall.O_RDWR, syscall.EISDIR},
34+
{dir, syscall.O_RDONLY, nil},
35+
{dir, syscall.O_CREAT, nil},
36+
{dir, syscall.O_RDONLY | syscall.O_CREAT, nil},
37+
{file, syscall.O_APPEND | syscall.O_WRONLY | os.O_CREATE, nil},
38+
{file, syscall.O_APPEND | syscall.O_WRONLY | os.O_CREATE | os.O_TRUNC, nil},
39+
{dir, syscall.O_RDONLY | syscall.O_TRUNC, syscall.ERROR_ACCESS_DENIED},
40+
{dir, syscall.O_WRONLY | syscall.O_RDWR, syscall.EISDIR},
41+
{dir, syscall.O_WRONLY, syscall.EISDIR},
42+
{dir, syscall.O_RDWR, syscall.EISDIR},
3343
}
3444
for i, tt := range tests {
35-
h, err := syscall.Open(dir, tt.flag, 0)
45+
h, err := syscall.Open(tt.path, tt.flag, 0o660)
3646
if err == nil {
3747
syscall.CloseHandle(h)
3848
}
3949
if err != tt.err {
40-
t.Errorf("%d: Open got %v, want %v", i, err, tt.err)
50+
t.Errorf("%d: Open got %q, want %q", i, err, tt.err)
4151
}
4252
}
4353
}

0 commit comments

Comments
 (0)