switch {
case flag&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL):
disposition = FILE_CREATE
+ options |= FILE_OPEN_REPARSE_POINT // don't follow symlinks
case flag&syscall.O_CREAT == syscall.O_CREAT:
disposition = FILE_OPEN_IF
default:
}
+func TestOpenFileCreateExclDanglingSymlink(t *testing.T) {
+ testMaybeRooted(t, func(t *testing.T, r *Root) {
+ const link = "link"
+ if err := Symlink("does_not_exist", link); err != nil {
+ t.Fatal(err)
+ }
+ var f *File
+ var err error
+ if r == nil {
+ f, err = OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o666)
+ } else {
+ f, err = r.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")
+ }
+ })
+}
+
// TestFileRDWRFlags tests the O_RDONLY, O_WRONLY, and O_RDWR flags.
func TestFileRDWRFlags(t *testing.T) {
for _, test := range []struct {
//
// Instead, we ftruncate the file after opening when O_TRUNC is set.
var createmode uint32
+ var attrs uint32 = FILE_ATTRIBUTE_NORMAL
switch {
case flag&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
createmode = CREATE_NEW
+ attrs |= FILE_FLAG_OPEN_REPARSE_POINT // don't follow symlinks
case flag&O_CREAT == O_CREAT:
createmode = OPEN_ALWAYS
default:
createmode = OPEN_EXISTING
}
- var attrs uint32 = FILE_ATTRIBUTE_NORMAL
if perm&S_IWRITE == 0 {
attrs = FILE_ATTRIBUTE_READONLY
}