diff options
| author | Ian Lance Taylor <iant@golang.org> | 2020-05-19 20:23:58 -0700 |
|---|---|---|
| committer | Ian Lance Taylor <iant@golang.org> | 2020-05-20 21:52:34 +0000 |
| commit | 567556d78657326c99b8fa84ec2a5ee511a0941b (patch) | |
| tree | 9c93d363daf422261e2caae9319a58a90654d31a /src/syscall | |
| parent | aeab40317415468323ef45095f2090ff90c3ecd2 (diff) | |
| download | go-567556d78657326c99b8fa84ec2a5ee511a0941b.tar.xz | |
syscall: preserve Windows file permissions for O_CREAT|O_TRUNC
On Windows, calling syscall.Open(file, O_CREAT|O_TRUNC, 0) for a file
that already exists would change the file to be read-only.
That is not how the Unix syscall.Open behaves, so avoid it on
Windows by calling CreateFile twice if necessary.
Fixes #38225
Change-Id: I70097fca8863df427cc8a97b9376a9ffc69c6318
Reviewed-on: https://go-review.googlesource.com/c/go/+/234534
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Diffstat (limited to 'src/syscall')
| -rw-r--r-- | src/syscall/syscall_windows.go | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 89c0a930cb..f62c00d72f 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -339,6 +339,26 @@ func Open(path string, mode int, perm uint32) (fd Handle, err error) { var attrs uint32 = FILE_ATTRIBUTE_NORMAL if perm&S_IWRITE == 0 { attrs = FILE_ATTRIBUTE_READONLY + if createmode == CREATE_ALWAYS { + // We have been asked to create a read-only file. + // If the file already exists, the semantics of + // the Unix open system call is to preserve the + // existing permissions. If we pass CREATE_ALWAYS + // and FILE_ATTRIBUTE_READONLY to CreateFile, + // and the file already exists, CreateFile will + // change the file permissions. + // Avoid that to preserve the Unix semantics. + h, e := CreateFile(pathp, access, sharemode, sa, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) + switch e { + case ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, ERROR_PATH_NOT_FOUND: + // File does not exist. These are the same + // errors as Errno.Is checks for ErrNotExist. + // Carry on to create the file. + default: + // Success or some different error. + return h, e + } + } } h, e := CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0) return h, e |
