Commit ae8e0199 authored by lch's avatar lch Committed by lchopn

posixtest: fix test FcntlFlockSetLk

This test case is going to test whether the file lock works well on the
system. It firstly adds a lock and then get the lock through syscalls.
It uses F_OFD_GETLK command of fcntl(2) to get the lock info on an
opened file description[1], which is not defined on the FreeBSD. This
commit seperate the process of getting the information of lock for
different OSes, and mimic the behaviour of F_OFD_GETLK on FreeBSD.

[1]: https://www.gnu.org/software/libc/manual/html_node/Open-File-Description-Locks.html

Change-Id: I8abae0e7040fc667143eea028731e341be9b1baf
parent 4f621f9a
...@@ -662,12 +662,11 @@ func FcntlFlockSetLk(t *testing.T, mnt string) { ...@@ -662,12 +662,11 @@ func FcntlFlockSetLk(t *testing.T, mnt string) {
} }
defer f2.Close() defer f2.Close()
lk := syscall.Flock_t{} lk := syscall.Flock_t{}
if err := syscall.FcntlFlock(f2.Fd(), unix.F_OFD_GETLK, &lk); err != nil { if err := sysFcntlFlockGetOFDLock(f2.Fd(), &lk); err != nil {
t.Errorf("FcntlFlock failed: %v", err) t.Errorf("FcntlFlock failed: %v", err)
} }
if lk.Type != syscall.F_WRLCK { if lk.Type != syscall.F_WRLCK {
t.Errorf("got lk.Type=%v, want %v", lk.Type, syscall.F_WRLCK) t.Errorf("got lk.Type=%v, want %v", lk.Type, syscall.F_WRLCK)
} }
} }
} }
......
package posixtest
import "syscall"
// Exist at least from macOS Siera 10.12
const sys_F_OFD_GETLK = 92
func sysFcntlFlockGetOFDLock(fd uintptr, lk *syscall.Flock_t) error {
return syscall.FcntlFlock(fd, sys_F_OFD_GETLK, lk)
}
package posixtest
import (
"syscall"
"unsafe"
)
// Since FreeBSD doesn't implement the F_OFD_GETLK, to mimic its behaviour,
// we here first fork the process via syscall, and execute fcntl(2) in the child
// process to get the lock info. Then we send the lock info via pipe back to
// the parent test process.
func sysFcntlFlockGetOFDLock(fd uintptr, lk *syscall.Flock_t) error {
pipefd := make([]int, 2)
err := syscall.Pipe(pipefd)
if err != nil {
return err
}
pid, _, err := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0)
if pid == 0 { // child process
syscall.Close(pipefd[0]) // close read end
var clk syscall.Flock_t
// Here we must give a vaild lock type, or fcntl(2) will return
// EINVAL. And it should be different from what we set earlier
// in the test. Here we set to F_RDLOCK.
clk.Type = syscall.F_RDLCK
syscall.FcntlFlock(fd, syscall.F_GETLK, &clk)
syscall.Syscall(syscall.SYS_WRITE, uintptr(pipefd[1]), uintptr(unsafe.Pointer(&clk)), unsafe.Sizeof(clk))
syscall.Exit(0)
} else if pid > 0 { // parent process
syscall.Close(pipefd[1]) // close write end
buf := make([]byte, unsafe.Sizeof(*lk))
syscall.Read(pipefd[0], buf)
*lk = *((*syscall.Flock_t)(unsafe.Pointer(&buf[0])))
syscall.Close(pipefd[0]) // close read end
} else {
return err
}
return nil
}
package posixtest
import (
"syscall"
"golang.org/x/sys/unix"
)
func sysFcntlFlockGetOFDLock(fd uintptr, lk *syscall.Flock_t) error {
return syscall.FcntlFlock(fd, unix.F_OFD_GETLK, lk)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment