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 }