package rootstate import ( "os" "github.com/carlosframework/platform/internal/safefile" "golang.org/x/sys/unix" ) func (d *directory) liveFile(name string, create bool) (*os.File, error) { if !component(name) || uint32(os.Geteuid()) != d.owner { return nil, os.ErrPermission } if err := d.check(); err != nil { return nil, err } flags := os.O_RDWR if create { flags |= os.O_CREATE } f, err := safefile.OpenFileAt(int(d.file.Fd()), name, flags, 0600) if err != nil { return nil, err } if err := trusted(int(f.Fd()), d.owner, unix.S_IFREG); err != nil { f.Close() return nil, err } return f, nil } func (d *directory) HoldLive(name string) (func(), error) { f, err := d.liveFile(name, true) if err != nil { return nil, err } lock := unix.Flock_t{Type: unix.F_WRLCK, Whence: 0} if err := unix.FcntlFlock(f.Fd(), unix.F_OFD_SETLK, &lock); err != nil { f.Close() return nil, err } return func() { _ = f.Close() }, nil } func (d *directory) LiveHeld(name string) (bool, error) { f, err := d.liveFile(name, false) if err != nil { return false, err } defer f.Close() lock := unix.Flock_t{Type: unix.F_RDLCK, Whence: 0} if err := unix.FcntlFlock(f.Fd(), unix.F_OFD_GETLK, &lock); err != nil { return false, err } return lock.Type == unix.F_WRLCK && lock.Pid == -1, nil }