// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build aix solaris
+
// This code implements the filelock API using POSIX 'fcntl' locks, which attach
// to an (inode, process) pair rather than a file descriptor. To avoid unlocking
// files prematurely when the same file is opened through different descriptors,
//
// TODO(bcmills): If we add a build tag for Illumos (see golang.org/issue/20603)
// then Illumos should use F_OFD_SETLK, and the resulting code would be as
-// simple as filelock_unix.go. We will still need the code in this file as long
-// as Oracle Solaris provides only F_SETLK.
+// simple as filelock_unix.go. We will still need the code in this file for AIX
+// or as long as Oracle Solaris provides only F_SETLK.
package filelock
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!plan9,!solaris,!windows
+// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!plan9,!solaris,!windows
package filelock
f2 := mustOpen(t, f.Name())
defer f2.Close()
- if runtime.GOOS == "solaris" {
+ if runtime.GOOS == "solaris" || runtime.GOOS == "aix" {
// When using POSIX locks (as on Solaris), we can't safely read-lock the
// same inode through two different descriptors at the same time: when the
// first descriptor is closed, the second descriptor would still be open but
lockOther := mustBlock(t, "Lock", other)
unlock(t, f2)
- if runtime.GOOS != "solaris" {
+ if runtime.GOOS != "solaris" && runtime.GOOS != "aix" {
unlock(t, f)
}
lockOther(t)
import "unsafe"
-// On AIX, there is no flock() system call, we emulate it.
-// Moreover, we can't call the default fcntl syscall because the arguments
-// must be integer and it's not possible to transform a pointer (lk)
-// to a int value.
-// It's easier to call syscall6 than to transform fcntl for every GOOS.
-func fcntlFlock(fd, cmd int, lk *Flock_t) (err error) {
+// On AIX, there is no flock() system call.
+
+// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
+func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) (err error) {
_, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
-
-func Flock(fd int, op int) (err error) {
- lk := &Flock_t{}
- if (op & LOCK_UN) != 0 {
- lk.Type = F_UNLCK
- } else if (op & LOCK_EX) != 0 {
- lk.Type = F_WRLCK
- } else if (op & LOCK_SH) != 0 {
- lk.Type = F_RDLCK
- } else {
- return nil
- }
- if (op & LOCK_NB) != 0 {
- err = fcntlFlock(fd, F_SETLK, lk)
- if err != nil && (err == EAGAIN || err == EACCES) {
- return EWOULDBLOCK
- }
- return err
- }
- return fcntlFlock(fd, F_SETLKW, lk)
-}