carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package host
4
5import (
6 "fmt"
7 "os"
8 "path/filepath"
9 "syscall"
10
11 "github.com/carlosframework/platform/internal/safefile"
12)
13
14// The apply's two kernel-level needs, on the platform it actually runs on:
15// opening a path under a user-owned tree without following one symlink, and
16// an advisory lock that fails rather than waits when another apply holds it.
17//
18// linux, not unix: syscall.Openat is not in the stdlib syscall package on
19// darwin, and internal/host is linked into the CLI that people run on Macs.
20// The apply is a root oneshot on a Linux box and nothing else, so every
21// other OS gets systemapply_other.go's refusals and merely has to build.
22
23// openBeneath refuses symlinks in root and its descendants. The leaf is
24// pinned and checked as a single-link regular file before opening it for
25// I/O, so a planted device or FIFO is never opened for reading.
26func openBeneath(root string, parts ...string) (*os.File, error) {
27 for _, part := range parts {
28 if !filepath.IsLocal(part) {
29 return nil, fmt.Errorf("open %s: path escapes directory", root)
30 }
31 }
32 return safefile.OpenFile(filepath.Join(append([]string{root}, parts...)...), os.O_RDONLY, 0)
33}
34
35// flockExclusiveNonblock refuses when another apply holds the lock, so a
36// path-unit-triggered run exits quietly instead of queueing. It is the ONLY
37// way this package takes the apply lock: --recover wants it too, and wants
38// it enough to poll for half a minute, but never enough to block — see
39// systemApplier.waitForLock for the deadlock that buys.
40func flockExclusiveNonblock(f *os.File) error {
41 return syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
42}
43