carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package rootstate
2
3import (
4 "os"
5
6 "github.com/carlosframework/platform/internal/safefile"
7 "golang.org/x/sys/unix"
8)
9
10func (d *directory) liveFile(name string, create bool) (*os.File, error) {
11 if !component(name) || uint32(os.Geteuid()) != d.owner {
12 return nil, os.ErrPermission
13 }
14 if err := d.check(); err != nil {
15 return nil, err
16 }
17 flags := os.O_RDWR
18 if create {
19 flags |= os.O_CREATE
20 }
21 f, err := safefile.OpenFileAt(int(d.file.Fd()), name, flags, 0600)
22 if err != nil {
23 return nil, err
24 }
25 if err := trusted(int(f.Fd()), d.owner, unix.S_IFREG); err != nil {
26 f.Close()
27 return nil, err
28 }
29 return f, nil
30}
31
32func (d *directory) HoldLive(name string) (func(), error) {
33 f, err := d.liveFile(name, true)
34 if err != nil {
35 return nil, err
36 }
37 lock := unix.Flock_t{Type: unix.F_WRLCK, Whence: 0}
38 if err := unix.FcntlFlock(f.Fd(), unix.F_OFD_SETLK, &lock); err != nil {
39 f.Close()
40 return nil, err
41 }
42 return func() { _ = f.Close() }, nil
43}
44
45func (d *directory) LiveHeld(name string) (bool, error) {
46 f, err := d.liveFile(name, false)
47 if err != nil {
48 return false, err
49 }
50 defer f.Close()
51 lock := unix.Flock_t{Type: unix.F_RDLCK, Whence: 0}
52 if err := unix.FcntlFlock(f.Fd(), unix.F_OFD_GETLK, &lock); err != nil {
53 return false, err
54 }
55 return lock.Type == unix.F_WRLCK && lock.Pid == -1, nil
56}
57