diff options
Diffstat (limited to 'fikenauth/lock_unix.go')
| -rw-r--r-- | fikenauth/lock_unix.go | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/fikenauth/lock_unix.go b/fikenauth/lock_unix.go new file mode 100644 index 0000000..e29472d --- /dev/null +++ b/fikenauth/lock_unix.go @@ -0,0 +1,31 @@ +//go:build unix + +package fikenauth + +import ( + "fmt" + "os" + "path/filepath" + "syscall" +) + +// lock takes an exclusive lock beside the token file, held until unlock is +// called. It is advisory: it only orders programs that also take it, which is +// every program using this package. +func (s *Store) lock() (unlock func(), err error) { + if err := os.MkdirAll(filepath.Dir(s.path), 0o700); err != nil { + return nil, fmt.Errorf("create %s: %w", filepath.Dir(s.path), err) + } + f, err := os.OpenFile(s.path+".lock", os.O_CREATE|os.O_RDWR, 0o600) + if err != nil { + return nil, fmt.Errorf("lock %s: %w", s.path, err) + } + if err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX); err != nil { + f.Close() + return nil, fmt.Errorf("lock %s: %w", s.path, err) + } + return func() { + syscall.Flock(int(f.Fd()), syscall.LOCK_UN) //nolint:errcheck // closing releases it anyway + f.Close() + }, nil +} |
