From 792c48e5130bf33d14a6a7fdfbe437439a4a93d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sun, 19 Jun 2022 13:07:03 +0200 Subject: [PATCH] Add windows version of lockutil from nerdctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also include netbsd, next to freebsd + linux Signed-off-by: Anders F Björklund --- .../{lockutil.go => lockutil_unix.go} | 5 +- pkg/lockutil/lockutil_windows.go | 70 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) rename pkg/lockutil/{lockutil.go => lockutil_unix.go} (90%) create mode 100644 pkg/lockutil/lockutil_windows.go diff --git a/pkg/lockutil/lockutil.go b/pkg/lockutil/lockutil_unix.go similarity index 90% rename from pkg/lockutil/lockutil.go rename to pkg/lockutil/lockutil_unix.go index cafe58eca7fc..f5abb778c3e6 100644 --- a/pkg/lockutil/lockutil.go +++ b/pkg/lockutil/lockutil_unix.go @@ -1,4 +1,7 @@ -// From https://github.com/containerd/nerdctl/blob/v0.9.0/pkg/lockutil/lockutil_linux.go +//go:build !windows +// +build !windows + +// From https://github.com/containerd/nerdctl/blob/v0.13.0/pkg/lockutil/lockutil_unix.go /* Copyright The containerd Authors. diff --git a/pkg/lockutil/lockutil_windows.go b/pkg/lockutil/lockutil_windows.go new file mode 100644 index 000000000000..9ac2394d629c --- /dev/null +++ b/pkg/lockutil/lockutil_windows.go @@ -0,0 +1,70 @@ +// From https://github.com/containerd/nerdctl/blob/v0.13.0/pkg/lockutil/lockutil_windows.go +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package lockutil + +import ( + "fmt" + "os" + "syscall" + "unsafe" + + "github.com/sirupsen/logrus" +) + +// LockFile modified from https://github.com/boltdb/bolt/blob/v1.3.1/bolt_windows.go using MIT +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procLockFileEx = modkernel32.NewProc("LockFileEx") + procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") +) + +func WithDirLock(dir string, fn func() error) error { + dirFile, err := os.OpenFile(dir+".lock", os.O_CREATE, 0644) + if err != nil { + return err + } + defer dirFile.Close() + // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx + // 1 lock immediately + if err := lockFileEx(syscall.Handle(dirFile.Fd()), 1, 0, 1, 0, &syscall.Overlapped{}); err != nil { + return fmt.Errorf("failed to lock %q: %w", dir, err) + } + + defer func() { + if err := unlockFileEx(syscall.Handle(dirFile.Fd()), 0, 1, 0, &syscall.Overlapped{}); err != nil { + logrus.WithError(err).Errorf("failed to unlock %q", dir) + } + }() + return fn() +} + +func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { + r, _, err := procLockFileEx.Call(uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol))) + if r == 0 { + return err + } + return nil +} + +func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { + r, _, err := procUnlockFileEx.Call(uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0) + if r == 0 { + return err + } + return nil +}