aboutsummaryrefslogtreecommitdiffstats
path: root/fikenauth/lock_unix.go
blob: e29472d4ac81d8d4d036e6ea447354e89f444145 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
}