mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit to v0.15.0-rc1
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
175
vendor/github.com/gofrs/flock/flock_unix.go
generated
vendored
175
vendor/github.com/gofrs/flock/flock_unix.go
generated
vendored
@ -1,42 +1,44 @@
|
||||
// Copyright 2015 Tim Heckman. All rights reserved.
|
||||
// Copyright 2018-2024 The Gofrs. All rights reserved.
|
||||
// Use of this source code is governed by the BSD 3-Clause
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !aix,!windows
|
||||
//go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd
|
||||
|
||||
package flock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Lock is a blocking call to try and take an exclusive file lock. It will wait
|
||||
// until it is able to obtain the exclusive file lock. It's recommended that
|
||||
// TryLock() be used over this function. This function may block the ability to
|
||||
// query the current Locked() or RLocked() status due to a RW-mutex lock.
|
||||
// Lock is a blocking call to try and take an exclusive file lock.
|
||||
// It will wait until it is able to obtain the exclusive file lock.
|
||||
// It's recommended that TryLock() be used over this function.
|
||||
// This function may block the ability to query the current Locked() or RLocked() status due to a RW-mutex lock.
|
||||
//
|
||||
// If we are already exclusive-locked, this function short-circuits and returns
|
||||
// immediately assuming it can take the mutex lock.
|
||||
// If we are already exclusive-locked,
|
||||
// this function short-circuits and returns immediately assuming it can take the mutex lock.
|
||||
//
|
||||
// If the *Flock has a shared lock (RLock), this may transparently replace the
|
||||
// shared lock with an exclusive lock on some UNIX-like operating systems. Be
|
||||
// careful when using exclusive locks in conjunction with shared locks
|
||||
// (RLock()), because calling Unlock() may accidentally release the exclusive
|
||||
// lock that was once a shared lock.
|
||||
// If the *Flock has a shared lock (RLock),
|
||||
// this may transparently replace the shared lock with an exclusive lock on some UNIX-like operating systems.
|
||||
// Be careful when using exclusive locks in conjunction with shared locks (RLock()),
|
||||
// because calling Unlock() may accidentally release the exclusive lock that was once a shared lock.
|
||||
func (f *Flock) Lock() error {
|
||||
return f.lock(&f.l, syscall.LOCK_EX)
|
||||
return f.lock(&f.l, unix.LOCK_EX)
|
||||
}
|
||||
|
||||
// RLock is a blocking call to try and take a shared file lock. It will wait
|
||||
// until it is able to obtain the shared file lock. It's recommended that
|
||||
// TryRLock() be used over this function. This function may block the ability to
|
||||
// query the current Locked() or RLocked() status due to a RW-mutex lock.
|
||||
// RLock is a blocking call to try and take a shared file lock.
|
||||
// It will wait until it is able to obtain the shared file lock.
|
||||
// It's recommended that TryRLock() be used over this function.
|
||||
// This function may block the ability to query the current Locked() or RLocked() status due to a RW-mutex lock.
|
||||
//
|
||||
// If we are already shared-locked, this function short-circuits and returns
|
||||
// immediately assuming it can take the mutex lock.
|
||||
// If we are already shared-locked,
|
||||
// this function short-circuits and returns immediately assuming it can take the mutex lock.
|
||||
func (f *Flock) RLock() error {
|
||||
return f.lock(&f.r, syscall.LOCK_SH)
|
||||
return f.lock(&f.r, unix.LOCK_SH)
|
||||
}
|
||||
|
||||
func (f *Flock) lock(locked *bool, flag int) error {
|
||||
@ -51,10 +53,12 @@ func (f *Flock) lock(locked *bool, flag int) error {
|
||||
if err := f.setFh(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.ensureFhState()
|
||||
}
|
||||
|
||||
if err := syscall.Flock(int(f.fh.Fd()), flag); err != nil {
|
||||
err := unix.Flock(int(f.fh.Fd()), flag)
|
||||
if err != nil {
|
||||
shouldRetry, reopenErr := f.reopenFDOnError(err)
|
||||
if reopenErr != nil {
|
||||
return reopenErr
|
||||
@ -64,71 +68,74 @@ func (f *Flock) lock(locked *bool, flag int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = syscall.Flock(int(f.fh.Fd()), flag); err != nil {
|
||||
err = unix.Flock(int(f.fh.Fd()), flag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
*locked = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unlock is a function to unlock the file. This file takes a RW-mutex lock, so
|
||||
// while it is running the Locked() and RLocked() functions will be blocked.
|
||||
// Unlock is a function to unlock the file.
|
||||
// This file takes a RW-mutex lock,
|
||||
// so while it is running the Locked() and RLocked() functions will be blocked.
|
||||
//
|
||||
// This function short-circuits if we are unlocked already. If not, it calls
|
||||
// syscall.LOCK_UN on the file and closes the file descriptor. It does not
|
||||
// remove the file from disk. It's up to your application to do.
|
||||
// This function short-circuits if we are unlocked already.
|
||||
// If not, it calls unix.LOCK_UN on the file and closes the file descriptor.
|
||||
// It does not remove the file from disk. It's up to your application to do.
|
||||
//
|
||||
// Please note, if your shared lock became an exclusive lock this may
|
||||
// unintentionally drop the exclusive lock if called by the consumer that
|
||||
// believes they have a shared lock. Please see Lock() for more details.
|
||||
// Please note,
|
||||
// if your shared lock became an exclusive lock,
|
||||
// this may unintentionally drop the exclusive lock if called by the consumer that believes they have a shared lock.
|
||||
// Please see Lock() for more details.
|
||||
func (f *Flock) Unlock() error {
|
||||
f.m.Lock()
|
||||
defer f.m.Unlock()
|
||||
|
||||
// if we aren't locked or if the lockfile instance is nil
|
||||
// just return a nil error because we are unlocked
|
||||
// If we aren't locked or if the lockfile instance is nil
|
||||
// just return a nil error because we are unlocked.
|
||||
if (!f.l && !f.r) || f.fh == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// mark the file as unlocked
|
||||
if err := syscall.Flock(int(f.fh.Fd()), syscall.LOCK_UN); err != nil {
|
||||
// Mark the file as unlocked.
|
||||
err := unix.Flock(int(f.fh.Fd()), unix.LOCK_UN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.fh.Close()
|
||||
|
||||
f.l = false
|
||||
f.r = false
|
||||
f.fh = nil
|
||||
f.reset()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TryLock is the preferred function for taking an exclusive file lock. This
|
||||
// function takes an RW-mutex lock before it tries to lock the file, so there is
|
||||
// the possibility that this function may block for a short time if another
|
||||
// goroutine is trying to take any action.
|
||||
// TryLock is the preferred function for taking an exclusive file lock.
|
||||
// This function takes an RW-mutex lock before it tries to lock the file,
|
||||
// so there is the possibility that this function may block for a short time
|
||||
// if another goroutine is trying to take any action.
|
||||
//
|
||||
// The actual file lock is non-blocking. If we are unable to get the exclusive
|
||||
// file lock, the function will return false instead of waiting for the lock. If
|
||||
// we get the lock, we also set the *Flock instance as being exclusive-locked.
|
||||
// The actual file lock is non-blocking.
|
||||
// If we are unable to get the exclusive file lock,
|
||||
// the function will return false instead of waiting for the lock.
|
||||
// If we get the lock, we also set the *Flock instance as being exclusive-locked.
|
||||
func (f *Flock) TryLock() (bool, error) {
|
||||
return f.try(&f.l, syscall.LOCK_EX)
|
||||
return f.try(&f.l, unix.LOCK_EX)
|
||||
}
|
||||
|
||||
// TryRLock is the preferred function for taking a shared file lock. This
|
||||
// function takes an RW-mutex lock before it tries to lock the file, so there is
|
||||
// the possibility that this function may block for a short time if another
|
||||
// goroutine is trying to take any action.
|
||||
// TryRLock is the preferred function for taking a shared file lock.
|
||||
// This function takes an RW-mutex lock before it tries to lock the file,
|
||||
// so there is the possibility that this function may block for a short time
|
||||
// if another goroutine is trying to take any action.
|
||||
//
|
||||
// The actual file lock is non-blocking. If we are unable to get the shared file
|
||||
// lock, the function will return false instead of waiting for the lock. If we
|
||||
// get the lock, we also set the *Flock instance as being share-locked.
|
||||
// The actual file lock is non-blocking.
|
||||
// If we are unable to get the shared file lock,
|
||||
// the function will return false instead of waiting for the lock.
|
||||
// If we get the lock, we also set the *Flock instance as being share-locked.
|
||||
func (f *Flock) TryRLock() (bool, error) {
|
||||
return f.try(&f.r, syscall.LOCK_SH)
|
||||
return f.try(&f.r, unix.LOCK_SH)
|
||||
}
|
||||
|
||||
func (f *Flock) try(locked *bool, flag int) (bool, error) {
|
||||
@ -143,22 +150,25 @@ func (f *Flock) try(locked *bool, flag int) (bool, error) {
|
||||
if err := f.setFh(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer f.ensureFhState()
|
||||
}
|
||||
|
||||
var retried bool
|
||||
retry:
|
||||
err := syscall.Flock(int(f.fh.Fd()), flag|syscall.LOCK_NB)
|
||||
err := unix.Flock(int(f.fh.Fd()), flag|unix.LOCK_NB)
|
||||
|
||||
switch err {
|
||||
case syscall.EWOULDBLOCK:
|
||||
switch {
|
||||
case errors.Is(err, unix.EWOULDBLOCK):
|
||||
return false, nil
|
||||
case nil:
|
||||
case err == nil:
|
||||
*locked = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if !retried {
|
||||
if shouldRetry, reopenErr := f.reopenFDOnError(err); reopenErr != nil {
|
||||
shouldRetry, reopenErr := f.reopenFDOnError(err)
|
||||
if reopenErr != nil {
|
||||
return false, reopenErr
|
||||
} else if shouldRetry {
|
||||
retried = true
|
||||
@ -169,29 +179,34 @@ retry:
|
||||
return false, err
|
||||
}
|
||||
|
||||
// reopenFDOnError determines whether we should reopen the file handle
|
||||
// in readwrite mode and try again. This comes from util-linux/sys-utils/flock.c:
|
||||
// Since Linux 3.4 (commit 55725513)
|
||||
// Probably NFSv4 where flock() is emulated by fcntl().
|
||||
// reopenFDOnError determines whether we should reopen the file handle in readwrite mode and try again.
|
||||
// This comes from `util-linux/sys-utils/flock.c`:
|
||||
// > Since Linux 3.4 (commit 55725513)
|
||||
// > Probably NFSv4 where flock() is emulated by fcntl().
|
||||
func (f *Flock) reopenFDOnError(err error) (bool, error) {
|
||||
if err != syscall.EIO && err != syscall.EBADF {
|
||||
if !errors.Is(err, unix.EIO) && !errors.Is(err, unix.EBADF) {
|
||||
return false, nil
|
||||
}
|
||||
if st, err := f.fh.Stat(); err == nil {
|
||||
// if the file is able to be read and written
|
||||
if st.Mode()&0600 == 0600 {
|
||||
f.fh.Close()
|
||||
f.fh = nil
|
||||
|
||||
// reopen in read-write mode and set the filehandle
|
||||
fh, err := os.OpenFile(f.path, os.O_CREATE|os.O_RDWR, os.FileMode(0600))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
f.fh = fh
|
||||
return true, nil
|
||||
}
|
||||
st, err := f.fh.Stat()
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
if st.Mode()&f.perm != f.perm {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
_ = f.fh.Close()
|
||||
f.fh = nil
|
||||
|
||||
// reopen in read-write mode and set the file handle
|
||||
fh, err := os.OpenFile(f.path, f.flag, f.perm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
f.fh = fh
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user