diff --git a/go.mod b/go.mod
index 19881b0e81a3ea3964fd19e02a7b04aa71ff6471..cc0252c8123b9a69fff481f15fca0597d0b3de46 100644
--- a/go.mod
+++ b/go.mod
@@ -13,13 +13,13 @@ require (
 	github.com/go-ldap/ldap/v3 v3.4.8
 	github.com/go-sql-driver/mysql v1.7.1
 	github.com/go-webauthn/webauthn v0.10.2
+	github.com/gofrs/flock v0.12.1
 	github.com/google/go-cmp v0.6.0
 	github.com/lib/pq v1.10.9
 	github.com/mattn/go-sqlite3 v1.14.23
 	github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627
 	github.com/pquerna/otp v1.4.0
 	github.com/prometheus/client_golang v1.20.3
-	github.com/theckman/go-flock v0.8.1
 	go.opentelemetry.io/otel v1.10.0
 	go.opentelemetry.io/otel/trace v1.10.0
 	golang.org/x/sync v0.8.0
diff --git a/go.sum b/go.sum
index b60dca5b31dcf7a4266d8fd988073015eb8fdc5f..d41ff7b87c4f39a43622e70ea13a3be8036e49fa 100644
--- a/go.sum
+++ b/go.sum
@@ -784,7 +784,6 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/theckman/go-flock v0.8.1 h1:kTixuOsFBOtGYSTLRLWK6GOs1hk/8OD11sR1pDd0dl4=
 github.com/theckman/go-flock v0.8.1/go.mod h1:kjuth3y9VJ2aNlkNEO99G/8lp9fMIKaGyBmh84IBheM=
 github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
 github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
diff --git a/lineproto/unix.go b/lineproto/unix.go
index 3a6378b492619900939412a51e2fd3b9e662523d..d67ce7846fed2a3f68c2856a0eb360b3ac5bb9a3 100644
--- a/lineproto/unix.go
+++ b/lineproto/unix.go
@@ -5,7 +5,7 @@ import (
 	"net"
 	"os"
 
-	"github.com/theckman/go-flock"
+	"github.com/gofrs/flock"
 )
 
 type socketListener struct {
diff --git a/vendor/github.com/theckman/go-flock/.gitignore b/vendor/github.com/gofrs/flock/.gitignore
similarity index 100%
rename from vendor/github.com/theckman/go-flock/.gitignore
rename to vendor/github.com/gofrs/flock/.gitignore
diff --git a/vendor/github.com/gofrs/flock/.golangci.yml b/vendor/github.com/gofrs/flock/.golangci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3ad88a38fcd0f1cb2f011819a4739a74d60e6d97
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/.golangci.yml
@@ -0,0 +1,114 @@
+run:
+  timeout: 10m
+
+linters:
+  enable:
+    - asasalint
+    - bidichk
+    - dogsled
+    - dupword
+    - durationcheck
+    - err113
+    - errname
+    - errorlint
+    - fatcontext
+    - forbidigo
+    - gocheckcompilerdirectives
+    - gochecknoinits
+    - gocritic
+    - godot
+    - godox
+    - gofumpt
+    - goheader
+    - goimports
+    - gomoddirectives
+    - goprintffuncname
+    - gosec
+    - inamedparam
+    - interfacebloat
+    - ireturn
+    - mirror
+    - misspell
+    - nolintlint
+    - revive
+    - stylecheck
+    - tenv
+    - testifylint
+    - thelper
+    - unconvert
+    - unparam
+    - usestdlibvars
+    - whitespace
+
+linters-settings:
+  misspell:
+    locale: US
+  godox:
+    keywords:
+      - FIXME
+  goheader:
+    template: |-
+      Copyright 2015 Tim Heckman. All rights reserved.
+      Copyright 2018-{{ YEAR }} 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.
+  gofumpt:
+    extra-rules: true
+  gocritic:
+    enabled-tags:
+      - diagnostic
+      - style
+      - performance
+    disabled-checks:
+      - paramTypeCombine # already handle by gofumpt.extra-rules
+      - whyNoLint # already handle by nonolint
+      - unnamedResult
+      - hugeParam
+      - sloppyReassign
+      - rangeValCopy
+      - octalLiteral
+      - ptrToRefParam
+      - appendAssign
+      - ruleguard
+      - httpNoBody
+      - exposedSyncMutex
+
+  revive:
+    rules:
+      - name: struct-tag
+      - name: blank-imports
+      - name: context-as-argument
+      - name: context-keys-type
+      - name: dot-imports
+      - name: error-return
+      - name: error-strings
+      - name: error-naming
+      - name: exported
+      - name: if-return
+      - name: increment-decrement
+      - name: var-naming
+      - name: var-declaration
+      - name: package-comments
+      - name: range
+      - name: receiver-naming
+      - name: time-naming
+      - name: unexported-return
+      - name: indent-error-flow
+      - name: errorf
+      - name: empty-block
+      - name: superfluous-else
+      - name: unused-parameter
+      - name: unreachable-code
+      - name: redefines-builtin-id
+
+issues:
+  exclude-use-default: true
+  max-issues-per-linter: 0
+  max-same-issues: 0
+
+output:
+  show-stats: true
+  sort-results: true
+  sort-order:
+    - linter
+    - file
diff --git a/vendor/github.com/theckman/go-flock/LICENSE b/vendor/github.com/gofrs/flock/LICENSE
similarity index 97%
rename from vendor/github.com/theckman/go-flock/LICENSE
rename to vendor/github.com/gofrs/flock/LICENSE
index 8b8ff36fe4269955d9c5487e8c9dcb939b9ee135..7de525bf027ae25743e0418e7a6315c1f48f142c 100644
--- a/vendor/github.com/theckman/go-flock/LICENSE
+++ b/vendor/github.com/gofrs/flock/LICENSE
@@ -1,3 +1,4 @@
+Copyright (c) 2018-2024, The Gofrs
 Copyright (c) 2015-2020, Tim Heckman
 All rights reserved.
 
diff --git a/vendor/github.com/gofrs/flock/Makefile b/vendor/github.com/gofrs/flock/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..65c139d68c089e767da15ee48befe216088e0186
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/Makefile
@@ -0,0 +1,15 @@
+.PHONY: lint test test_race build_cross_os
+
+default: lint test build_cross_os
+
+test:
+	go test -v -cover ./...
+
+test_race:
+	CGO_ENABLED=1 go test -v -race ./...
+
+lint:
+	golangci-lint run
+
+build_cross_os:
+	./build.sh
diff --git a/vendor/github.com/gofrs/flock/README.md b/vendor/github.com/gofrs/flock/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f7ca0dd9c2417fc83dc3304db7c74f5afbfa5aa1
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/README.md
@@ -0,0 +1,45 @@
+# flock
+
+[![Go Reference](https://pkg.go.dev/badge/github.com/gofrs/flock.svg)](https://pkg.go.dev/github.com/gofrs/flock)
+[![License](https://img.shields.io/badge/license-BSD_3--Clause-brightgreen.svg?style=flat)](https://github.com/gofrs/flock/blob/main/LICENSE)
+[![Go Report Card](https://goreportcard.com/badge/github.com/gofrs/flock)](https://goreportcard.com/report/github.com/gofrs/flock)
+
+`flock` implements a thread-safe file lock.
+
+It also includes a non-blocking `TryLock()` function to allow locking without blocking execution.
+
+## Installation
+
+```bash
+go get -u github.com/gofrs/flock
+```
+
+## Usage
+
+```go
+import "github.com/gofrs/flock"
+
+fileLock := flock.New("/var/lock/go-lock.lock")
+
+locked, err := fileLock.TryLock()
+
+if err != nil {
+	// handle locking error
+}
+
+if locked {
+	// do work
+	fileLock.Unlock()
+}
+```
+
+For more detailed usage information take a look at the package API docs on
+[GoDoc](https://pkg.go.dev/github.com/gofrs/flock).
+
+## License
+
+`flock` is released under the BSD 3-Clause License. See the [`LICENSE`](./LICENSE) file for more details.
+
+## Project History
+
+This project was originally `github.com/theckman/go-flock`, it was transferred to Gofrs by the original author [Tim Heckman ](https://github.com/theckman).
diff --git a/vendor/github.com/gofrs/flock/SECURITY.md b/vendor/github.com/gofrs/flock/SECURITY.md
new file mode 100644
index 0000000000000000000000000000000000000000..01419bd592afd34db61c51b03c9afaa9ee367ddd
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/SECURITY.md
@@ -0,0 +1,21 @@
+# Security Policy
+
+## Supported Versions
+
+We support the latest version of this library.
+We do not guarantee support of previous versions.
+
+If a defect is reported, it will generally be fixed on the latest version (provided it exists) irrespective of whether it was introduced in a prior version.
+
+## Reporting a Vulnerability
+
+To report a potential security vulnerability, please create a [security advisory](https://github.com/gofrs/flock/security/advisories/new).
+
+For us to respond to your report most effectively, please include any of the following:
+
+- Steps to reproduce or a proof-of-concept
+- Any relevant information, including the versions used
+
+## Security Scorecard
+
+This project submits security [results](https://scorecard.dev/viewer/?uri=github.com/gofrs/flock) to the [OpenSSF Scorecard](https://securityscorecards.dev/).
diff --git a/vendor/github.com/gofrs/flock/build.sh b/vendor/github.com/gofrs/flock/build.sh
new file mode 100644
index 0000000000000000000000000000000000000000..60f7809f06578bc91b9a8ab47df02c8fd6024514
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -e
+
+# Not supported by flock:
+# - plan9/*
+# - js/wasm
+# - wasp1/wasm
+
+for row in $(go tool dist list -json | jq -r '.[] | @base64'); do
+  _jq() {
+    echo ${row} | base64 --decode | jq -r ${1}
+  }
+
+  GOOS=$(_jq '.GOOS')
+  GOARCH=$(_jq '.GOARCH')
+
+  echo "$GOOS/$GOARCH"
+  GOOS=$GOOS GOARCH=$GOARCH go build
+done
diff --git a/vendor/github.com/theckman/go-flock/flock.go b/vendor/github.com/gofrs/flock/flock.go
similarity index 68%
rename from vendor/github.com/theckman/go-flock/flock.go
rename to vendor/github.com/gofrs/flock/flock.go
index 95c784ca504bd1e089fd2e14462ea17a6fe4656c..ff942b228a66a7a4bbba671333bbe7cb1571beea 100644
--- a/vendor/github.com/theckman/go-flock/flock.go
+++ b/vendor/github.com/gofrs/flock/flock.go
@@ -1,4 +1,5 @@
 // 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.
 
@@ -18,12 +19,29 @@ package flock
 
 import (
 	"context"
+	"io/fs"
 	"os"
 	"runtime"
 	"sync"
 	"time"
 )
 
+type Option func(f *Flock)
+
+// SetFlag sets the flag used to create/open the file.
+func SetFlag(flag int) Option {
+	return func(f *Flock) {
+		f.flag = flag
+	}
+}
+
+// SetPermissions sets the OS permissions to set on the file.
+func SetPermissions(perm fs.FileMode) Option {
+	return func(f *Flock) {
+		f.perm = perm
+	}
+}
+
 // Flock is the struct type to handle file locking. All fields are unexported,
 // with access to some of the fields provided by getter methods (Path() and Locked()).
 type Flock struct {
@@ -32,12 +50,37 @@ type Flock struct {
 	fh   *os.File
 	l    bool
 	r    bool
+
+	// flag is the flag used to create/open the file.
+	flag int
+	// perm is the OS permissions to set on the file.
+	perm fs.FileMode
 }
 
 // New returns a new instance of *Flock. The only parameter
 // it takes is the path to the desired lockfile.
-func New(path string) *Flock {
-	return &Flock{path: path}
+func New(path string, opts ...Option) *Flock {
+	// create it if it doesn't exist, and open the file read-only.
+	flags := os.O_CREATE
+	switch runtime.GOOS {
+	case "aix", "solaris", "illumos":
+		// AIX cannot preform write-lock (i.e. exclusive) on a read-only file.
+		flags |= os.O_RDWR
+	default:
+		flags |= os.O_RDONLY
+	}
+
+	f := &Flock{
+		path: path,
+		flag: flags,
+		perm: fs.FileMode(0o600),
+	}
+
+	for _, opt := range opts {
+		opt(f)
+	}
+
+	return f
 }
 
 // NewFlock returns a new instance of *Flock. The only parameter
@@ -67,6 +110,7 @@ func (f *Flock) Path() string {
 func (f *Flock) Locked() bool {
 	f.m.RLock()
 	defer f.m.RUnlock()
+
 	return f.l
 }
 
@@ -76,6 +120,7 @@ func (f *Flock) Locked() bool {
 func (f *Flock) RLocked() bool {
 	f.m.RLock()
 	defer f.m.RUnlock()
+
 	return f.r
 }
 
@@ -83,16 +128,18 @@ func (f *Flock) String() string {
 	return f.path
 }
 
-// TryLockContext repeatedly tries to take an exclusive lock until one of the
-// conditions is met: TryLock succeeds, TryLock fails with error, or Context
-// Done channel is closed.
+// TryLockContext repeatedly tries to take an exclusive lock until one of the conditions is met:
+// - TryLock succeeds
+// - TryLock fails with error
+// - Context Done channel is closed.
 func (f *Flock) TryLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
 	return tryCtx(ctx, f.TryLock, retryDelay)
 }
 
-// TryRLockContext repeatedly tries to take a shared lock until one of the
-// conditions is met: TryRLock succeeds, TryRLock fails with error, or Context
-// Done channel is closed.
+// TryRLockContext repeatedly tries to take a shared lock until one of the conditions is met:
+// - TryRLock succeeds
+// - TryRLock fails with error
+// - Context Done channel is closed.
 func (f *Flock) TryRLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
 	return tryCtx(ctx, f.TryRLock, retryDelay)
 }
@@ -101,10 +148,12 @@ func tryCtx(ctx context.Context, fn func() (bool, error), retryDelay time.Durati
 	if ctx.Err() != nil {
 		return false, ctx.Err()
 	}
+
 	for {
 		if ok, err := fn(); ok || err != nil {
 			return ok, err
 		}
+
 		select {
 		case <-ctx.Done():
 			return false, ctx.Err()
@@ -114,31 +163,44 @@ func tryCtx(ctx context.Context, fn func() (bool, error), retryDelay time.Durati
 	}
 }
 
-func (f *Flock) setFh() error {
+func (f *Flock) setFh(flag int) error {
 	// open a new os.File instance
-	// create it if it doesn't exist, and open the file read-only.
-	flags := os.O_CREATE
-	if runtime.GOOS == "aix" {
-		// AIX cannot preform write-lock (ie exclusive) on a
-		// read-only file.
-		flags |= os.O_RDWR
-	} else {
-		flags |= os.O_RDONLY
-	}
-	fh, err := os.OpenFile(f.path, flags, os.FileMode(0600))
+	fh, err := os.OpenFile(f.path, flag, f.perm)
 	if err != nil {
 		return err
 	}
 
-	// set the filehandle on the struct
+	// set the file handle on the struct
 	f.fh = fh
+
 	return nil
 }
 
-// ensure the file handle is closed if no lock is held
+// resetFh resets file handle:
+// - tries to close the file (ignore errors)
+// - sets fh to nil.
+func (f *Flock) resetFh() {
+	if f.fh == nil {
+		return
+	}
+
+	_ = f.fh.Close()
+
+	f.fh = nil
+}
+
+// ensure the file handle is closed if no lock is held.
 func (f *Flock) ensureFhState() {
-	if !f.l && !f.r && f.fh != nil {
-		f.fh.Close()
-		f.fh = nil
+	if f.l || f.r || f.fh == nil {
+		return
 	}
+
+	f.resetFh()
+}
+
+func (f *Flock) reset() {
+	f.l = false
+	f.r = false
+
+	f.resetFh()
 }
diff --git a/vendor/github.com/gofrs/flock/flock_others.go b/vendor/github.com/gofrs/flock/flock_others.go
new file mode 100644
index 0000000000000000000000000000000000000000..18b14f1bd7a54690857e5e4a8f6c7e7405297aaf
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/flock_others.go
@@ -0,0 +1,40 @@
+//go:build (!unix && !windows) || plan9
+
+package flock
+
+import (
+	"errors"
+	"io/fs"
+)
+
+func (f *Flock) Lock() error {
+	return &fs.PathError{
+		Op:   "Lock",
+		Path: f.Path(),
+		Err:  errors.ErrUnsupported,
+	}
+}
+
+func (f *Flock) RLock() error {
+	return &fs.PathError{
+		Op:   "RLock",
+		Path: f.Path(),
+		Err:  errors.ErrUnsupported,
+	}
+}
+
+func (f *Flock) Unlock() error {
+	return &fs.PathError{
+		Op:   "Unlock",
+		Path: f.Path(),
+		Err:  errors.ErrUnsupported,
+	}
+}
+
+func (f *Flock) TryLock() (bool, error) {
+	return false, f.Lock()
+}
+
+func (f *Flock) TryRLock() (bool, error) {
+	return false, f.RLock()
+}
diff --git a/vendor/github.com/gofrs/flock/flock_unix.go b/vendor/github.com/gofrs/flock/flock_unix.go
new file mode 100644
index 0000000000000000000000000000000000000000..cf8919c7addb5a100124bb585dc0c645415645b4
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/flock_unix.go
@@ -0,0 +1,210 @@
+// 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.
+
+//go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd
+
+package flock
+
+import (
+	"errors"
+	"os"
+
+	"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.
+//
+// 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.
+func (f *Flock) Lock() error {
+	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.
+//
+// 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, unix.LOCK_SH)
+}
+
+func (f *Flock) lock(locked *bool, flag int) error {
+	f.m.Lock()
+	defer f.m.Unlock()
+
+	if *locked {
+		return nil
+	}
+
+	if f.fh == nil {
+		if err := f.setFh(f.flag); err != nil {
+			return err
+		}
+
+		defer f.ensureFhState()
+	}
+
+	err := unix.Flock(int(f.fh.Fd()), flag)
+	if err != nil {
+		shouldRetry, reopenErr := f.reopenFDOnError(err)
+		if reopenErr != nil {
+			return reopenErr
+		}
+
+		if !shouldRetry {
+			return err
+		}
+
+		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.
+//
+// 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.
+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 (!f.l && !f.r) || f.fh == nil {
+		return nil
+	}
+
+	// Mark the file as unlocked.
+	err := unix.Flock(int(f.fh.Fd()), unix.LOCK_UN)
+	if err != nil {
+		return err
+	}
+
+	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.
+//
+// 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, 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.
+//
+// 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, unix.LOCK_SH)
+}
+
+func (f *Flock) try(locked *bool, flag int) (bool, error) {
+	f.m.Lock()
+	defer f.m.Unlock()
+
+	if *locked {
+		return true, nil
+	}
+
+	if f.fh == nil {
+		if err := f.setFh(f.flag); err != nil {
+			return false, err
+		}
+
+		defer f.ensureFhState()
+	}
+
+	var retried bool
+retry:
+	err := unix.Flock(int(f.fh.Fd()), flag|unix.LOCK_NB)
+
+	switch {
+	case errors.Is(err, unix.EWOULDBLOCK):
+		return false, nil
+	case err == nil:
+		*locked = true
+		return true, nil
+	}
+
+	if !retried {
+		shouldRetry, reopenErr := f.reopenFDOnError(err)
+		if reopenErr != nil {
+			return false, reopenErr
+		} else if shouldRetry {
+			retried = true
+			goto 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().
+// > https://github.com/util-linux/util-linux/blob/198e920aa24743ef6ace4e07cf6237de527f9261/sys-utils/flock.c#L374-L390
+func (f *Flock) reopenFDOnError(err error) (bool, error) {
+	if !errors.Is(err, unix.EIO) && !errors.Is(err, unix.EBADF) {
+		return false, nil
+	}
+
+	st, err := f.fh.Stat()
+	if err != nil {
+		return false, nil
+	}
+
+	if st.Mode()&f.perm != f.perm {
+		return false, nil
+	}
+
+	f.resetFh()
+
+	// reopen in read-write mode and set the file handle
+	err = f.setFh(f.flag | os.O_RDWR)
+	if err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
diff --git a/vendor/github.com/gofrs/flock/flock_unix_fcntl.go b/vendor/github.com/gofrs/flock/flock_unix_fcntl.go
new file mode 100644
index 0000000000000000000000000000000000000000..ea007b47d9af5f5ef76c96e4decca1267ed50d6f
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/flock_unix_fcntl.go
@@ -0,0 +1,393 @@
+// 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.
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// 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,
+// we allow only one read-lock at a time.
+//
+// This code is adapted from the Go package (go.22):
+// https://github.com/golang/go/blob/release-branch.go1.22/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go
+
+//go:build aix || (solaris && !illumos)
+
+package flock
+
+import (
+	"errors"
+	"io"
+	"io/fs"
+	"math/rand"
+	"sync"
+	"syscall"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+// https://github.com/golang/go/blob/09aeb6e33ab426eff4676a3baf694d5a3019e9fc/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go#L28
+type lockType int16
+
+// String returns the name of the function corresponding to lt
+// (Lock, RLock, or Unlock).
+// https://github.com/golang/go/blob/09aeb6e33ab426eff4676a3baf694d5a3019e9fc/src/cmd/go/internal/lockedfile/internal/filelock/filelock.go#L67
+func (lt lockType) String() string {
+	switch lt {
+	case readLock:
+		return "RLock"
+	case writeLock:
+		return "Lock"
+	default:
+		return "Unlock"
+	}
+}
+
+// https://github.com/golang/go/blob/09aeb6e33ab426eff4676a3baf694d5a3019e9fc/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go#L30-L33
+const (
+	readLock  lockType = unix.F_RDLCK
+	writeLock lockType = unix.F_WRLCK
+)
+
+// https://github.com/golang/go/blob/09aeb6e33ab426eff4676a3baf694d5a3019e9fc/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go#L35
+type inode = uint64
+
+// https://github.com/golang/go/blob/09aeb6e33ab426eff4676a3baf694d5a3019e9fc/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go#L37-L40
+type inodeLock struct {
+	owner *Flock
+	queue []<-chan *Flock
+}
+
+type cmdType int
+
+const (
+	tryLock  cmdType = unix.F_SETLK
+	waitLock cmdType = unix.F_SETLKW
+)
+
+var (
+	mu     sync.Mutex
+	inodes = map[*Flock]inode{}
+	locks  = map[inode]inodeLock{}
+)
+
+// 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 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, writeLock)
+}
+
+// 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.
+func (f *Flock) RLock() error {
+	return f.lock(&f.r, readLock)
+}
+
+func (f *Flock) lock(locked *bool, flag lockType) error {
+	f.m.Lock()
+	defer f.m.Unlock()
+
+	if *locked {
+		return nil
+	}
+
+	if f.fh == nil {
+		if err := f.setFh(f.flag); err != nil {
+			return err
+		}
+
+		defer f.ensureFhState()
+	}
+
+	_, err := f.doLock(waitLock, flag, true)
+	if err != nil {
+		return err
+	}
+
+	*locked = true
+
+	return nil
+}
+
+// https://github.com/golang/go/blob/09aeb6e33ab426eff4676a3baf694d5a3019e9fc/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go#L48
+func (f *Flock) doLock(cmd cmdType, lt lockType, blocking bool) (bool, error) {
+	// POSIX locks apply per inode and process,
+	// and the lock for an inode is released when *any* descriptor for that inode is closed.
+	// So we need to synchronize access to each inode internally,
+	// and must serialize lock and unlock calls that refer to the same inode through different descriptors.
+	fi, err := f.fh.Stat()
+	if err != nil {
+		return false, err
+	}
+
+	// Note(ldez): don't replace `syscall.Stat_t` by `unix.Stat_t` because `FileInfo.Sys()` returns `syscall.Stat_t`
+	ino := fi.Sys().(*syscall.Stat_t).Ino
+
+	mu.Lock()
+
+	if i, dup := inodes[f]; dup && i != ino {
+		mu.Unlock()
+		return false, &fs.PathError{
+			Op:   lt.String(),
+			Path: f.Path(),
+			Err:  errors.New("inode for file changed since last Lock or RLock"),
+		}
+	}
+
+	inodes[f] = ino
+
+	var wait chan *Flock
+
+	l := locks[ino]
+
+	switch {
+	case l.owner == f:
+		// This file already owns the lock, but the call may change its lock type.
+	case l.owner == nil:
+		// No owner: it's ours now.
+		l.owner = f
+
+	case !blocking:
+		// Already owned: cannot take the lock.
+		mu.Unlock()
+		return false, nil
+
+	default:
+		// Already owned: add a channel to wait on.
+		wait = make(chan *Flock)
+		l.queue = append(l.queue, wait)
+	}
+
+	locks[ino] = l
+
+	mu.Unlock()
+
+	if wait != nil {
+		wait <- f
+	}
+
+	// Spurious EDEADLK errors arise on platforms that compute deadlock graphs at
+	// the process, rather than thread, level. Consider processes P and Q, with
+	// threads P.1, P.2, and Q.3. The following trace is NOT a deadlock, but will be
+	// reported as a deadlock on systems that consider only process granularity:
+	//
+	// 	P.1 locks file A.
+	// 	Q.3 locks file B.
+	// 	Q.3 blocks on file A.
+	// 	P.2 blocks on file B. (This is erroneously reported as a deadlock.)
+	// 	P.1 unlocks file A.
+	// 	Q.3 unblocks and locks file A.
+	// 	Q.3 unlocks files A and B.
+	// 	P.2 unblocks and locks file B.
+	// 	P.2 unlocks file B.
+	//
+	// These spurious errors were observed in practice on AIX and Solaris in
+	// cmd/go: see https://golang.org/issue/32817.
+	//
+	// We work around this bug by treating EDEADLK as always spurious. If there
+	// really is a lock-ordering bug between the interacting processes, it will
+	// become a livelock instead, but that's not appreciably worse than if we had
+	// a proper flock implementation (which generally does not even attempt to
+	// diagnose deadlocks).
+	//
+	// In the above example, that changes the trace to:
+	//
+	// 	P.1 locks file A.
+	// 	Q.3 locks file B.
+	// 	Q.3 blocks on file A.
+	// 	P.2 spuriously fails to lock file B and goes to sleep.
+	// 	P.1 unlocks file A.
+	// 	Q.3 unblocks and locks file A.
+	// 	Q.3 unlocks files A and B.
+	// 	P.2 wakes up and locks file B.
+	// 	P.2 unlocks file B.
+	//
+	// We know that the retry loop will not introduce a *spurious* livelock
+	// because, according to the POSIX specification, EDEADLK is only to be
+	// returned when “the lock is blocked by a lock from another process”.
+	// If that process is blocked on some lock that we are holding, then the
+	// resulting livelock is due to a real deadlock (and would manifest as such
+	// when using, for example, the flock implementation of this package).
+	// If the other process is *not* blocked on some other lock that we are
+	// holding, then it will eventually release the requested lock.
+
+	nextSleep := 1 * time.Millisecond
+	const maxSleep = 500 * time.Millisecond
+	for {
+		err = setlkw(f.fh.Fd(), cmd, lt)
+		if !errors.Is(err, unix.EDEADLK) {
+			break
+		}
+
+		time.Sleep(nextSleep)
+
+		nextSleep += nextSleep
+		if nextSleep > maxSleep {
+			nextSleep = maxSleep
+		}
+		// Apply 10% jitter to avoid synchronizing collisions when we finally unblock.
+		nextSleep += time.Duration((0.1*rand.Float64() - 0.05) * float64(nextSleep))
+	}
+
+	if err != nil {
+		f.doUnlock()
+
+		if cmd == tryLock && errors.Is(err, unix.EACCES) {
+			return false, nil
+		}
+
+		return false, &fs.PathError{
+			Op:   lt.String(),
+			Path: f.Path(),
+			Err:  err,
+		}
+	}
+
+	return true, nil
+}
+
+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 (!f.l && !f.r) || f.fh == nil {
+		return nil
+	}
+
+	if err := f.doUnlock(); err != nil {
+		return err
+	}
+
+	f.reset()
+
+	return nil
+}
+
+// https://github.com/golang/go/blob/09aeb6e33ab426eff4676a3baf694d5a3019e9fc/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go#L163
+func (f *Flock) doUnlock() (err error) {
+	var owner *Flock
+
+	mu.Lock()
+
+	ino, ok := inodes[f]
+	if ok {
+		owner = locks[ino].owner
+	}
+
+	mu.Unlock()
+
+	if owner == f {
+		err = setlkw(f.fh.Fd(), waitLock, unix.F_UNLCK)
+	}
+
+	mu.Lock()
+
+	l := locks[ino]
+
+	if len(l.queue) == 0 {
+		// No waiters: remove the map entry.
+		delete(locks, ino)
+	} else {
+		// The first waiter is sending us their file now.
+		// Receive it and update the queue.
+		l.owner = <-l.queue[0]
+		l.queue = l.queue[1:]
+		locks[ino] = l
+	}
+
+	delete(inodes, f)
+
+	mu.Unlock()
+
+	return err
+}
+
+// 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.
+func (f *Flock) TryLock() (bool, error) {
+	return f.try(&f.l, writeLock)
+}
+
+// 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.
+func (f *Flock) TryRLock() (bool, error) {
+	return f.try(&f.r, readLock)
+}
+
+func (f *Flock) try(locked *bool, flag lockType) (bool, error) {
+	f.m.Lock()
+	defer f.m.Unlock()
+
+	if *locked {
+		return true, nil
+	}
+
+	if f.fh == nil {
+		if err := f.setFh(f.flag); err != nil {
+			return false, err
+		}
+
+		defer f.ensureFhState()
+	}
+
+	hasLock, err := f.doLock(tryLock, flag, false)
+	if err != nil {
+		return false, err
+	}
+
+	*locked = hasLock
+
+	return hasLock, nil
+}
+
+// setlkw calls FcntlFlock with cmd for the entire file indicated by fd.
+// https://github.com/golang/go/blob/09aeb6e33ab426eff4676a3baf694d5a3019e9fc/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go#L198
+func setlkw(fd uintptr, cmd cmdType, lt lockType) error {
+	for {
+		err := unix.FcntlFlock(fd, int(cmd), &unix.Flock_t{
+			Type:   int16(lt),
+			Whence: io.SeekStart,
+			Start:  0,
+			Len:    0, // All bytes.
+		})
+		if !errors.Is(err, unix.EINTR) {
+			return err
+		}
+	}
+}
diff --git a/vendor/github.com/gofrs/flock/flock_windows.go b/vendor/github.com/gofrs/flock/flock_windows.go
new file mode 100644
index 0000000000000000000000000000000000000000..dfd31e15f509ce7c0661ba8ed86b8390055eb918
--- /dev/null
+++ b/vendor/github.com/gofrs/flock/flock_windows.go
@@ -0,0 +1,158 @@
+// 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.
+
+//go:build windows
+
+package flock
+
+import (
+	"errors"
+
+	"golang.org/x/sys/windows"
+)
+
+// Use of 0x00000000 for the shared lock is a guess based on some the MS Windows `LockFileEX` docs,
+// which document the `LOCKFILE_EXCLUSIVE_LOCK` flag as:
+//
+// > The function requests an exclusive lock. Otherwise, it requests a shared lock.
+//
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
+const winLockfileSharedLock = 0x00000000
+
+// ErrorLockViolation is the error code returned from the Windows syscall when a lock would block,
+// and you ask to fail immediately.
+const ErrorLockViolation windows.Errno = 0x21 // 33
+
+// 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 locked, this function short-circuits and
+// returns immediately assuming it can take the mutex lock.
+func (f *Flock) Lock() error {
+	return f.lock(&f.l, windows.LOCKFILE_EXCLUSIVE_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 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, winLockfileSharedLock)
+}
+
+func (f *Flock) lock(locked *bool, flag uint32) error {
+	f.m.Lock()
+	defer f.m.Unlock()
+
+	if *locked {
+		return nil
+	}
+
+	if f.fh == nil {
+		if err := f.setFh(f.flag); err != nil {
+			return err
+		}
+
+		defer f.ensureFhState()
+	}
+
+	err := windows.LockFileEx(windows.Handle(f.fh.Fd()), flag, 0, 1, 0, &windows.Overlapped{})
+	if err != nil && !errors.Is(err, windows.Errno(0)) {
+		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.
+//
+// This function short-circuits if we are unlocked already.
+// If not, it calls UnlockFileEx() on the file and closes the file descriptor.
+// It does not remove the file from disk.
+// It's up to your application to do.
+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 (!f.l && !f.r) || f.fh == nil {
+		return nil
+	}
+
+	// mark the file as unlocked
+	err := windows.UnlockFileEx(windows.Handle(f.fh.Fd()), 0, 1, 0, &windows.Overlapped{})
+	if err != nil && !errors.Is(err, windows.Errno(0)) {
+		return err
+	}
+
+	f.reset()
+
+	return nil
+}
+
+// TryLock is the preferred function for taking an exclusive file lock.
+// This function does take a 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.
+func (f *Flock) TryLock() (bool, error) {
+	return f.try(&f.l, windows.LOCKFILE_EXCLUSIVE_LOCK)
+}
+
+// TryRLock is the preferred function for taking a shared file lock.
+// This function does take a 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 shared-locked.
+func (f *Flock) TryRLock() (bool, error) {
+	return f.try(&f.r, winLockfileSharedLock)
+}
+
+func (f *Flock) try(locked *bool, flag uint32) (bool, error) {
+	f.m.Lock()
+	defer f.m.Unlock()
+
+	if *locked {
+		return true, nil
+	}
+
+	if f.fh == nil {
+		if err := f.setFh(f.flag); err != nil {
+			return false, err
+		}
+
+		defer f.ensureFhState()
+	}
+
+	err := windows.LockFileEx(windows.Handle(f.fh.Fd()), flag|windows.LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &windows.Overlapped{})
+	if err != nil && !errors.Is(err, windows.Errno(0)) {
+		if errors.Is(err, ErrorLockViolation) || errors.Is(err, windows.ERROR_IO_PENDING) {
+			return false, nil
+		}
+
+		return false, err
+	}
+
+	*locked = true
+
+	return true, nil
+}
diff --git a/vendor/github.com/theckman/go-flock/.travis.yml b/vendor/github.com/theckman/go-flock/.travis.yml
deleted file mode 100644
index b16d040fa89ebc904cbbc98afc8a8bcaf855507e..0000000000000000000000000000000000000000
--- a/vendor/github.com/theckman/go-flock/.travis.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-language: go
-go:
-  - 1.14.x
-  - 1.15.x
-script: go test -v -check.vv -race ./...
-sudo: false
-notifications:
-  email:
-    on_success: never
-    on_failure: always
diff --git a/vendor/github.com/theckman/go-flock/README.md b/vendor/github.com/theckman/go-flock/README.md
deleted file mode 100644
index 71ce63692e8e3ef433719aea060aa4dbfbe53ffb..0000000000000000000000000000000000000000
--- a/vendor/github.com/theckman/go-flock/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# flock
-[![TravisCI Build Status](https://img.shields.io/travis/gofrs/flock/master.svg?style=flat)](https://travis-ci.org/gofrs/flock)
-[![GoDoc](https://img.shields.io/badge/godoc-flock-blue.svg?style=flat)](https://godoc.org/github.com/gofrs/flock)
-[![License](https://img.shields.io/badge/license-BSD_3--Clause-brightgreen.svg?style=flat)](https://github.com/gofrs/flock/blob/master/LICENSE)
-[![Go Report Card](https://goreportcard.com/badge/github.com/gofrs/flock)](https://goreportcard.com/report/github.com/gofrs/flock)
-
-`flock` implements a thread-safe sync.Locker interface for file locking. It also
-includes a non-blocking TryLock() function to allow locking without blocking execution.
-
-## License
-`flock` is released under the BSD 3-Clause License. See the `LICENSE` file for more details.
-
-## Go Compatibility
-This package makes use of the `context` package that was introduced in Go 1.7. As such, this
-package has an implicit dependency on Go 1.7+.
-
-## Installation
-```
-go get -u github.com/gofrs/flock
-```
-
-## Usage
-```Go
-import "github.com/gofrs/flock"
-
-fileLock := flock.New("/var/lock/go-lock.lock")
-
-locked, err := fileLock.TryLock()
-
-if err != nil {
-	// handle locking error
-}
-
-if locked {
-	// do work
-	fileLock.Unlock()
-}
-```
-
-For more detailed usage information take a look at the package API docs on
-[GoDoc](https://godoc.org/github.com/gofrs/flock).
diff --git a/vendor/github.com/theckman/go-flock/appveyor.yml b/vendor/github.com/theckman/go-flock/appveyor.yml
deleted file mode 100644
index 909b4bf7cb4e21ca70c7cb9869066e8f4b6d719c..0000000000000000000000000000000000000000
--- a/vendor/github.com/theckman/go-flock/appveyor.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-version: '{build}'
-
-build: false
-deploy: false
-
-clone_folder: 'c:\gopath\src\github.com\gofrs\flock'
-
-environment:
-  GOPATH: 'c:\gopath'
-  GOVERSION: '1.15'
-
-init:
-  - git config --global core.autocrlf input
-
-install:
-  - rmdir c:\go /s /q
-  - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi
-  - msiexec /i go%GOVERSION%.windows-amd64.msi /q
-  - set Path=c:\go\bin;c:\gopath\bin;%Path%
-  - go version
-  - go env
-
-test_script:
-  - go get -t ./...
-  - go test -race -v ./...
diff --git a/vendor/github.com/theckman/go-flock/flock_aix.go b/vendor/github.com/theckman/go-flock/flock_aix.go
deleted file mode 100644
index 7277c1b6b2655cdc7eb5dfa59666ed0ebafd7b98..0000000000000000000000000000000000000000
--- a/vendor/github.com/theckman/go-flock/flock_aix.go
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright 2019 Tim Heckman. All rights reserved. Use of this source code is
-// governed by the BSD 3-Clause license that can be found in the LICENSE file.
-
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// 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,
-// we allow only one read-lock at a time.
-//
-// This code is adapted from the Go package:
-// cmd/go/internal/lockedfile/internal/filelock
-
-//+build aix
-
-package flock
-
-import (
-	"errors"
-	"io"
-	"os"
-	"sync"
-	"syscall"
-
-	"golang.org/x/sys/unix"
-)
-
-type lockType int16
-
-const (
-	readLock  lockType = unix.F_RDLCK
-	writeLock lockType = unix.F_WRLCK
-)
-
-type cmdType int
-
-const (
-	tryLock  cmdType = unix.F_SETLK
-	waitLock cmdType = unix.F_SETLKW
-)
-
-type inode = uint64
-
-type inodeLock struct {
-	owner *Flock
-	queue []<-chan *Flock
-}
-
-var (
-	mu     sync.Mutex
-	inodes = map[*Flock]inode{}
-	locks  = map[inode]inodeLock{}
-)
-
-// 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 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, writeLock)
-}
-
-// 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.
-func (f *Flock) RLock() error {
-	return f.lock(&f.r, readLock)
-}
-
-func (f *Flock) lock(locked *bool, flag lockType) error {
-	f.m.Lock()
-	defer f.m.Unlock()
-
-	if *locked {
-		return nil
-	}
-
-	if f.fh == nil {
-		if err := f.setFh(); err != nil {
-			return err
-		}
-		defer f.ensureFhState()
-	}
-
-	if _, err := f.doLock(waitLock, flag, true); err != nil {
-		return err
-	}
-
-	*locked = true
-	return nil
-}
-
-func (f *Flock) doLock(cmd cmdType, lt lockType, blocking bool) (bool, error) {
-	// POSIX locks apply per inode and process, and the lock for an inode is
-	// released when *any* descriptor for that inode is closed. So we need to
-	// synchronize access to each inode internally, and must serialize lock and
-	// unlock calls that refer to the same inode through different descriptors.
-	fi, err := f.fh.Stat()
-	if err != nil {
-		return false, err
-	}
-	ino := inode(fi.Sys().(*syscall.Stat_t).Ino)
-
-	mu.Lock()
-	if i, dup := inodes[f]; dup && i != ino {
-		mu.Unlock()
-		return false, &os.PathError{
-			Path: f.Path(),
-			Err:  errors.New("inode for file changed since last Lock or RLock"),
-		}
-	}
-
-	inodes[f] = ino
-
-	var wait chan *Flock
-	l := locks[ino]
-	if l.owner == f {
-		// This file already owns the lock, but the call may change its lock type.
-	} else if l.owner == nil {
-		// No owner: it's ours now.
-		l.owner = f
-	} else if !blocking {
-		// Already owned: cannot take the lock.
-		mu.Unlock()
-		return false, nil
-	} else {
-		// Already owned: add a channel to wait on.
-		wait = make(chan *Flock)
-		l.queue = append(l.queue, wait)
-	}
-	locks[ino] = l
-	mu.Unlock()
-
-	if wait != nil {
-		wait <- f
-	}
-
-	err = setlkw(f.fh.Fd(), cmd, lt)
-
-	if err != nil {
-		f.doUnlock()
-		if cmd == tryLock && err == unix.EACCES {
-			return false, nil
-		}
-		return false, err
-	}
-
-	return true, nil
-}
-
-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 (!f.l && !f.r) || f.fh == nil {
-		return nil
-	}
-
-	if err := f.doUnlock(); err != nil {
-		return err
-	}
-
-	f.fh.Close()
-
-	f.l = false
-	f.r = false
-	f.fh = nil
-
-	return nil
-}
-
-func (f *Flock) doUnlock() (err error) {
-	var owner *Flock
-	mu.Lock()
-	ino, ok := inodes[f]
-	if ok {
-		owner = locks[ino].owner
-	}
-	mu.Unlock()
-
-	if owner == f {
-		err = setlkw(f.fh.Fd(), waitLock, unix.F_UNLCK)
-	}
-
-	mu.Lock()
-	l := locks[ino]
-	if len(l.queue) == 0 {
-		// No waiters: remove the map entry.
-		delete(locks, ino)
-	} else {
-		// The first waiter is sending us their file now.
-		// Receive it and update the queue.
-		l.owner = <-l.queue[0]
-		l.queue = l.queue[1:]
-		locks[ino] = l
-	}
-	delete(inodes, f)
-	mu.Unlock()
-
-	return err
-}
-
-// 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.
-func (f *Flock) TryLock() (bool, error) {
-	return f.try(&f.l, writeLock)
-}
-
-// 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.
-func (f *Flock) TryRLock() (bool, error) {
-	return f.try(&f.r, readLock)
-}
-
-func (f *Flock) try(locked *bool, flag lockType) (bool, error) {
-	f.m.Lock()
-	defer f.m.Unlock()
-
-	if *locked {
-		return true, nil
-	}
-
-	if f.fh == nil {
-		if err := f.setFh(); err != nil {
-			return false, err
-		}
-		defer f.ensureFhState()
-	}
-
-	haslock, err := f.doLock(tryLock, flag, false)
-	if err != nil {
-		return false, err
-	}
-
-	*locked = haslock
-	return haslock, nil
-}
-
-// setlkw calls FcntlFlock with cmd for the entire file indicated by fd.
-func setlkw(fd uintptr, cmd cmdType, lt lockType) error {
-	for {
-		err := unix.FcntlFlock(fd, int(cmd), &unix.Flock_t{
-			Type:   int16(lt),
-			Whence: io.SeekStart,
-			Start:  0,
-			Len:    0, // All bytes.
-		})
-		if err != unix.EINTR {
-			return err
-		}
-	}
-}
diff --git a/vendor/github.com/theckman/go-flock/flock_unix.go b/vendor/github.com/theckman/go-flock/flock_unix.go
deleted file mode 100644
index c315a3e29084fd02b0da3513f50edec2cdaf8326..0000000000000000000000000000000000000000
--- a/vendor/github.com/theckman/go-flock/flock_unix.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2015 Tim Heckman. 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
-
-package flock
-
-import (
-	"os"
-	"syscall"
-)
-
-// 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 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)
-}
-
-// 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.
-func (f *Flock) RLock() error {
-	return f.lock(&f.r, syscall.LOCK_SH)
-}
-
-func (f *Flock) lock(locked *bool, flag int) error {
-	f.m.Lock()
-	defer f.m.Unlock()
-
-	if *locked {
-		return nil
-	}
-
-	if f.fh == nil {
-		if err := f.setFh(); err != nil {
-			return err
-		}
-		defer f.ensureFhState()
-	}
-
-	if err := syscall.Flock(int(f.fh.Fd()), flag); err != nil {
-		shouldRetry, reopenErr := f.reopenFDOnError(err)
-		if reopenErr != nil {
-			return reopenErr
-		}
-
-		if !shouldRetry {
-			return err
-		}
-
-		if err = syscall.Flock(int(f.fh.Fd()), flag); 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.
-//
-// 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.
-//
-// 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 (!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 {
-		return err
-	}
-
-	f.fh.Close()
-
-	f.l = false
-	f.r = false
-	f.fh = nil
-
-	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.
-//
-// 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)
-}
-
-// 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.
-func (f *Flock) TryRLock() (bool, error) {
-	return f.try(&f.r, syscall.LOCK_SH)
-}
-
-func (f *Flock) try(locked *bool, flag int) (bool, error) {
-	f.m.Lock()
-	defer f.m.Unlock()
-
-	if *locked {
-		return true, nil
-	}
-
-	if f.fh == nil {
-		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)
-
-	switch err {
-	case syscall.EWOULDBLOCK:
-		return false, nil
-	case nil:
-		*locked = true
-		return true, nil
-	}
-	if !retried {
-		if shouldRetry, reopenErr := f.reopenFDOnError(err); reopenErr != nil {
-			return false, reopenErr
-		} else if shouldRetry {
-			retried = true
-			goto 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().
-func (f *Flock) reopenFDOnError(err error) (bool, error) {
-	if err != syscall.EIO && err != syscall.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
-		}
-	}
-
-	return false, nil
-}
diff --git a/vendor/github.com/theckman/go-flock/flock_winapi.go b/vendor/github.com/theckman/go-flock/flock_winapi.go
deleted file mode 100644
index fe405a255ae5893637fe2b445c49090ae3c8f008..0000000000000000000000000000000000000000
--- a/vendor/github.com/theckman/go-flock/flock_winapi.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2015 Tim Heckman. 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 windows
-
-package flock
-
-import (
-	"syscall"
-	"unsafe"
-)
-
-var (
-	kernel32, _         = syscall.LoadLibrary("kernel32.dll")
-	procLockFileEx, _   = syscall.GetProcAddress(kernel32, "LockFileEx")
-	procUnlockFileEx, _ = syscall.GetProcAddress(kernel32, "UnlockFileEx")
-)
-
-const (
-	winLockfileFailImmediately = 0x00000001
-	winLockfileExclusiveLock   = 0x00000002
-	winLockfileSharedLock      = 0x00000000
-)
-
-// Use of 0x00000000 for the shared lock is a guess based on some the MS Windows
-// `LockFileEX` docs, which document the `LOCKFILE_EXCLUSIVE_LOCK` flag as:
-//
-// > The function requests an exclusive lock. Otherwise, it requests a shared
-// > lock.
-//
-// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
-
-func lockFileEx(handle syscall.Handle, flags uint32, reserved uint32, numberOfBytesToLockLow uint32, numberOfBytesToLockHigh uint32, offset *syscall.Overlapped) (bool, syscall.Errno) {
-	r1, _, errNo := syscall.Syscall6(
-		uintptr(procLockFileEx),
-		6,
-		uintptr(handle),
-		uintptr(flags),
-		uintptr(reserved),
-		uintptr(numberOfBytesToLockLow),
-		uintptr(numberOfBytesToLockHigh),
-		uintptr(unsafe.Pointer(offset)))
-
-	if r1 != 1 {
-		if errNo == 0 {
-			return false, syscall.EINVAL
-		}
-
-		return false, errNo
-	}
-
-	return true, 0
-}
-
-func unlockFileEx(handle syscall.Handle, reserved uint32, numberOfBytesToLockLow uint32, numberOfBytesToLockHigh uint32, offset *syscall.Overlapped) (bool, syscall.Errno) {
-	r1, _, errNo := syscall.Syscall6(
-		uintptr(procUnlockFileEx),
-		5,
-		uintptr(handle),
-		uintptr(reserved),
-		uintptr(numberOfBytesToLockLow),
-		uintptr(numberOfBytesToLockHigh),
-		uintptr(unsafe.Pointer(offset)),
-		0)
-
-	if r1 != 1 {
-		if errNo == 0 {
-			return false, syscall.EINVAL
-		}
-
-		return false, errNo
-	}
-
-	return true, 0
-}
diff --git a/vendor/github.com/theckman/go-flock/flock_windows.go b/vendor/github.com/theckman/go-flock/flock_windows.go
deleted file mode 100644
index ddb534ccef097fa17fd211ddc9ba55a8313f1bb4..0000000000000000000000000000000000000000
--- a/vendor/github.com/theckman/go-flock/flock_windows.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2015 Tim Heckman. All rights reserved.
-// Use of this source code is governed by the BSD 3-Clause
-// license that can be found in the LICENSE file.
-
-package flock
-
-import (
-	"syscall"
-)
-
-// ErrorLockViolation is the error code returned from the Windows syscall when a
-// lock would block and you ask to fail immediately.
-const ErrorLockViolation syscall.Errno = 0x21 // 33
-
-// 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 locked, this function short-circuits and returns
-// immediately assuming it can take the mutex lock.
-func (f *Flock) Lock() error {
-	return f.lock(&f.l, winLockfileExclusiveLock)
-}
-
-// 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 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, winLockfileSharedLock)
-}
-
-func (f *Flock) lock(locked *bool, flag uint32) error {
-	f.m.Lock()
-	defer f.m.Unlock()
-
-	if *locked {
-		return nil
-	}
-
-	if f.fh == nil {
-		if err := f.setFh(); err != nil {
-			return err
-		}
-		defer f.ensureFhState()
-	}
-
-	if _, errNo := lockFileEx(syscall.Handle(f.fh.Fd()), flag, 0, 1, 0, &syscall.Overlapped{}); errNo > 0 {
-		return errNo
-	}
-
-	*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.
-//
-// This function short-circuits if we are unlocked already. If not, it calls
-// UnlockFileEx() on the file and closes the file descriptor. It does not remove
-// the file from disk. It's up to your application to do.
-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 (!f.l && !f.r) || f.fh == nil {
-		return nil
-	}
-
-	// mark the file as unlocked
-	if _, errNo := unlockFileEx(syscall.Handle(f.fh.Fd()), 0, 1, 0, &syscall.Overlapped{}); errNo > 0 {
-		return errNo
-	}
-
-	f.fh.Close()
-
-	f.l = false
-	f.r = false
-	f.fh = nil
-
-	return nil
-}
-
-// TryLock is the preferred function for taking an exclusive file lock. This
-// function does take a 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.
-func (f *Flock) TryLock() (bool, error) {
-	return f.try(&f.l, winLockfileExclusiveLock)
-}
-
-// TryRLock is the preferred function for taking a shared file lock. This
-// function does take a 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 shared-locked.
-func (f *Flock) TryRLock() (bool, error) {
-	return f.try(&f.r, winLockfileSharedLock)
-}
-
-func (f *Flock) try(locked *bool, flag uint32) (bool, error) {
-	f.m.Lock()
-	defer f.m.Unlock()
-
-	if *locked {
-		return true, nil
-	}
-
-	if f.fh == nil {
-		if err := f.setFh(); err != nil {
-			return false, err
-		}
-		defer f.ensureFhState()
-	}
-
-	_, errNo := lockFileEx(syscall.Handle(f.fh.Fd()), flag|winLockfileFailImmediately, 0, 1, 0, &syscall.Overlapped{})
-
-	if errNo > 0 {
-		if errNo == ErrorLockViolation || errNo == syscall.ERROR_IO_PENDING {
-			return false, nil
-		}
-
-		return false, errNo
-	}
-
-	*locked = true
-
-	return true, nil
-}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e9faa3ece05883b776b0a52a5b14e690012ec1ae..81ba21f9780d6da9240b17df0d1521dfab52de15 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -73,6 +73,9 @@ github.com/go-webauthn/webauthn/webauthn
 # github.com/go-webauthn/x v0.1.9
 ## explicit; go 1.21
 github.com/go-webauthn/x/revoke
+# github.com/gofrs/flock v0.12.1
+## explicit; go 1.21.0
+github.com/gofrs/flock
 # github.com/golang-jwt/jwt/v5 v5.2.1
 ## explicit; go 1.18
 github.com/golang-jwt/jwt/v5
@@ -145,9 +148,6 @@ github.com/prometheus/common/model
 github.com/prometheus/procfs
 github.com/prometheus/procfs/internal/fs
 github.com/prometheus/procfs/internal/util
-# github.com/theckman/go-flock v0.8.1
-## explicit
-github.com/theckman/go-flock
 # github.com/x448/float16 v0.8.4
 ## explicit; go 1.11
 github.com/x448/float16