carlos / platform Public

host: system apply's syscalls behind the package's platform tags

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015QCUCpfxbCyEAVQ2m51dH5
Paul Campbell pushed by paul@keymail.dev 1b81a2d70ff014b6b7ae1d65e996e4f349e4c961 parent e77c186
3 files changed, +69 −29
  • internal/host/systemapply.go +0 −29
  • internal/host/systemapply_unix.go +46 −0
  • internal/host/systemapply_windows.go +23 −0
diff --git a/internal/host/systemapply.go b/internal/host/systemapply.go
index 78e2df5ad..0d46a97fe 100644
--- a/internal/host/systemapply.go
+++ b/internal/host/systemapply.go
@@ -12,7 +12,6 @@ import (
"os"
"path/filepath"
"strings"
- "syscall"
"time"
"github.com/carlosframework/platform/internal/release"
@@ -204,29 +203,6 @@ func (a *systemApplier) readRequest() (systemRequest, error) {
return req, nil
}
-// openBeneath opens root/parts... one component at a time with
-// O_DIRECTORY|O_NOFOLLOW for every directory and O_NOFOLLOW for the leaf,
-// so no component under a user-owned tree can be a symlink.
-func openBeneath(root string, parts ...string) (*os.File, error) {
- fd, err := syscall.Open(root, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_CLOEXEC, 0)
- if err != nil {
- return nil, fmt.Errorf("open %s: %w", root, err)
- }
- for i, part := range parts {
- flags := syscall.O_RDONLY | syscall.O_NOFOLLOW | syscall.O_CLOEXEC
- if i < len(parts)-1 {
- flags |= syscall.O_DIRECTORY
- }
- next, err := syscall.Openat(fd, part, flags, 0)
- syscall.Close(fd)
- if err != nil {
- return nil, fmt.Errorf("open %s: %w", filepath.Join(append([]string{root}, parts[:i+1]...)...), err)
- }
- fd = next
- }
- return os.NewFile(uintptr(fd), filepath.Join(append([]string{root}, parts...)...)), nil
-}
-
// verifyPointer fetches THIS box's channel pointer and verifies it with
// the release public key. The channel is root's own (host.env), never the
// request's. A store error is deferred, a bad pointer refused.
@@ -303,8 +279,3 @@ func (a *systemApplier) stageCandidate(p *release.SystemPointer, req systemReque
}
return staged, nil
}
-
-func flockExclusive(f *os.File) error { return syscall.Flock(int(f.Fd()), syscall.LOCK_EX) }
-func flockExclusiveNonblock(f *os.File) error {
- return syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
-}
diff --git a/internal/host/systemapply_unix.go b/internal/host/systemapply_unix.go
new file mode 100644
index 000000000..d906a1116
--- /dev/null
+++ b/internal/host/systemapply_unix.go
@@ -0,0 +1,46 @@
+//go:build !windows
+
+package host
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "syscall"
+)
+
+// The apply's two kernel-level needs, on the platform it actually runs on:
+// opening a path under a user-owned tree without following one symlink, and
+// an advisory lock that fails rather than waits when another apply holds it.
+
+// openBeneath opens root/parts... one component at a time with
+// O_DIRECTORY|O_NOFOLLOW for every directory and O_NOFOLLOW for the leaf,
+// so no component under a user-owned tree can be a symlink.
+func openBeneath(root string, parts ...string) (*os.File, error) {
+ fd, err := syscall.Open(root, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_CLOEXEC, 0)
+ if err != nil {
+ return nil, fmt.Errorf("open %s: %w", root, err)
+ }
+ for i, part := range parts {
+ flags := syscall.O_RDONLY | syscall.O_NOFOLLOW | syscall.O_CLOEXEC
+ if i < len(parts)-1 {
+ flags |= syscall.O_DIRECTORY
+ }
+ next, err := syscall.Openat(fd, part, flags, 0)
+ syscall.Close(fd)
+ if err != nil {
+ return nil, fmt.Errorf("open %s: %w", filepath.Join(append([]string{root}, parts[:i+1]...)...), err)
+ }
+ fd = next
+ }
+ return os.NewFile(uintptr(fd), filepath.Join(append([]string{root}, parts...)...)), nil
+}
+
+// flockExclusive waits for the apply lock (the recovery run must not skip
+// its work); flockExclusiveNonblock refuses when another apply holds it, so
+// a path-unit-triggered run exits quietly instead of queueing.
+func flockExclusive(f *os.File) error { return lockFileEx(f) }
+
+func flockExclusiveNonblock(f *os.File) error {
+ return syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
+}
diff --git a/internal/host/systemapply_windows.go b/internal/host/systemapply_windows.go
new file mode 100644
index 000000000..1dec23f4d
--- /dev/null
+++ b/internal/host/systemapply_windows.go
@@ -0,0 +1,23 @@
+//go:build windows
+
+package host
+
+import (
+ "errors"
+ "os"
+)
+
+// The platform self-update is a root oneshot on a Linux box; the Windows
+// build exists only so the carlos CLI compiles for workstation use. Both
+// primitives refuse rather than pretend: an apply that cannot lock, or that
+// cannot open a path without following symlinks, must do nothing at all.
+
+var errSystemUnsupported = errors.New("carlos system apply: unsupported on this platform")
+
+func openBeneath(root string, parts ...string) (*os.File, error) {
+ return nil, errSystemUnsupported
+}
+
+func flockExclusive(f *os.File) error { return errSystemUnsupported }
+
+func flockExclusiveNonblock(f *os.File) error { return errSystemUnsupported }