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:
Ophestra 2025-10-09 05:04:08 +09:00
parent df9b77b077
commit 87b5c30ef6
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
47 changed files with 210 additions and 185 deletions

View File

@ -15,17 +15,17 @@ import (
"time"
"hakurei.app/command"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/internal"
"hakurei.app/internal/app"
"hakurei.app/internal/app/state"
"hakurei.app/message"
"hakurei.app/system/dbus"
)
func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningErrs, out io.Writer) command.Command {
func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErrs, out io.Writer) command.Command {
var (
flagVerbose bool
flagJSON bool

View File

@ -7,7 +7,7 @@ import (
"testing"
"hakurei.app/command"
"hakurei.app/container"
"hakurei.app/message"
)
func TestHelp(t *testing.T) {
@ -69,7 +69,7 @@ Flags:
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
out := new(bytes.Buffer)
c := buildCommand(t.Context(), container.NewMsg(nil), new(earlyHardeningErrs), out)
c := buildCommand(t.Context(), message.NewMsg(nil), new(earlyHardeningErrs), out)
if err := c.Parse(tc.args); !errors.Is(err, command.ErrHelp) && !errors.Is(err, flag.ErrHelp) {
t.Errorf("Parse: error = %v; want %v",
err, command.ErrHelp)

View File

@ -13,6 +13,7 @@ import (
"syscall"
"hakurei.app/container"
"hakurei.app/message"
)
var (
@ -31,7 +32,7 @@ func main() {
log.SetPrefix("hakurei: ")
log.SetFlags(0)
msg := container.NewMsg(log.Default())
msg := message.NewMsg(log.Default())
early := earlyHardeningErrs{
yamaLSM: container.SetPtracer(0),

View File

@ -10,13 +10,13 @@ import (
"strings"
"syscall"
"hakurei.app/container"
"hakurei.app/hst"
"hakurei.app/internal/app"
"hakurei.app/internal/app/state"
"hakurei.app/message"
)
func tryPath(msg container.Msg, name string) (config *hst.Config) {
func tryPath(msg message.Msg, name string) (config *hst.Config) {
var r io.Reader
config = new(hst.Config)
@ -49,7 +49,7 @@ func tryPath(msg container.Msg, name string) (config *hst.Config) {
return
}
func tryFd(msg container.Msg, name string) io.ReadCloser {
func tryFd(msg message.Msg, name string) io.ReadCloser {
if v, err := strconv.Atoi(name); err != nil {
if !errors.Is(err, strconv.ErrSyntax) {
msg.Verbosef("name cannot be interpreted as int64: %v", err)
@ -68,7 +68,7 @@ func tryFd(msg container.Msg, name string) io.ReadCloser {
}
}
func tryShort(msg container.Msg, name string) (config *hst.Config, entry *state.State) {
func tryShort(msg message.Msg, name string) (config *hst.Config, entry *state.State) {
likePrefix := false
if len(name) <= 32 {
likePrefix = true

View File

@ -11,10 +11,10 @@ import (
"text/tabwriter"
"time"
"hakurei.app/container"
"hakurei.app/hst"
"hakurei.app/internal/app"
"hakurei.app/internal/app/state"
"hakurei.app/message"
)
func printShowSystem(output io.Writer, short, flagJSON bool) {
@ -56,7 +56,7 @@ func printShowInstance(
if err := config.Validate(); err != nil {
valid = false
if m, ok := container.GetErrorMessage(err); ok {
if m, ok := message.GetMessage(err); ok {
mustPrint(output, "Error: "+m+"!\n\n")
}
}

View File

@ -11,10 +11,10 @@ import (
"syscall"
"hakurei.app/command"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/message"
)
var (
@ -24,7 +24,7 @@ var (
func main() {
log.SetPrefix("hpkg: ")
log.SetFlags(0)
msg := container.NewMsg(log.Default())
msg := message.NewMsg(log.Default())
if err := os.Setenv("SHELL", pathShell.String()); err != nil {
log.Fatalf("cannot set $SHELL: %v", err)

View File

@ -7,10 +7,10 @@ import (
"strconv"
"sync/atomic"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/message"
)
const bash = "bash"
@ -52,7 +52,7 @@ func lookPath(file string) string {
var beforeRunFail = new(atomic.Pointer[func()])
func mustRun(msg container.Msg, name string, arg ...string) {
func mustRun(msg message.Msg, name string, arg ...string) {
msg.Verbosef("spawning process: %q %q", name, arg)
cmd := exec.Command(name, arg...)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr

View File

@ -9,14 +9,14 @@ import (
"os"
"os/exec"
"hakurei.app/container"
"hakurei.app/hst"
"hakurei.app/internal"
"hakurei.app/message"
)
var hakureiPath = internal.MustHakureiPath()
func mustRunApp(ctx context.Context, msg container.Msg, config *hst.Config, beforeFail func()) {
func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, beforeFail func()) {
var (
cmd *exec.Cmd
st io.WriteCloser

View File

@ -5,15 +5,15 @@ import (
"os"
"strings"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/message"
)
func withNixDaemon(
ctx context.Context,
msg container.Msg,
msg message.Msg,
action string, command []string, net bool, updateConfig func(config *hst.Config) *hst.Config,
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(),
) {
@ -64,7 +64,7 @@ func withNixDaemon(
func withCacheDir(
ctx context.Context,
msg container.Msg,
msg message.Msg,
action string, command []string, workDir *check.Absolute,
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func()) {
mustRunAppDropShell(ctx, msg, &hst.Config{
@ -102,7 +102,7 @@ func withCacheDir(
}, dropShell, beforeFail)
}
func mustRunAppDropShell(ctx context.Context, msg container.Msg, config *hst.Config, dropShell bool, beforeFail func()) {
func mustRunAppDropShell(ctx context.Context, msg message.Msg, config *hst.Config, dropShell bool, beforeFail func()) {
if dropShell {
if config.Container != nil {
config.Container.Args = []string{bash, "-l"}

View File

@ -6,6 +6,7 @@ import (
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/message"
)
func init() { gob.Register(new(AutoRootOp)) }
@ -81,7 +82,7 @@ func (r *AutoRootOp) String() string {
}
// IsAutoRootBindable returns whether a dir entry name is selected for AutoRoot.
func IsAutoRootBindable(msg Msg, name string) bool {
func IsAutoRootBindable(msg message.Msg, name string) bool {
switch name {
case "proc", "dev", "tmp", "mnt", "etc":

View File

@ -8,6 +8,7 @@ import (
"hakurei.app/container/bits"
"hakurei.app/container/check"
"hakurei.app/container/stub"
"hakurei.app/message"
)
func TestAutoRootOp(t *testing.T) {
@ -195,7 +196,7 @@ func TestIsAutoRootBindable(t *testing.T) {
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var msg Msg
var msg message.Msg
if tc.log {
msg = &kstub{nil, stub.New(t, func(s *stub.Stub[syscallDispatcher]) syscallDispatcher { panic("unreachable") }, stub.Expect{Calls: []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"got unexpected root entry"}}, nil, nil),

View File

@ -18,6 +18,7 @@ import (
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp"
"hakurei.app/message"
)
const (
@ -52,7 +53,7 @@ type (
cmd *exec.Cmd
ctx context.Context
msg Msg
msg message.Msg
Params
}
@ -396,9 +397,9 @@ func (p *Container) ProcessState() *os.ProcessState {
}
// New returns the address to a new instance of [Container] that requires further initialisation before use.
func New(ctx context.Context, msg Msg) *Container {
func New(ctx context.Context, msg message.Msg) *Container {
if msg == nil {
msg = NewMsg(nil)
msg = message.NewMsg(nil)
}
p := &Container{ctx: ctx, msg: msg, Params: Params{Ops: new(Ops)}}
@ -409,7 +410,7 @@ func New(ctx context.Context, msg Msg) *Container {
}
// NewCommand calls [New] and initialises the [Params.Path] and [Params.Args] fields.
func NewCommand(ctx context.Context, msg Msg, pathname *check.Absolute, name string, args ...string) *Container {
func NewCommand(ctx context.Context, msg message.Msg, pathname *check.Absolute, name string, args ...string) *Container {
z := New(ctx, msg)
z.Path = pathname
z.Args = append([]string{name}, args...)

View File

@ -26,6 +26,7 @@ import (
"hakurei.app/container/vfs"
"hakurei.app/hst"
"hakurei.app/ldd"
"hakurei.app/message"
)
func TestStartError(t *testing.T) {
@ -152,13 +153,13 @@ func TestStartError(t *testing.T) {
})
t.Run("msg", func(t *testing.T) {
if got, ok := container.GetErrorMessage(tc.err); !ok {
if got, ok := message.GetMessage(tc.err); !ok {
if tc.msg != "" {
t.Errorf("GetErrorMessage: err does not implement MessageError")
t.Errorf("GetMessage: err does not implement MessageError")
}
return
} else if got != tc.msg {
t.Errorf("GetErrorMessage: %q, want %q", got, tc.msg)
t.Errorf("GetMessage: %q, want %q", got, tc.msg)
}
})
})
@ -545,7 +546,7 @@ func testContainerCancel(
}
func TestContainerString(t *testing.T) {
msg := container.NewMsg(nil)
msg := message.NewMsg(nil)
c := container.NewCommand(t.Context(), msg, check.MustAbs("/run/current-system/sw/bin/ldd"), "ldd", "/usr/bin/env")
c.SeccompFlags |= seccomp.AllowMultiarch
c.SeccompRules = seccomp.Preset(
@ -711,7 +712,7 @@ func TestMain(m *testing.M) {
}
func helperNewContainerLibPaths(ctx context.Context, libPaths *[]*check.Absolute, args ...string) (c *container.Container) {
msg := container.NewMsg(nil)
msg := message.NewMsg(nil)
c = container.NewCommand(ctx, msg, absHelperInnerPath, "helper", args...)
c.Env = append(c.Env, envDoCheck+"=1")
c.Bind(check.MustAbs(os.Args[0]), absHelperInnerPath, 0)

View File

@ -11,6 +11,7 @@ import (
"syscall"
"hakurei.app/container/seccomp"
"hakurei.app/message"
)
type osFile interface {
@ -37,7 +38,7 @@ type syscallDispatcher interface {
setNoNewPrivs() error
// lastcap provides [LastCap].
lastcap(msg Msg) uintptr
lastcap(msg message.Msg) uintptr
// capset provides capset.
capset(hdrp *capHeader, datap *[2]capData) error
// capBoundingSetDrop provides capBoundingSetDrop.
@ -52,9 +53,9 @@ type syscallDispatcher interface {
receive(key string, e any, fdp *uintptr) (closeFunc func() error, err error)
// bindMount provides procPaths.bindMount.
bindMount(msg Msg, source, target string, flags uintptr) error
bindMount(msg message.Msg, source, target string, flags uintptr) error
// remount provides procPaths.remount.
remount(msg Msg, target string, flags uintptr) error
remount(msg message.Msg, target string, flags uintptr) error
// mountTmpfs provides mountTmpfs.
mountTmpfs(fsname, target string, flags uintptr, size int, perm os.FileMode) error
// ensureFile provides ensureFile.
@ -122,11 +123,11 @@ type syscallDispatcher interface {
wait4(pid int, wstatus *syscall.WaitStatus, options int, rusage *syscall.Rusage) (wpid int, err error)
// printf provides the Printf method of [log.Logger].
printf(msg Msg, format string, v ...any)
printf(msg message.Msg, format string, v ...any)
// fatal provides the Fatal method of [log.Logger]
fatal(msg Msg, v ...any)
fatal(msg message.Msg, v ...any)
// fatalf provides the Fatalf method of [log.Logger]
fatalf(msg Msg, format string, v ...any)
fatalf(msg message.Msg, format string, v ...any)
}
// direct implements syscallDispatcher on the current kernel.
@ -140,7 +141,7 @@ func (direct) setPtracer(pid uintptr) error { return SetPtracer(pid) }
func (direct) setDumpable(dumpable uintptr) error { return SetDumpable(dumpable) }
func (direct) setNoNewPrivs() error { return SetNoNewPrivs() }
func (direct) lastcap(msg Msg) uintptr { return LastCap(msg) }
func (direct) lastcap(msg message.Msg) uintptr { return LastCap(msg) }
func (direct) capset(hdrp *capHeader, datap *[2]capData) error { return capset(hdrp, datap) }
func (direct) capBoundingSetDrop(cap uintptr) error { return capBoundingSetDrop(cap) }
func (direct) capAmbientClearAll() error { return capAmbientClearAll() }
@ -150,10 +151,10 @@ func (direct) receive(key string, e any, fdp *uintptr) (func() error, error) {
return Receive(key, e, fdp)
}
func (direct) bindMount(msg Msg, source, target string, flags uintptr) error {
func (direct) bindMount(msg message.Msg, source, target string, flags uintptr) error {
return hostProc.bindMount(msg, source, target, flags)
}
func (direct) remount(msg Msg, target string, flags uintptr) error {
func (direct) remount(msg message.Msg, target string, flags uintptr) error {
return hostProc.remount(msg, target, flags)
}
func (k direct) mountTmpfs(fsname, target string, flags uintptr, size int, perm os.FileMode) error {
@ -221,6 +222,6 @@ func (direct) wait4(pid int, wstatus *syscall.WaitStatus, options int, rusage *s
return syscall.Wait4(pid, wstatus, options, rusage)
}
func (direct) printf(msg Msg, format string, v ...any) { msg.GetLogger().Printf(format, v...) }
func (direct) fatal(msg Msg, v ...any) { msg.GetLogger().Fatal(v...) }
func (direct) fatalf(msg Msg, format string, v ...any) { msg.GetLogger().Fatalf(format, v...) }
func (direct) printf(msg message.Msg, format string, v ...any) { msg.GetLogger().Printf(format, v...) }
func (direct) fatal(msg message.Msg, v ...any) { msg.GetLogger().Fatal(v...) }
func (direct) fatalf(msg message.Msg, format string, v ...any) { msg.GetLogger().Fatalf(format, v...) }

View File

@ -18,6 +18,7 @@ import (
"hakurei.app/container/seccomp"
"hakurei.app/container/stub"
"hakurei.app/message"
)
type opValidTestCase struct {
@ -329,7 +330,7 @@ func (k *kstub) setDumpable(dumpable uintptr) error {
}
func (k *kstub) setNoNewPrivs() error { k.Helper(); return k.Expects("setNoNewPrivs").Err }
func (k *kstub) lastcap(msg Msg) uintptr {
func (k *kstub) lastcap(msg message.Msg) uintptr {
k.Helper()
k.checkMsg(msg)
return k.Expects("lastcap").Ret.(uintptr)
@ -409,7 +410,7 @@ func (k *kstub) receive(key string, e any, fdp *uintptr) (closeFunc func() error
return
}
func (k *kstub) bindMount(msg Msg, source, target string, flags uintptr) error {
func (k *kstub) bindMount(msg message.Msg, source, target string, flags uintptr) error {
k.Helper()
k.checkMsg(msg)
return k.Expects("bindMount").Error(
@ -418,7 +419,7 @@ func (k *kstub) bindMount(msg Msg, source, target string, flags uintptr) error {
stub.CheckArg(k.Stub, "flags", flags, 2))
}
func (k *kstub) remount(msg Msg, target string, flags uintptr) error {
func (k *kstub) remount(msg message.Msg, target string, flags uintptr) error {
k.Helper()
k.checkMsg(msg)
return k.Expects("remount").Error(
@ -702,7 +703,7 @@ func (k *kstub) wait4(pid int, wstatus *syscall.WaitStatus, options int, rusage
return
}
func (k *kstub) printf(_ Msg, format string, v ...any) {
func (k *kstub) printf(_ message.Msg, format string, v ...any) {
k.Helper()
if k.Expects("printf").Error(
stub.CheckArg(k.Stub, "format", format, 0),
@ -711,7 +712,7 @@ func (k *kstub) printf(_ Msg, format string, v ...any) {
}
}
func (k *kstub) fatal(_ Msg, v ...any) {
func (k *kstub) fatal(_ message.Msg, v ...any) {
k.Helper()
if k.Expects("fatal").Error(
stub.CheckArgReflect(k.Stub, "v", v, 0)) != nil {
@ -720,7 +721,7 @@ func (k *kstub) fatal(_ Msg, v ...any) {
panic(stub.PanicExit)
}
func (k *kstub) fatalf(_ Msg, format string, v ...any) {
func (k *kstub) fatalf(_ message.Msg, format string, v ...any) {
k.Helper()
if k.Expects("fatalf").Error(
stub.CheckArg(k.Stub, "format", format, 0),
@ -730,7 +731,7 @@ func (k *kstub) fatalf(_ Msg, format string, v ...any) {
panic(stub.PanicExit)
}
func (k *kstub) checkMsg(msg Msg) {
func (k *kstub) checkMsg(msg message.Msg) {
k.Helper()
var target *kstub

View File

@ -3,6 +3,8 @@ package container
import (
"os"
"sync"
"hakurei.app/message"
)
var (
@ -10,7 +12,7 @@ var (
executableOnce sync.Once
)
func copyExecutable(msg Msg) {
func copyExecutable(msg message.Msg) {
if name, err := os.Executable(); err != nil {
msg.BeforeExit()
msg.GetLogger().Fatalf("cannot read executable path: %v", err)
@ -19,7 +21,7 @@ func copyExecutable(msg Msg) {
}
}
func MustExecutable(msg Msg) string {
func MustExecutable(msg message.Msg) string {
executableOnce.Do(func() { copyExecutable(msg) })
return executable
}

View File

@ -5,11 +5,12 @@ import (
"testing"
"hakurei.app/container"
"hakurei.app/message"
)
func TestExecutable(t *testing.T) {
for i := 0; i < 16; i++ {
if got := container.MustExecutable(container.NewMsg(nil)); got != os.Args[0] {
if got := container.MustExecutable(message.NewMsg(nil)); got != os.Args[0] {
t.Errorf("MustExecutable: %q, want %q",
got, os.Args[0])
}

View File

@ -14,6 +14,7 @@ import (
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp"
"hakurei.app/message"
)
const (
@ -61,7 +62,7 @@ type (
setupState struct {
nonrepeatable uintptr
*Params
Msg
message.Msg
}
)
@ -95,14 +96,14 @@ type initParams struct {
}
// Init is called by [TryArgv0] if the current process is the container init.
func Init(msg Msg) {
func Init(msg message.Msg) {
if msg == nil {
panic("attempting to call initEntrypoint with nil msg")
}
initEntrypoint(direct{}, msg)
}
func initEntrypoint(k syscallDispatcher, msg Msg) {
func initEntrypoint(k syscallDispatcher, msg message.Msg) {
k.lockOSThread()
if k.getpid() != 1 {
@ -125,7 +126,7 @@ func initEntrypoint(k syscallDispatcher, msg Msg) {
k.fatal(msg, "invalid setup descriptor")
}
if errors.Is(err, ErrReceiveEnv) {
k.fatal(msg, "HAKUREI_SETUP not set")
k.fatal(msg, setupEnv+" not set")
}
k.fatalf(msg, "cannot decode init setup payload: %v", err)
@ -448,11 +449,11 @@ const initName = "init"
// TryArgv0 calls [Init] if the last element of argv0 is "init".
// If a nil msg is passed, the system logger is used instead.
func TryArgv0(msg Msg) {
func TryArgv0(msg message.Msg) {
if msg == nil {
log.SetPrefix(initName + ": ")
log.SetFlags(0)
msg = NewMsg(log.Default())
msg = message.NewMsg(log.Default())
}
if len(os.Args) > 0 && path.Base(os.Args[0]) == initName {

View File

@ -7,6 +7,7 @@ import (
. "syscall"
"hakurei.app/container/vfs"
"hakurei.app/message"
)
/*
@ -87,7 +88,7 @@ const (
)
// bindMount mounts source on target and recursively applies flags if MS_REC is set.
func (p *procPaths) bindMount(msg Msg, source, target string, flags uintptr) error {
func (p *procPaths) bindMount(msg message.Msg, source, target string, flags uintptr) error {
// syscallDispatcher.bindMount and procPaths.remount must not be called from this function
if err := p.k.mount(source, target, FstypeNULL, MS_SILENT|MS_BIND|flags&MS_REC, zeroString); err != nil {
@ -97,7 +98,7 @@ func (p *procPaths) bindMount(msg Msg, source, target string, flags uintptr) err
}
// remount applies flags on target, recursively if MS_REC is set.
func (p *procPaths) remount(msg Msg, target string, flags uintptr) error {
func (p *procPaths) remount(msg message.Msg, target string, flags uintptr) error {
// syscallDispatcher methods bindMount, remount must not be called from this function
var targetFinal string
@ -159,7 +160,7 @@ func (p *procPaths) remount(msg Msg, target string, flags uintptr) error {
}
// remountWithFlags remounts mount point described by [vfs.MountInfoNode].
func remountWithFlags(k syscallDispatcher, msg Msg, n *vfs.MountInfoNode, mf uintptr) error {
func remountWithFlags(k syscallDispatcher, msg message.Msg, n *vfs.MountInfoNode, mf uintptr) error {
// syscallDispatcher methods bindMount, remount must not be called from this function
kf, unmatched := n.Flags()

View File

@ -7,6 +7,7 @@ import (
"sync"
"hakurei.app/container/fhs"
"hakurei.app/message"
)
var (
@ -23,7 +24,7 @@ const (
kernelCapLastCapPath = fhs.ProcSys + "kernel/cap_last_cap"
)
func mustReadSysctl(msg Msg) {
func mustReadSysctl(msg message.Msg) {
sysctlOnce.Do(func() {
if v, err := os.ReadFile(kernelOverflowuidPath); err != nil {
msg.GetLogger().Fatalf("cannot read %q: %v", kernelOverflowuidPath, err)
@ -45,6 +46,6 @@ func mustReadSysctl(msg Msg) {
})
}
func OverflowUid(msg Msg) int { mustReadSysctl(msg); return kernelOverflowuid }
func OverflowGid(msg Msg) int { mustReadSysctl(msg); return kernelOverflowgid }
func LastCap(msg Msg) uintptr { mustReadSysctl(msg); return uintptr(kernelCapLastCap) }
func OverflowUid(msg message.Msg) int { mustReadSysctl(msg); return kernelOverflowuid }
func OverflowGid(msg message.Msg) int { mustReadSysctl(msg); return kernelOverflowgid }
func LastCap(msg message.Msg) uintptr { mustReadSysctl(msg); return uintptr(kernelCapLastCap) }

View File

@ -12,12 +12,13 @@ import (
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/helper/proc"
"hakurei.app/message"
)
// New initialises a Helper instance with wt as the null-terminated argument writer.
func New(
ctx context.Context,
msg container.Msg,
msg message.Msg,
pathname *check.Absolute, name string,
wt io.WriterTo,
stat bool,

View File

@ -5,8 +5,8 @@ import (
"slices"
"testing"
"hakurei.app/container"
"hakurei.app/hst"
"hakurei.app/message"
)
func TestBadInterfaceError(t *testing.T) {
@ -26,10 +26,10 @@ func TestBadInterfaceError(t *testing.T) {
if gotError := tc.err.Error(); gotError != tc.want {
t.Errorf("Error: %s, want %s", gotError, tc.want)
}
if gotMessage, ok := container.GetErrorMessage(tc.err); !ok {
t.Error("GetErrorMessage: ok = false")
if gotMessage, ok := message.GetMessage(tc.err); !ok {
t.Error("GetMessage: ok = false")
} else if gotMessage != tc.want {
t.Errorf("GetErrorMessage: %s, want %s", gotMessage, tc.want)
t.Errorf("GetMessage: %s, want %s", gotMessage, tc.want)
}
})
}

View File

@ -8,9 +8,9 @@ import (
"syscall"
"testing"
"hakurei.app/container"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/message"
)
func TestAppError(t *testing.T) {
@ -65,14 +65,14 @@ func TestAppError(t *testing.T) {
})
t.Run("message", func(t *testing.T) {
gotMessage, gotMessageOk := container.GetErrorMessage(tc.err)
gotMessage, gotMessageOk := message.GetMessage(tc.err)
if want := tc.message != "\x00"; gotMessageOk != want {
t.Errorf("GetErrorMessage: ok = %v, want %v", gotMessage, want)
t.Errorf("GetMessage: ok = %v, want %v", gotMessage, want)
}
if gotMessageOk {
if gotMessage != tc.message {
t.Errorf("GetErrorMessage: %s, want %s", gotMessage, tc.message)
t.Errorf("GetMessage: %s, want %s", gotMessage, tc.message)
}
}
})

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()))
}

View File

@ -13,6 +13,7 @@ import (
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp"
"hakurei.app/message"
)
const (
@ -25,7 +26,7 @@ var (
msgStaticGlibc = []byte("not a dynamic executable")
)
func Exec(ctx context.Context, msg container.Msg, p string) ([]*Entry, error) {
func Exec(ctx context.Context, msg message.Msg, p string) ([]*Entry, error) {
c, cancel := context.WithTimeout(ctx, lddTimeout)
defer cancel()

View File

@ -1,4 +1,5 @@
package container
// Package message provides interfaces and a base implementation for extended reporting on top of [log.Logger]
package message
import (
"errors"
@ -6,19 +7,19 @@ import (
"sync/atomic"
)
// MessageError is an error with a user-facing message.
type MessageError interface {
// Error is an error with a user-facing message.
type Error interface {
// Message returns a user-facing error message.
Message() string
error
}
// GetErrorMessage returns whether an error implements [MessageError], and the message if it does.
func GetErrorMessage(err error) (string, bool) {
var e MessageError
// GetMessage returns whether an error implements [Error], and the message if it does.
func GetMessage(err error) (string, bool) {
var e Error
if !errors.As(err, &e) || e == nil {
return zeroString, false
return "", false
}
return e.Message(), true
}

View File

@ -1,4 +1,4 @@
package container_test
package message_test
import (
"bytes"
@ -11,6 +11,7 @@ import (
"hakurei.app/container"
"hakurei.app/container/stub"
"hakurei.app/message"
)
func TestMessageError(t *testing.T) {
@ -29,12 +30,12 @@ func TestMessageError(t *testing.T) {
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got, ok := container.GetErrorMessage(tc.err)
got, ok := message.GetMessage(tc.err)
if got != tc.want {
t.Errorf("GetErrorMessage: %q, want %q", got, tc.want)
t.Errorf("GetMessage: %q, want %q", got, tc.want)
}
if ok != tc.wantOk {
t.Errorf("GetErrorMessage: ok = %v, want %v", ok, tc.wantOk)
t.Errorf("GetMessage: ok = %v, want %v", ok, tc.wantOk)
}
})
}
@ -46,9 +47,9 @@ func TestDefaultMsg(t *testing.T) {
t.Run("logger", func(t *testing.T) {
t.Run("nil", func(t *testing.T) {
got := container.NewMsg(nil).GetLogger()
got := message.NewMsg(nil).GetLogger()
if out := got.Writer().(*container.Suspendable).Downstream; out != log.Writer() {
if out := got.Writer().(*message.Suspendable).Downstream; out != log.Writer() {
t.Errorf("GetLogger: Downstream = %#v", out)
}
@ -59,13 +60,13 @@ func TestDefaultMsg(t *testing.T) {
t.Run("takeover", func(t *testing.T) {
l := log.New(io.Discard, "\x00", 0xdeadbeef)
got := container.NewMsg(l)
got := message.NewMsg(l)
if logger := got.GetLogger(); logger != l {
t.Errorf("GetLogger: %#v, want %#v", logger, l)
}
if ds := l.Writer().(*container.Suspendable).Downstream; ds != io.Discard {
if ds := l.Writer().(*message.Suspendable).Downstream; ds != io.Discard {
t.Errorf("GetLogger: Downstream = %#v", ds)
}
})
@ -78,93 +79,93 @@ func TestDefaultMsg(t *testing.T) {
pt, next []byte
err error
f func(t *testing.T, msg container.Msg)
f func(t *testing.T, msg message.Msg)
}{
{"zero verbose", nil, nil, nil, func(t *testing.T, msg container.Msg) {
{"zero verbose", nil, nil, nil, func(t *testing.T, msg message.Msg) {
if msg.IsVerbose() {
t.Error("IsVerbose unexpected true")
}
}},
{"swap false", nil, nil, nil, func(t *testing.T, msg container.Msg) {
{"swap false", nil, nil, nil, func(t *testing.T, msg message.Msg) {
if msg.SwapVerbose(false) {
t.Error("SwapVerbose unexpected true")
}
}},
{"write discard", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
{"write discard", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
msg.Verbose("\x00")
msg.Verbosef("\x00")
}},
{"verbose false", nil, nil, nil, func(t *testing.T, msg container.Msg) {
{"verbose false", nil, nil, nil, func(t *testing.T, msg message.Msg) {
if msg.IsVerbose() {
t.Error("IsVerbose unexpected true")
}
}},
{"swap true", nil, nil, nil, func(t *testing.T, msg container.Msg) {
{"swap true", nil, nil, nil, func(t *testing.T, msg message.Msg) {
if msg.SwapVerbose(true) {
t.Error("SwapVerbose unexpected true")
}
}},
{"write verbose", []byte("test: \x00\n"), nil, nil, func(_ *testing.T, msg container.Msg) {
{"write verbose", []byte("test: \x00\n"), nil, nil, func(_ *testing.T, msg message.Msg) {
msg.Verbose("\x00")
}},
{"write verbosef", []byte(`test: "\x00"` + "\n"), nil, nil, func(_ *testing.T, msg container.Msg) {
{"write verbosef", []byte(`test: "\x00"` + "\n"), nil, nil, func(_ *testing.T, msg message.Msg) {
msg.Verbosef("%q", "\x00")
}},
{"verbose true", nil, nil, nil, func(t *testing.T, msg container.Msg) {
{"verbose true", nil, nil, nil, func(t *testing.T, msg message.Msg) {
if !msg.IsVerbose() {
t.Error("IsVerbose unexpected false")
}
}},
{"resume noop", nil, nil, nil, func(t *testing.T, msg container.Msg) {
{"resume noop", nil, nil, nil, func(t *testing.T, msg message.Msg) {
if msg.Resume() {
t.Error("Resume unexpected success")
}
}},
{"beforeExit noop", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
{"beforeExit noop", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
msg.BeforeExit()
}},
{"beforeExit suspend", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
{"beforeExit suspend", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
msg.Suspend()
}},
{"beforeExit message", []byte("test: beforeExit reached on suspended output\n"), nil, nil, func(_ *testing.T, msg container.Msg) {
{"beforeExit message", []byte("test: beforeExit reached on suspended output\n"), nil, nil, func(_ *testing.T, msg message.Msg) {
msg.BeforeExit()
}},
{"post beforeExit resume noop", nil, nil, nil, func(t *testing.T, msg container.Msg) {
{"post beforeExit resume noop", nil, nil, nil, func(t *testing.T, msg message.Msg) {
if msg.Resume() {
t.Error("Resume unexpected success")
}
}},
{"suspend", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
{"suspend", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
msg.Suspend()
}},
{"suspend write", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
{"suspend write", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
msg.GetLogger().Print("\x00")
}},
{"resume error", []byte("test: \x00\n"), []byte("test: cannot dump buffer on resume: unique error 0 injected by the test suite\n"), stub.UniqueError(0), func(t *testing.T, msg container.Msg) {
{"resume error", []byte("test: \x00\n"), []byte("test: cannot dump buffer on resume: unique error 0 injected by the test suite\n"), stub.UniqueError(0), func(t *testing.T, msg message.Msg) {
if !msg.Resume() {
t.Error("Resume unexpected failure")
}
}},
{"suspend drop", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
{"suspend drop", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
msg.Suspend()
}},
{"suspend write fill", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
{"suspend write fill", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
msg.GetLogger().Print(strings.Repeat("\x00", suspendBufMax))
}},
{"resume dropped", append([]byte("test: "), bytes.Repeat([]byte{0}, suspendBufMax-6)...), []byte("test: dropped 7 bytes while output is suspended\n"), nil, func(t *testing.T, msg container.Msg) {
{"resume dropped", append([]byte("test: "), bytes.Repeat([]byte{0}, suspendBufMax-6)...), []byte("test: dropped 7 bytes while output is suspended\n"), nil, func(t *testing.T, msg message.Msg) {
if !msg.Resume() {
t.Error("Resume unexpected failure")
}
}},
}
msg := container.NewMsg(log.New(&dw, "test: ", 0))
msg := message.NewMsg(log.New(&dw, "test: ", 0))
for _, step := range steps {
// these share the same writer, so cannot be subtests
t.Logf("running step %q", step.name)

View File

@ -1,4 +1,4 @@
package container
package message
import (
"bytes"

View File

@ -1,4 +1,4 @@
package container_test
package message_test
import (
"bytes"
@ -8,8 +8,8 @@ import (
"syscall"
"testing"
"hakurei.app/container"
"hakurei.app/container/stub"
"hakurei.app/message"
)
func TestSuspendable(t *testing.T) {
@ -74,7 +74,7 @@ func TestSuspendable(t *testing.T) {
var dw expectWriter
w := container.Suspendable{Downstream: &dw}
w := message.Suspendable{Downstream: &dw}
for _, step := range steps {
// these share the same writer, so cannot be subtests
t.Logf("writing step %q", step.name)

View File

@ -11,8 +11,8 @@ import (
"testing"
"time"
"hakurei.app/container"
"hakurei.app/helper"
"hakurei.app/message"
"hakurei.app/system/dbus"
)
@ -93,9 +93,9 @@ func testProxyFinaliseStartWaitCloseString(t *testing.T, useSandbox bool) {
t.Run("invalid start", func(t *testing.T) {
if !useSandbox {
p = dbus.NewDirect(t.Context(), container.NewMsg(nil), nil, nil)
p = dbus.NewDirect(t.Context(), message.NewMsg(nil), nil, nil)
} else {
p = dbus.New(t.Context(), container.NewMsg(nil), nil, nil)
p = dbus.New(t.Context(), message.NewMsg(nil), nil, nil)
}
if err := p.Start(); !errors.Is(err, syscall.ENOTRECOVERABLE) {
@ -128,9 +128,9 @@ func testProxyFinaliseStartWaitCloseString(t *testing.T, useSandbox bool) {
defer cancel()
output := new(strings.Builder)
if !useSandbox {
p = dbus.NewDirect(ctx, container.NewMsg(nil), final, output)
p = dbus.NewDirect(ctx, message.NewMsg(nil), final, output)
} else {
p = dbus.New(ctx, container.NewMsg(nil), final, output)
p = dbus.New(ctx, message.NewMsg(nil), final, output)
}
t.Run("invalid wait", func(t *testing.T) {

View File

@ -4,11 +4,11 @@ import (
"context"
"io"
"hakurei.app/container"
"hakurei.app/message"
)
// NewDirect returns a new instance of [Proxy] with its sandbox disabled.
func NewDirect(ctx context.Context, msg container.Msg, final *Final, output io.Writer) *Proxy {
func NewDirect(ctx context.Context, msg message.Msg, final *Final, output io.Writer) *Proxy {
p := New(ctx, msg, final, output)
p.useSandbox = false
return p

View File

@ -6,9 +6,9 @@ import (
"sync"
"syscall"
"hakurei.app/container"
"hakurei.app/helper"
"hakurei.app/hst"
"hakurei.app/message"
)
// ProxyName is the file name or path to the proxy program.
@ -19,7 +19,7 @@ var ProxyName = "xdg-dbus-proxy"
type Proxy struct {
helper helper.Helper
ctx context.Context
msg container.Msg
msg message.Msg
cancel context.CancelCauseFunc
cause func() error
@ -100,6 +100,6 @@ func Finalise(sessionBus, systemBus ProxyPair, session, system *hst.BusConfig) (
}
// New returns a new instance of [Proxy].
func New(ctx context.Context, msg container.Msg, final *Final, output io.Writer) *Proxy {
func New(ctx context.Context, msg message.Msg, final *Final, output io.Writer) *Proxy {
return &Proxy{name: ProxyName, ctx: ctx, msg: msg, final: final, output: output, useSandbox: true}
}

View File

@ -6,6 +6,7 @@ import (
"os"
"hakurei.app/container"
"hakurei.app/message"
)
// OpError is returned by [I.Commit] and [I.Revert].
@ -70,14 +71,14 @@ func printJoinedError(println func(v ...any), fallback string, err error) {
error
}
if !errors.As(err, &joinErr) {
if m, ok := container.GetErrorMessage(err); ok {
if m, ok := message.GetMessage(err); ok {
println(m)
} else {
println(fallback, err)
}
} else {
for _, err = range joinErr.Unwrap() {
if m, ok := container.GetErrorMessage(err); ok {
if m, ok := message.GetMessage(err); ok {
println(m)
} else {
println(err.Error())

View File

@ -9,6 +9,7 @@ import (
"testing"
"hakurei.app/container"
"hakurei.app/message"
)
func TestOpError(t *testing.T) {
@ -64,13 +65,13 @@ func TestOpError(t *testing.T) {
})
t.Run("msg", func(t *testing.T) {
if got, ok := container.GetErrorMessage(tc.err); !ok {
if got, ok := message.GetMessage(tc.err); !ok {
if tc.msg != "" {
t.Errorf("GetErrorMessage: err does not implement MessageError")
t.Errorf("GetMessage: err does not implement MessageError")
}
return
} else if got != tc.msg {
t.Errorf("GetErrorMessage: %q, want %q", got, tc.msg)
t.Errorf("GetMessage: %q, want %q", got, tc.msg)
}
})
})

View File

@ -6,8 +6,8 @@ import (
"errors"
"strings"
"hakurei.app/container"
"hakurei.app/hst"
"hakurei.app/message"
)
const (
@ -68,7 +68,7 @@ func TypeString(e hst.Enablement) string {
}
// New returns the address of a new [I] targeting uid.
func New(ctx context.Context, msg container.Msg, uid int) (sys *I) {
func New(ctx context.Context, msg message.Msg, uid int) (sys *I) {
if ctx == nil || msg == nil || uid < 0 {
panic("invalid call to New")
}
@ -89,7 +89,7 @@ type I struct {
// the behaviour of Revert is only defined for up to one call
reverted bool
msg container.Msg
msg message.Msg
syscallDispatcher
}

View File

@ -8,10 +8,10 @@ import (
"strconv"
"testing"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/message"
"hakurei.app/system/internal/xcb"
)
@ -74,7 +74,7 @@ func TestNew(t *testing.T) {
t.Errorf("recover: %v, want %v", r, want)
}
}()
New(nil, container.NewMsg(nil), 0)
New(nil, message.NewMsg(nil), 0)
})
t.Run("msg", func(t *testing.T) {
@ -94,11 +94,11 @@ func TestNew(t *testing.T) {
t.Errorf("recover: %v, want %v", r, want)
}
}()
New(t.Context(), container.NewMsg(nil), -1)
New(t.Context(), message.NewMsg(nil), -1)
})
})
sys := New(t.Context(), container.NewMsg(nil), 0xdeadbeef)
sys := New(t.Context(), message.NewMsg(nil), 0xdeadbeef)
if sys.ctx == nil {
t.Error("New: ctx = nil")
}
@ -115,51 +115,51 @@ func TestEqual(t *testing.T) {
want bool
}{
{"simple UID",
New(t.Context(), container.NewMsg(nil), 150),
New(t.Context(), container.NewMsg(nil), 150),
New(t.Context(), message.NewMsg(nil), 150),
New(t.Context(), message.NewMsg(nil), 150),
true},
{"simple UID differ",
New(t.Context(), container.NewMsg(nil), 150),
New(t.Context(), container.NewMsg(nil), 151),
New(t.Context(), message.NewMsg(nil), 150),
New(t.Context(), message.NewMsg(nil), 151),
false},
{"simple UID nil",
New(t.Context(), container.NewMsg(nil), 150),
New(t.Context(), message.NewMsg(nil), 150),
nil,
false},
{"op length mismatch",
New(t.Context(), container.NewMsg(nil), 150).
New(t.Context(), message.NewMsg(nil), 150).
ChangeHosts("chronos"),
New(t.Context(), container.NewMsg(nil), 150).
New(t.Context(), message.NewMsg(nil), 150).
ChangeHosts("chronos").
Ensure(m("/run"), 0755),
false},
{"op value mismatch",
New(t.Context(), container.NewMsg(nil), 150).
New(t.Context(), message.NewMsg(nil), 150).
ChangeHosts("chronos").
Ensure(m("/run"), 0644),
New(t.Context(), container.NewMsg(nil), 150).
New(t.Context(), message.NewMsg(nil), 150).
ChangeHosts("chronos").
Ensure(m("/run"), 0755),
false},
{"op type mismatch",
New(t.Context(), container.NewMsg(nil), 150).
New(t.Context(), message.NewMsg(nil), 150).
ChangeHosts("chronos").
CopyFile(new([]byte), m("/home/ophestra/xdg/config/pulse/cookie"), 0, 256),
New(t.Context(), container.NewMsg(nil), 150).
New(t.Context(), message.NewMsg(nil), 150).
ChangeHosts("chronos").
Ensure(m("/run"), 0755),
false},
{"op equals",
New(t.Context(), container.NewMsg(nil), 150).
New(t.Context(), message.NewMsg(nil), 150).
ChangeHosts("chronos").
Ensure(m("/run"), 0755),
New(t.Context(), container.NewMsg(nil), 150).
New(t.Context(), message.NewMsg(nil), 150).
ChangeHosts("chronos").
Ensure(m("/run"), 0755),
true},