//go:build ((freebsd || openbsd || netbsd || dragonfly || illumos) && !(sqlite3_dotlk || sqlite3_nosys)) || sqlite3_flock package vfs import ( "os" "golang.org/x/sys/unix" ) func osGetSharedLock(file *os.File) _ErrorCode { return osLock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK) } func osGetReservedLock(file *os.File) _ErrorCode { rc := osLock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK) if rc == _BUSY { // The documentation states the lock is upgraded by releasing the previous lock, // then acquiring the new lock. // This is a race, so return BUSY_SNAPSHOT to ensure the transaction is aborted. return _BUSY_SNAPSHOT } return rc } func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { if *state >= LOCK_RESERVED { return _OK } return osGetReservedLock(file) } func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode { rc := osLock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK) if rc == _BUSY { // The documentation states the lock is upgraded by releasing the previous lock, // then acquiring the new lock. // This is a race, so return IOERR_RDLOCK to ensure the transaction is aborted. return _IOERR_RDLOCK } return _OK } func osReleaseLock(file *os.File, _ LockLevel) _ErrorCode { err := unix.Flock(int(file.Fd()), unix.LOCK_UN) if err != nil { return _IOERR_UNLOCK } return _OK } func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { // Test the RESERVED lock. lock, rc := osTestLock(file, _RESERVED_BYTE, 1) return lock == unix.F_WRLCK, rc } func osLock(file *os.File, how int, def _ErrorCode) _ErrorCode { err := unix.Flock(int(file.Fd()), how) return osLockErrorCode(err, def) }