--- /dev/null
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build netbsd
+
+package os
+
+import "syscall"
+
+// isNoFollowErr reports whether err may result from O_NOFOLLOW blocking an open operation.
+func isNoFollowErr(err error) bool {
+ // NetBSD returns EFTYPE, but check the other possibilities as well.
+ switch err {
+ case syscall.ELOOP, syscall.EMLINK, syscall.EFTYPE:
+ return true
+ }
+ return false
+}
--- /dev/null
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || dragonfly || freebsd || linux || openbsd || solaris || wasip1
+
+package os
+
+import (
+ "runtime"
+ "syscall"
+)
+
+// isNoFollowErr reports whether err may result from O_NOFOLLOW blocking an open operation.
+func isNoFollowErr(err error) bool {
+ switch err {
+ case syscall.ELOOP, syscall.EMLINK:
+ return true
+ }
+ if runtime.GOOS == "dragonfly" {
+ // Dragonfly appears to return EINVAL from openat in this case.
+ if err == syscall.EINVAL {
+ return true
+ }
+ }
+ return false
+}
fd, err := doInRoot(r, name, func(parent int, name string) (fd int, err error) {
ignoringEINTR(func() error {
fd, err = unix.Openat(parent, name, syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0)
- if err == syscall.ELOOP || err == syscall.EMLINK {
+ if isNoFollowErr(err) {
err = checkSymlink(parent, name, err)
}
return err
fd, err := doInRoot(root, name, func(parent int, name string) (fd int, err error) {
ignoringEINTR(func() error {
fd, err = unix.Openat(parent, name, syscall.O_NOFOLLOW|syscall.O_CLOEXEC|flag, uint32(perm))
- if err == syscall.ELOOP || err == syscall.ENOTDIR || err == syscall.EMLINK {
+ if isNoFollowErr(err) || err == syscall.ENOTDIR {
err = checkSymlink(parent, name, err)
}
return err
)
ignoringEINTR(func() error {
fd, err = unix.Openat(parent, name, syscall.O_NOFOLLOW|syscall.O_CLOEXEC|syscall.O_DIRECTORY, 0)
- if err == syscall.ELOOP || err == syscall.ENOTDIR || err == syscall.EMLINK {
+ if isNoFollowErr(err) || err == syscall.ENOTDIR {
err = checkSymlink(parent, name, err)
} else if err == syscall.ENOTSUP || err == syscall.EOPNOTSUPP {
// ENOTSUP and EOPNOTSUPP are often, but not always, the same errno.