Files
lch b0fe8dea8b 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
2024-05-15 10:12:19 +00:00

41 lines
1.3 KiB
Go

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
}