github.com/containers/podman/v4@v4.9.4/pkg/machine/wsl/filelock.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package wsl
     5  
     6  import (
     7  	"io/fs"
     8  	"math"
     9  	"os"
    10  
    11  	"golang.org/x/sys/windows"
    12  )
    13  
    14  type fileLock struct {
    15  	file *os.File
    16  }
    17  
    18  // Locks a file path, creating or overwriting a file if necessary. This API only
    19  // supports dedicated empty lock files. Locking is not advisory, once a file is
    20  // locked, additional opens will block on read/write.
    21  func lockFile(path string) (*fileLock, error) {
    22  	// In the future we may want to switch this to an async open vs the win32 API
    23  	// to bring support for timeouts, so we don't export the current underlying
    24  	// File object.
    25  	file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
    26  	if err != nil {
    27  		return nil, &fs.PathError{
    28  			Op:   "lock",
    29  			Path: path,
    30  			Err:  err,
    31  		}
    32  	}
    33  
    34  	const max = uint32(math.MaxUint32)
    35  	overlapped := new(windows.Overlapped)
    36  	lockType := windows.LOCKFILE_EXCLUSIVE_LOCK
    37  	// Lock largest possible length (all 64 bits (lo + hi) set)
    38  	err = windows.LockFileEx(windows.Handle(file.Fd()), uint32(lockType), 0, max, max, overlapped)
    39  	if err != nil {
    40  		file.Close()
    41  		return nil, &fs.PathError{
    42  			Op:   "lock",
    43  			Path: file.Name(),
    44  			Err:  err,
    45  		}
    46  	}
    47  
    48  	return &fileLock{file: file}, nil
    49  }
    50  
    51  func (flock *fileLock) unlock() error {
    52  	if flock == nil || flock.file == nil {
    53  		return nil
    54  	}
    55  
    56  	defer func() {
    57  		flock.file.Close()
    58  		flock.file = nil
    59  	}()
    60  
    61  	const max = uint32(math.MaxUint32)
    62  	overlapped := new(windows.Overlapped)
    63  	err := windows.UnlockFileEx(windows.Handle(flock.file.Fd()), 0, max, max, overlapped)
    64  	if err != nil {
    65  		return &fs.PathError{
    66  			Op:   "unlock",
    67  			Path: flock.file.Name(),
    68  			Err:  err,
    69  		}
    70  	}
    71  
    72  	return nil
    73  }