diff --git a/src/os/os_test.go b/src/os/os_test.go index f1755dfa91..24a1d84b16 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -2174,6 +2174,24 @@ func TestAppend(t *testing.T) { } } +func TestOpenFileCreateExclDanglingSymlink(t *testing.T) { + defer chtmpdir(t)() + const link = "link" + if err := Symlink("does_not_exist", link); err != nil { + t.Fatal(err) + } + f, err := OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o666) + if err == nil { + f.Close() + } + if !errors.Is(err, ErrExist) { + t.Errorf("OpenFile of a dangling symlink with O_CREATE|O_EXCL = %v, want ErrExist", err) + } + if _, err := Stat(link); err == nil { + t.Errorf("OpenFile of a dangling symlink with O_CREATE|O_EXCL created a file") + } +} + func TestStatDirWithTrailingSlash(t *testing.T) { t.Parallel() diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index d49ee522c4..bbc1a11784 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -406,6 +406,9 @@ func Open(path string, mode int, perm uint32) (fd Handle, err error) { } } } + if createmode == CREATE_NEW { + attrs |= FILE_FLAG_OPEN_REPARSE_POINT // don't follow symlinks + } if createmode == OPEN_EXISTING && access == GENERIC_READ { // Necessary for opening directory handles. attrs |= FILE_FLAG_BACKUP_SEMANTICS