message: relocate from container
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m22s
Test / Hpkg (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 4m28s
Test / Hakurei (race detector) (push) Successful in 5m21s
Test / Hakurei (push) Successful in 2m9s
Test / Flake checks (push) Successful in 1m29s

This package is quite useful. This change allows it to be imported without importing container.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2025-10-09 05:04:08 +09:00
parent df9b77b077
commit 87b5c30ef6
47 changed files with 210 additions and 185 deletions

View File

@@ -6,13 +6,13 @@ import (
"log"
"os"
"hakurei.app/container"
"hakurei.app/hst"
"hakurei.app/internal/app/state"
"hakurei.app/message"
)
// Main runs an app according to [hst.Config] and terminates. Main does not return.
func Main(ctx context.Context, msg container.Msg, config *hst.Config) {
func Main(ctx context.Context, msg message.Msg, config *hst.Config) {
var id state.ID
if err := state.NewAppID(&id); err != nil {
log.Fatal(err)

View File

@@ -23,12 +23,13 @@ import (
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/internal/app/state"
"hakurei.app/message"
"hakurei.app/system"
"hakurei.app/system/acl"
)
func TestApp(t *testing.T) {
msg := container.NewMsg(nil)
msg := message.NewMsg(nil)
msg.SwapVerbose(testing.Verbose())
testCases := []struct {
@@ -744,8 +745,8 @@ func (k *stubNixOS) cmdOutput(cmd *exec.Cmd) ([]byte, error) {
}
}
func (k *stubNixOS) overflowUid(container.Msg) int { return 65534 }
func (k *stubNixOS) overflowGid(container.Msg) int { return 65534 }
func (k *stubNixOS) overflowUid(message.Msg) int { return 65534 }
func (k *stubNixOS) overflowGid(message.Msg) int { return 65534 }
func (k *stubNixOS) mustHsuPath() *check.Absolute { return m("/proc/nonexistent/hsu") }

View File

@@ -12,6 +12,7 @@ import (
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/internal"
"hakurei.app/message"
)
// osFile represents [os.File].
@@ -53,9 +54,9 @@ type syscallDispatcher interface {
cmdOutput(cmd *exec.Cmd) ([]byte, error)
// overflowUid provides [container.OverflowUid].
overflowUid(msg container.Msg) int
overflowUid(msg message.Msg) int
// overflowGid provides [container.OverflowGid].
overflowGid(msg container.Msg) int
overflowGid(msg message.Msg) int
// mustHsuPath provides [internal.MustHsuPath].
mustHsuPath() *check.Absolute
@@ -90,8 +91,8 @@ func (direct) lookupGroupId(name string) (gid string, err error) {
func (direct) cmdOutput(cmd *exec.Cmd) ([]byte, error) { return cmd.Output() }
func (direct) overflowUid(msg container.Msg) int { return container.OverflowUid(msg) }
func (direct) overflowGid(msg container.Msg) int { return container.OverflowGid(msg) }
func (direct) overflowUid(msg message.Msg) int { return container.OverflowUid(msg) }
func (direct) overflowGid(msg message.Msg) int { return container.OverflowGid(msg) }
func (direct) mustHsuPath() *check.Absolute { return internal.MustHsuPath() }

View File

@@ -4,8 +4,8 @@ import (
"os"
"os/exec"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/message"
)
type panicDispatcher struct{}
@@ -21,7 +21,7 @@ func (panicDispatcher) tempdir() string { panic("unreachab
func (panicDispatcher) evalSymlinks(string) (string, error) { panic("unreachable") }
func (panicDispatcher) lookupGroupId(string) (string, error) { panic("unreachable") }
func (panicDispatcher) cmdOutput(*exec.Cmd) ([]byte, error) { panic("unreachable") }
func (panicDispatcher) overflowUid(container.Msg) int { panic("unreachable") }
func (panicDispatcher) overflowGid(container.Msg) int { panic("unreachable") }
func (panicDispatcher) overflowUid(message.Msg) int { panic("unreachable") }
func (panicDispatcher) overflowGid(message.Msg) int { panic("unreachable") }
func (panicDispatcher) mustHsuPath() *check.Absolute { panic("unreachable") }
func (panicDispatcher) fatalf(string, ...any) { panic("unreachable") }

View File

@@ -8,9 +8,9 @@ import (
"os/user"
"sync/atomic"
"hakurei.app/container"
"hakurei.app/hst"
"hakurei.app/internal/app/state"
"hakurei.app/message"
"hakurei.app/system"
)
@@ -37,7 +37,7 @@ type outcome struct {
syscallDispatcher
}
func (k *outcome) finalise(ctx context.Context, msg container.Msg, id *state.ID, config *hst.Config) error {
func (k *outcome) finalise(ctx context.Context, msg message.Msg, id *state.ID, config *hst.Config) error {
if ctx == nil || id == nil {
// unreachable
panic("invalid call to finalise")

View File

@@ -9,9 +9,9 @@ import (
"strconv"
"sync"
"hakurei.app/container"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/message"
)
// Hsu caches responses from cmd/hsu.
@@ -74,7 +74,7 @@ func (h *Hsu) ID() (int, error) {
func (h *Hsu) MustID() int { return h.MustIDMsg(nil) }
// MustIDMsg implements MustID with a custom [container.Msg].
func (h *Hsu) MustIDMsg(msg container.Msg) int {
func (h *Hsu) MustIDMsg(msg message.Msg) int {
id, err := h.ID()
if err == nil {
return id
@@ -87,7 +87,7 @@ func (h *Hsu) MustIDMsg(msg container.Msg) int {
}
os.Exit(1)
return -0xdeadbeef
} else if m, ok := container.GetErrorMessage(err); ok {
} else if m, ok := message.GetMessage(err); ok {
log.Fatal(m)
return -0xdeadbeef
} else {

View File

@@ -8,6 +8,7 @@ import (
"hakurei.app/container/check"
"hakurei.app/hst"
"hakurei.app/internal/app/state"
"hakurei.app/message"
"hakurei.app/system"
"hakurei.app/system/acl"
)
@@ -61,7 +62,7 @@ type outcomeState struct {
// Copied via populateLocal.
k syscallDispatcher
// Copied via populateLocal.
msg container.Msg
msg message.Msg
}
// valid checks outcomeState to be safe for use with outcomeOp.
@@ -75,7 +76,7 @@ func (s *outcomeState) valid() bool {
// populateEarly populates exported fields via syscallDispatcher.
// This must only be called from the priv side.
func (s *outcomeState) populateEarly(k syscallDispatcher, msg container.Msg, config *hst.Config) {
func (s *outcomeState) populateEarly(k syscallDispatcher, msg message.Msg, config *hst.Config) {
s.Shim = &shimParams{PrivPID: os.Getpid(), Verbose: msg.IsVerbose(), Ops: fromConfig(config)}
// enforce bounds and default early
@@ -98,7 +99,7 @@ func (s *outcomeState) populateEarly(k syscallDispatcher, msg container.Msg, con
// populateLocal populates unexported fields from transmitted exported fields.
// These fields are cheaper to recompute per-process.
func (s *outcomeState) populateLocal(k syscallDispatcher, msg container.Msg) error {
func (s *outcomeState) populateLocal(k syscallDispatcher, msg message.Msg) error {
if !s.valid() || k == nil || msg == nil {
return newWithMessage("impossible outcome state reached")
}

View File

@@ -17,6 +17,7 @@ import (
"hakurei.app/hst"
"hakurei.app/internal"
"hakurei.app/internal/app/state"
"hakurei.app/message"
"hakurei.app/system"
)
@@ -40,7 +41,7 @@ type mainState struct {
cmdWait chan error
k *outcome
container.Msg
message.Msg
uintptr
}
@@ -207,7 +208,7 @@ func (ms mainState) fatal(fallback string, ferr error) {
}
// main carries out outcome and terminates. main does not return.
func (k *outcome) main(msg container.Msg) {
func (k *outcome) main(msg message.Msg) {
if !k.active.CompareAndSwap(false, true) {
panic("outcome: attempted to run twice")
}
@@ -312,10 +313,10 @@ func (k *outcome) main(msg container.Msg) {
os.Exit(0)
}
// printMessageError prints the error message according to [container.GetErrorMessage],
// printMessageError prints the error message according to [message.GetMessage],
// or fallback prepended to err if an error message is not available.
func printMessageError(fallback string, err error) {
m, ok := container.GetErrorMessage(err)
m, ok := message.GetMessage(err)
if !ok {
log.Println(fallback, err)
return

View File

@@ -18,6 +18,7 @@ import (
"hakurei.app/container/bits"
"hakurei.app/container/seccomp"
"hakurei.app/hst"
"hakurei.app/message"
)
//#include "shim-signal.h"
@@ -57,7 +58,7 @@ func (p *shimParams) valid() bool {
func ShimMain() {
log.SetPrefix("shim: ")
log.SetFlags(0)
msg := container.NewMsg(log.Default())
msg := message.NewMsg(log.Default())
if err := container.SetDumpable(container.SUID_DUMP_DISABLE); err != nil {
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
@@ -81,7 +82,7 @@ func ShimMain() {
closeSetup = f
if err = state.populateLocal(direct{}, msg); err != nil {
if m, ok := container.GetErrorMessage(err); ok {
if m, ok := message.GetMessage(err); ok {
log.Fatal(m)
} else {
log.Fatalf("cannot populate local state: %v", err)
@@ -114,7 +115,7 @@ func ShimMain() {
}
for _, op := range state.Shim.Ops {
if err := op.toContainer(&stateParams); err != nil {
if m, ok := container.GetErrorMessage(err); ok {
if m, ok := message.GetMessage(err); ok {
log.Fatal(m)
} else {
log.Fatalf("cannot create container state: %v", err)

View File

@@ -15,6 +15,7 @@ import (
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp"
"hakurei.app/hst"
"hakurei.app/message"
"hakurei.app/system/dbus"
)
@@ -299,7 +300,7 @@ func resolveRoot(c *hst.ContainerConfig) (rootfs hst.FilesystemConfig, filesyste
}
// evalSymlinks calls syscallDispatcher.evalSymlinks but discards errors unwrapping to [fs.ErrNotExist].
func evalSymlinks(msg container.Msg, k syscallDispatcher, v *string) error {
func evalSymlinks(msg message.Msg, k syscallDispatcher, v *string) error {
if p, err := k.evalSymlinks(*v); err != nil {
if !errors.Is(err, fs.ErrNotExist) {
return err

View File

@@ -11,8 +11,8 @@ import (
"sync"
"syscall"
"hakurei.app/container"
"hakurei.app/hst"
"hakurei.app/message"
)
// fine-grained locking and access
@@ -22,7 +22,7 @@ type multiStore struct {
// initialised backends
backends *sync.Map
msg container.Msg
msg message.Msg
mu sync.RWMutex
}
@@ -280,7 +280,7 @@ func (b *multiBackend) close() error {
}
// NewMulti returns an instance of the multi-file store.
func NewMulti(msg container.Msg, runDir string) Store {
func NewMulti(msg message.Msg, runDir string) Store {
return &multiStore{
msg: msg,
base: path.Join(runDir, "state"),

View File

@@ -4,10 +4,10 @@ import (
"log"
"testing"
"hakurei.app/container"
"hakurei.app/internal/app/state"
"hakurei.app/message"
)
func TestMulti(t *testing.T) {
testStore(t, state.NewMulti(container.NewMsg(log.New(log.Writer(), "multi: ", 0)), t.TempDir()))
testStore(t, state.NewMulti(message.NewMsg(log.New(log.Writer(), "multi: ", 0)), t.TempDir()))
}