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
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:
parent
df9b77b077
commit
87b5c30ef6
@ -15,17 +15,17 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/command"
|
"hakurei.app/command"
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal"
|
"hakurei.app/internal"
|
||||||
"hakurei.app/internal/app"
|
"hakurei.app/internal/app"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/message"
|
||||||
"hakurei.app/system/dbus"
|
"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 (
|
var (
|
||||||
flagVerbose bool
|
flagVerbose bool
|
||||||
flagJSON bool
|
flagJSON bool
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/command"
|
"hakurei.app/command"
|
||||||
"hakurei.app/container"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHelp(t *testing.T) {
|
func TestHelp(t *testing.T) {
|
||||||
@ -69,7 +69,7 @@ Flags:
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
out := new(bytes.Buffer)
|
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) {
|
if err := c.Parse(tc.args); !errors.Is(err, command.ErrHelp) && !errors.Is(err, flag.ErrHelp) {
|
||||||
t.Errorf("Parse: error = %v; want %v",
|
t.Errorf("Parse: error = %v; want %v",
|
||||||
err, command.ErrHelp)
|
err, command.ErrHelp)
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -31,7 +32,7 @@ func main() {
|
|||||||
|
|
||||||
log.SetPrefix("hakurei: ")
|
log.SetPrefix("hakurei: ")
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
msg := container.NewMsg(log.Default())
|
msg := message.NewMsg(log.Default())
|
||||||
|
|
||||||
early := earlyHardeningErrs{
|
early := earlyHardeningErrs{
|
||||||
yamaLSM: container.SetPtracer(0),
|
yamaLSM: container.SetPtracer(0),
|
||||||
|
@ -10,13 +10,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/app"
|
"hakurei.app/internal/app"
|
||||||
"hakurei.app/internal/app/state"
|
"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
|
var r io.Reader
|
||||||
config = new(hst.Config)
|
config = new(hst.Config)
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ func tryPath(msg container.Msg, name string) (config *hst.Config) {
|
|||||||
return
|
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 v, err := strconv.Atoi(name); err != nil {
|
||||||
if !errors.Is(err, strconv.ErrSyntax) {
|
if !errors.Is(err, strconv.ErrSyntax) {
|
||||||
msg.Verbosef("name cannot be interpreted as int64: %v", err)
|
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
|
likePrefix := false
|
||||||
if len(name) <= 32 {
|
if len(name) <= 32 {
|
||||||
likePrefix = true
|
likePrefix = true
|
||||||
|
@ -11,10 +11,10 @@ import (
|
|||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/app"
|
"hakurei.app/internal/app"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func printShowSystem(output io.Writer, short, flagJSON bool) {
|
func printShowSystem(output io.Writer, short, flagJSON bool) {
|
||||||
@ -56,7 +56,7 @@ func printShowInstance(
|
|||||||
|
|
||||||
if err := config.Validate(); err != nil {
|
if err := config.Validate(); err != nil {
|
||||||
valid = false
|
valid = false
|
||||||
if m, ok := container.GetErrorMessage(err); ok {
|
if m, ok := message.GetMessage(err); ok {
|
||||||
mustPrint(output, "Error: "+m+"!\n\n")
|
mustPrint(output, "Error: "+m+"!\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,10 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/command"
|
"hakurei.app/command"
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -24,7 +24,7 @@ var (
|
|||||||
func main() {
|
func main() {
|
||||||
log.SetPrefix("hpkg: ")
|
log.SetPrefix("hpkg: ")
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
msg := container.NewMsg(log.Default())
|
msg := message.NewMsg(log.Default())
|
||||||
|
|
||||||
if err := os.Setenv("SHELL", pathShell.String()); err != nil {
|
if err := os.Setenv("SHELL", pathShell.String()); err != nil {
|
||||||
log.Fatalf("cannot set $SHELL: %v", err)
|
log.Fatalf("cannot set $SHELL: %v", err)
|
||||||
|
@ -7,10 +7,10 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
const bash = "bash"
|
const bash = "bash"
|
||||||
@ -52,7 +52,7 @@ func lookPath(file string) string {
|
|||||||
|
|
||||||
var beforeRunFail = new(atomic.Pointer[func()])
|
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)
|
msg.Verbosef("spawning process: %q %q", name, arg)
|
||||||
cmd := exec.Command(name, arg...)
|
cmd := exec.Command(name, arg...)
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
|
@ -9,14 +9,14 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal"
|
"hakurei.app/internal"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var hakureiPath = internal.MustHakureiPath()
|
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 (
|
var (
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
st io.WriteCloser
|
st io.WriteCloser
|
||||||
|
@ -5,15 +5,15 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func withNixDaemon(
|
func withNixDaemon(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
msg container.Msg,
|
msg message.Msg,
|
||||||
action string, command []string, net bool, updateConfig func(config *hst.Config) *hst.Config,
|
action string, command []string, net bool, updateConfig func(config *hst.Config) *hst.Config,
|
||||||
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(),
|
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(),
|
||||||
) {
|
) {
|
||||||
@ -64,7 +64,7 @@ func withNixDaemon(
|
|||||||
|
|
||||||
func withCacheDir(
|
func withCacheDir(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
msg container.Msg,
|
msg message.Msg,
|
||||||
action string, command []string, workDir *check.Absolute,
|
action string, command []string, workDir *check.Absolute,
|
||||||
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func()) {
|
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func()) {
|
||||||
mustRunAppDropShell(ctx, msg, &hst.Config{
|
mustRunAppDropShell(ctx, msg, &hst.Config{
|
||||||
@ -102,7 +102,7 @@ func withCacheDir(
|
|||||||
}, dropShell, beforeFail)
|
}, 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 dropShell {
|
||||||
if config.Container != nil {
|
if config.Container != nil {
|
||||||
config.Container.Args = []string{bash, "-l"}
|
config.Container.Args = []string{bash, "-l"}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() { gob.Register(new(AutoRootOp)) }
|
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.
|
// 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 {
|
switch name {
|
||||||
case "proc", "dev", "tmp", "mnt", "etc":
|
case "proc", "dev", "tmp", "mnt", "etc":
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"hakurei.app/container/bits"
|
"hakurei.app/container/bits"
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAutoRootOp(t *testing.T) {
|
func TestAutoRootOp(t *testing.T) {
|
||||||
@ -195,7 +196,7 @@ func TestIsAutoRootBindable(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
var msg Msg
|
var msg message.Msg
|
||||||
if tc.log {
|
if tc.log {
|
||||||
msg = &kstub{nil, stub.New(t, func(s *stub.Stub[syscallDispatcher]) syscallDispatcher { panic("unreachable") }, stub.Expect{Calls: []stub.Call{
|
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),
|
call("verbose", stub.ExpectArgs{[]any{"got unexpected root entry"}}, nil, nil),
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -52,7 +53,7 @@ type (
|
|||||||
|
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
msg Msg
|
msg message.Msg
|
||||||
Params
|
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.
|
// 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 {
|
if msg == nil {
|
||||||
msg = NewMsg(nil)
|
msg = message.NewMsg(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &Container{ctx: ctx, msg: msg, Params: Params{Ops: new(Ops)}}
|
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.
|
// 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 := New(ctx, msg)
|
||||||
z.Path = pathname
|
z.Path = pathname
|
||||||
z.Args = append([]string{name}, args...)
|
z.Args = append([]string{name}, args...)
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"hakurei.app/container/vfs"
|
"hakurei.app/container/vfs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/ldd"
|
"hakurei.app/ldd"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStartError(t *testing.T) {
|
func TestStartError(t *testing.T) {
|
||||||
@ -152,13 +153,13 @@ func TestStartError(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("msg", func(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 != "" {
|
if tc.msg != "" {
|
||||||
t.Errorf("GetErrorMessage: err does not implement MessageError")
|
t.Errorf("GetMessage: err does not implement MessageError")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else if got != tc.msg {
|
} 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) {
|
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 := container.NewCommand(t.Context(), msg, check.MustAbs("/run/current-system/sw/bin/ldd"), "ldd", "/usr/bin/env")
|
||||||
c.SeccompFlags |= seccomp.AllowMultiarch
|
c.SeccompFlags |= seccomp.AllowMultiarch
|
||||||
c.SeccompRules = seccomp.Preset(
|
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) {
|
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 = container.NewCommand(ctx, msg, absHelperInnerPath, "helper", args...)
|
||||||
c.Env = append(c.Env, envDoCheck+"=1")
|
c.Env = append(c.Env, envDoCheck+"=1")
|
||||||
c.Bind(check.MustAbs(os.Args[0]), absHelperInnerPath, 0)
|
c.Bind(check.MustAbs(os.Args[0]), absHelperInnerPath, 0)
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
type osFile interface {
|
type osFile interface {
|
||||||
@ -37,7 +38,7 @@ type syscallDispatcher interface {
|
|||||||
setNoNewPrivs() error
|
setNoNewPrivs() error
|
||||||
|
|
||||||
// lastcap provides [LastCap].
|
// lastcap provides [LastCap].
|
||||||
lastcap(msg Msg) uintptr
|
lastcap(msg message.Msg) uintptr
|
||||||
// capset provides capset.
|
// capset provides capset.
|
||||||
capset(hdrp *capHeader, datap *[2]capData) error
|
capset(hdrp *capHeader, datap *[2]capData) error
|
||||||
// capBoundingSetDrop provides capBoundingSetDrop.
|
// capBoundingSetDrop provides capBoundingSetDrop.
|
||||||
@ -52,9 +53,9 @@ type syscallDispatcher interface {
|
|||||||
receive(key string, e any, fdp *uintptr) (closeFunc func() error, err error)
|
receive(key string, e any, fdp *uintptr) (closeFunc func() error, err error)
|
||||||
|
|
||||||
// bindMount provides procPaths.bindMount.
|
// 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 provides procPaths.remount.
|
||||||
remount(msg Msg, target string, flags uintptr) error
|
remount(msg message.Msg, target string, flags uintptr) error
|
||||||
// mountTmpfs provides mountTmpfs.
|
// mountTmpfs provides mountTmpfs.
|
||||||
mountTmpfs(fsname, target string, flags uintptr, size int, perm os.FileMode) error
|
mountTmpfs(fsname, target string, flags uintptr, size int, perm os.FileMode) error
|
||||||
// ensureFile provides ensureFile.
|
// 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)
|
wait4(pid int, wstatus *syscall.WaitStatus, options int, rusage *syscall.Rusage) (wpid int, err error)
|
||||||
|
|
||||||
// printf provides the Printf method of [log.Logger].
|
// 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 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 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.
|
// 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) setDumpable(dumpable uintptr) error { return SetDumpable(dumpable) }
|
||||||
func (direct) setNoNewPrivs() error { return SetNoNewPrivs() }
|
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) capset(hdrp *capHeader, datap *[2]capData) error { return capset(hdrp, datap) }
|
||||||
func (direct) capBoundingSetDrop(cap uintptr) error { return capBoundingSetDrop(cap) }
|
func (direct) capBoundingSetDrop(cap uintptr) error { return capBoundingSetDrop(cap) }
|
||||||
func (direct) capAmbientClearAll() error { return capAmbientClearAll() }
|
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)
|
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)
|
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)
|
return hostProc.remount(msg, target, flags)
|
||||||
}
|
}
|
||||||
func (k direct) mountTmpfs(fsname, target string, flags uintptr, size int, perm os.FileMode) error {
|
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)
|
return syscall.Wait4(pid, wstatus, options, rusage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (direct) printf(msg Msg, format string, v ...any) { msg.GetLogger().Printf(format, v...) }
|
func (direct) printf(msg message.Msg, format string, v ...any) { msg.GetLogger().Printf(format, v...) }
|
||||||
func (direct) fatal(msg Msg, v ...any) { msg.GetLogger().Fatal(v...) }
|
func (direct) fatal(msg message.Msg, v ...any) { msg.GetLogger().Fatal(v...) }
|
||||||
func (direct) fatalf(msg Msg, format string, v ...any) { msg.GetLogger().Fatalf(format, v...) }
|
func (direct) fatalf(msg message.Msg, format string, v ...any) { msg.GetLogger().Fatalf(format, v...) }
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
|
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
type opValidTestCase struct {
|
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) 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.Helper()
|
||||||
k.checkMsg(msg)
|
k.checkMsg(msg)
|
||||||
return k.Expects("lastcap").Ret.(uintptr)
|
return k.Expects("lastcap").Ret.(uintptr)
|
||||||
@ -409,7 +410,7 @@ func (k *kstub) receive(key string, e any, fdp *uintptr) (closeFunc func() error
|
|||||||
return
|
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.Helper()
|
||||||
k.checkMsg(msg)
|
k.checkMsg(msg)
|
||||||
return k.Expects("bindMount").Error(
|
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))
|
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.Helper()
|
||||||
k.checkMsg(msg)
|
k.checkMsg(msg)
|
||||||
return k.Expects("remount").Error(
|
return k.Expects("remount").Error(
|
||||||
@ -702,7 +703,7 @@ func (k *kstub) wait4(pid int, wstatus *syscall.WaitStatus, options int, rusage
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kstub) printf(_ Msg, format string, v ...any) {
|
func (k *kstub) printf(_ message.Msg, format string, v ...any) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
if k.Expects("printf").Error(
|
if k.Expects("printf").Error(
|
||||||
stub.CheckArg(k.Stub, "format", format, 0),
|
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()
|
k.Helper()
|
||||||
if k.Expects("fatal").Error(
|
if k.Expects("fatal").Error(
|
||||||
stub.CheckArgReflect(k.Stub, "v", v, 0)) != nil {
|
stub.CheckArgReflect(k.Stub, "v", v, 0)) != nil {
|
||||||
@ -720,7 +721,7 @@ func (k *kstub) fatal(_ Msg, v ...any) {
|
|||||||
panic(stub.PanicExit)
|
panic(stub.PanicExit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kstub) fatalf(_ Msg, format string, v ...any) {
|
func (k *kstub) fatalf(_ message.Msg, format string, v ...any) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
if k.Expects("fatalf").Error(
|
if k.Expects("fatalf").Error(
|
||||||
stub.CheckArg(k.Stub, "format", format, 0),
|
stub.CheckArg(k.Stub, "format", format, 0),
|
||||||
@ -730,7 +731,7 @@ func (k *kstub) fatalf(_ Msg, format string, v ...any) {
|
|||||||
panic(stub.PanicExit)
|
panic(stub.PanicExit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kstub) checkMsg(msg Msg) {
|
func (k *kstub) checkMsg(msg message.Msg) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
var target *kstub
|
var target *kstub
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ package container
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -10,7 +12,7 @@ var (
|
|||||||
executableOnce sync.Once
|
executableOnce sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
func copyExecutable(msg Msg) {
|
func copyExecutable(msg message.Msg) {
|
||||||
if name, err := os.Executable(); err != nil {
|
if name, err := os.Executable(); err != nil {
|
||||||
msg.BeforeExit()
|
msg.BeforeExit()
|
||||||
msg.GetLogger().Fatalf("cannot read executable path: %v", err)
|
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) })
|
executableOnce.Do(func() { copyExecutable(msg) })
|
||||||
return executable
|
return executable
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExecutable(t *testing.T) {
|
func TestExecutable(t *testing.T) {
|
||||||
for i := 0; i < 16; i++ {
|
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",
|
t.Errorf("MustExecutable: %q, want %q",
|
||||||
got, os.Args[0])
|
got, os.Args[0])
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -61,7 +62,7 @@ type (
|
|||||||
setupState struct {
|
setupState struct {
|
||||||
nonrepeatable uintptr
|
nonrepeatable uintptr
|
||||||
*Params
|
*Params
|
||||||
Msg
|
message.Msg
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -95,14 +96,14 @@ type initParams struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init is called by [TryArgv0] if the current process is the container init.
|
// 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 {
|
if msg == nil {
|
||||||
panic("attempting to call initEntrypoint with nil msg")
|
panic("attempting to call initEntrypoint with nil msg")
|
||||||
}
|
}
|
||||||
initEntrypoint(direct{}, msg)
|
initEntrypoint(direct{}, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initEntrypoint(k syscallDispatcher, msg Msg) {
|
func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||||
k.lockOSThread()
|
k.lockOSThread()
|
||||||
|
|
||||||
if k.getpid() != 1 {
|
if k.getpid() != 1 {
|
||||||
@ -125,7 +126,7 @@ func initEntrypoint(k syscallDispatcher, msg Msg) {
|
|||||||
k.fatal(msg, "invalid setup descriptor")
|
k.fatal(msg, "invalid setup descriptor")
|
||||||
}
|
}
|
||||||
if errors.Is(err, ErrReceiveEnv) {
|
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)
|
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".
|
// TryArgv0 calls [Init] if the last element of argv0 is "init".
|
||||||
// If a nil msg is passed, the system logger is used instead.
|
// If a nil msg is passed, the system logger is used instead.
|
||||||
func TryArgv0(msg Msg) {
|
func TryArgv0(msg message.Msg) {
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
log.SetPrefix(initName + ": ")
|
log.SetPrefix(initName + ": ")
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
msg = NewMsg(log.Default())
|
msg = message.NewMsg(log.Default())
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(os.Args) > 0 && path.Base(os.Args[0]) == initName {
|
if len(os.Args) > 0 && path.Base(os.Args[0]) == initName {
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
. "syscall"
|
. "syscall"
|
||||||
|
|
||||||
"hakurei.app/container/vfs"
|
"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.
|
// 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
|
// 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 {
|
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.
|
// 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
|
// syscallDispatcher methods bindMount, remount must not be called from this function
|
||||||
|
|
||||||
var targetFinal string
|
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].
|
// 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
|
// syscallDispatcher methods bindMount, remount must not be called from this function
|
||||||
|
|
||||||
kf, unmatched := n.Flags()
|
kf, unmatched := n.Flags()
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -23,7 +24,7 @@ const (
|
|||||||
kernelCapLastCapPath = fhs.ProcSys + "kernel/cap_last_cap"
|
kernelCapLastCapPath = fhs.ProcSys + "kernel/cap_last_cap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mustReadSysctl(msg Msg) {
|
func mustReadSysctl(msg message.Msg) {
|
||||||
sysctlOnce.Do(func() {
|
sysctlOnce.Do(func() {
|
||||||
if v, err := os.ReadFile(kernelOverflowuidPath); err != nil {
|
if v, err := os.ReadFile(kernelOverflowuidPath); err != nil {
|
||||||
msg.GetLogger().Fatalf("cannot read %q: %v", kernelOverflowuidPath, err)
|
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 OverflowUid(msg message.Msg) int { mustReadSysctl(msg); return kernelOverflowuid }
|
||||||
func OverflowGid(msg Msg) int { mustReadSysctl(msg); return kernelOverflowgid }
|
func OverflowGid(msg message.Msg) int { mustReadSysctl(msg); return kernelOverflowgid }
|
||||||
func LastCap(msg Msg) uintptr { mustReadSysctl(msg); return uintptr(kernelCapLastCap) }
|
func LastCap(msg message.Msg) uintptr { mustReadSysctl(msg); return uintptr(kernelCapLastCap) }
|
||||||
|
@ -12,12 +12,13 @@ import (
|
|||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/helper/proc"
|
"hakurei.app/helper/proc"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New initialises a Helper instance with wt as the null-terminated argument writer.
|
// New initialises a Helper instance with wt as the null-terminated argument writer.
|
||||||
func New(
|
func New(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
msg container.Msg,
|
msg message.Msg,
|
||||||
pathname *check.Absolute, name string,
|
pathname *check.Absolute, name string,
|
||||||
wt io.WriterTo,
|
wt io.WriterTo,
|
||||||
stat bool,
|
stat bool,
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBadInterfaceError(t *testing.T) {
|
func TestBadInterfaceError(t *testing.T) {
|
||||||
@ -26,10 +26,10 @@ func TestBadInterfaceError(t *testing.T) {
|
|||||||
if gotError := tc.err.Error(); gotError != tc.want {
|
if gotError := tc.err.Error(); gotError != tc.want {
|
||||||
t.Errorf("Error: %s, want %s", gotError, tc.want)
|
t.Errorf("Error: %s, want %s", gotError, tc.want)
|
||||||
}
|
}
|
||||||
if gotMessage, ok := container.GetErrorMessage(tc.err); !ok {
|
if gotMessage, ok := message.GetMessage(tc.err); !ok {
|
||||||
t.Error("GetErrorMessage: ok = false")
|
t.Error("GetMessage: ok = false")
|
||||||
} else if gotMessage != tc.want {
|
} else if gotMessage != tc.want {
|
||||||
t.Errorf("GetErrorMessage: %s, want %s", gotMessage, tc.want)
|
t.Errorf("GetMessage: %s, want %s", gotMessage, tc.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAppError(t *testing.T) {
|
func TestAppError(t *testing.T) {
|
||||||
@ -65,14 +65,14 @@ func TestAppError(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("message", func(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 {
|
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 gotMessageOk {
|
||||||
if gotMessage != tc.message {
|
if gotMessage != tc.message {
|
||||||
t.Errorf("GetErrorMessage: %s, want %s", gotMessage, tc.message)
|
t.Errorf("GetMessage: %s, want %s", gotMessage, tc.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -6,13 +6,13 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Main runs an app according to [hst.Config] and terminates. Main does not return.
|
// 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
|
var id state.ID
|
||||||
if err := state.NewAppID(&id); err != nil {
|
if err := state.NewAppID(&id); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -23,12 +23,13 @@ import (
|
|||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/message"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
"hakurei.app/system/acl"
|
"hakurei.app/system/acl"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestApp(t *testing.T) {
|
func TestApp(t *testing.T) {
|
||||||
msg := container.NewMsg(nil)
|
msg := message.NewMsg(nil)
|
||||||
msg.SwapVerbose(testing.Verbose())
|
msg.SwapVerbose(testing.Verbose())
|
||||||
|
|
||||||
testCases := []struct {
|
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) overflowUid(message.Msg) int { return 65534 }
|
||||||
func (k *stubNixOS) overflowGid(container.Msg) int { return 65534 }
|
func (k *stubNixOS) overflowGid(message.Msg) int { return 65534 }
|
||||||
|
|
||||||
func (k *stubNixOS) mustHsuPath() *check.Absolute { return m("/proc/nonexistent/hsu") }
|
func (k *stubNixOS) mustHsuPath() *check.Absolute { return m("/proc/nonexistent/hsu") }
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/internal"
|
"hakurei.app/internal"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// osFile represents [os.File].
|
// osFile represents [os.File].
|
||||||
@ -53,9 +54,9 @@ type syscallDispatcher interface {
|
|||||||
cmdOutput(cmd *exec.Cmd) ([]byte, error)
|
cmdOutput(cmd *exec.Cmd) ([]byte, error)
|
||||||
|
|
||||||
// overflowUid provides [container.OverflowUid].
|
// overflowUid provides [container.OverflowUid].
|
||||||
overflowUid(msg container.Msg) int
|
overflowUid(msg message.Msg) int
|
||||||
// overflowGid provides [container.OverflowGid].
|
// overflowGid provides [container.OverflowGid].
|
||||||
overflowGid(msg container.Msg) int
|
overflowGid(msg message.Msg) int
|
||||||
|
|
||||||
// mustHsuPath provides [internal.MustHsuPath].
|
// mustHsuPath provides [internal.MustHsuPath].
|
||||||
mustHsuPath() *check.Absolute
|
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) cmdOutput(cmd *exec.Cmd) ([]byte, error) { return cmd.Output() }
|
||||||
|
|
||||||
func (direct) overflowUid(msg container.Msg) int { return container.OverflowUid(msg) }
|
func (direct) overflowUid(msg message.Msg) int { return container.OverflowUid(msg) }
|
||||||
func (direct) overflowGid(msg container.Msg) int { return container.OverflowGid(msg) }
|
func (direct) overflowGid(msg message.Msg) int { return container.OverflowGid(msg) }
|
||||||
|
|
||||||
func (direct) mustHsuPath() *check.Absolute { return internal.MustHsuPath() }
|
func (direct) mustHsuPath() *check.Absolute { return internal.MustHsuPath() }
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
type panicDispatcher struct{}
|
type panicDispatcher struct{}
|
||||||
@ -21,7 +21,7 @@ func (panicDispatcher) tempdir() string { panic("unreachab
|
|||||||
func (panicDispatcher) evalSymlinks(string) (string, error) { panic("unreachable") }
|
func (panicDispatcher) evalSymlinks(string) (string, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) lookupGroupId(string) (string, error) { panic("unreachable") }
|
func (panicDispatcher) lookupGroupId(string) (string, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) cmdOutput(*exec.Cmd) ([]byte, error) { panic("unreachable") }
|
func (panicDispatcher) cmdOutput(*exec.Cmd) ([]byte, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) overflowUid(container.Msg) int { panic("unreachable") }
|
func (panicDispatcher) overflowUid(message.Msg) int { panic("unreachable") }
|
||||||
func (panicDispatcher) overflowGid(container.Msg) int { panic("unreachable") }
|
func (panicDispatcher) overflowGid(message.Msg) int { panic("unreachable") }
|
||||||
func (panicDispatcher) mustHsuPath() *check.Absolute { panic("unreachable") }
|
func (panicDispatcher) mustHsuPath() *check.Absolute { panic("unreachable") }
|
||||||
func (panicDispatcher) fatalf(string, ...any) { panic("unreachable") }
|
func (panicDispatcher) fatalf(string, ...any) { panic("unreachable") }
|
||||||
|
@ -8,9 +8,9 @@ import (
|
|||||||
"os/user"
|
"os/user"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/message"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ type outcome struct {
|
|||||||
syscallDispatcher
|
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 {
|
if ctx == nil || id == nil {
|
||||||
// unreachable
|
// unreachable
|
||||||
panic("invalid call to finalise")
|
panic("invalid call to finalise")
|
||||||
|
@ -9,9 +9,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hsu caches responses from cmd/hsu.
|
// 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) }
|
func (h *Hsu) MustID() int { return h.MustIDMsg(nil) }
|
||||||
|
|
||||||
// MustIDMsg implements MustID with a custom [container.Msg].
|
// 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()
|
id, err := h.ID()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return id
|
return id
|
||||||
@ -87,7 +87,7 @@ func (h *Hsu) MustIDMsg(msg container.Msg) int {
|
|||||||
}
|
}
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return -0xdeadbeef
|
return -0xdeadbeef
|
||||||
} else if m, ok := container.GetErrorMessage(err); ok {
|
} else if m, ok := message.GetMessage(err); ok {
|
||||||
log.Fatal(m)
|
log.Fatal(m)
|
||||||
return -0xdeadbeef
|
return -0xdeadbeef
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/message"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
"hakurei.app/system/acl"
|
"hakurei.app/system/acl"
|
||||||
)
|
)
|
||||||
@ -61,7 +62,7 @@ type outcomeState struct {
|
|||||||
// Copied via populateLocal.
|
// Copied via populateLocal.
|
||||||
k syscallDispatcher
|
k syscallDispatcher
|
||||||
// Copied via populateLocal.
|
// Copied via populateLocal.
|
||||||
msg container.Msg
|
msg message.Msg
|
||||||
}
|
}
|
||||||
|
|
||||||
// valid checks outcomeState to be safe for use with outcomeOp.
|
// 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.
|
// populateEarly populates exported fields via syscallDispatcher.
|
||||||
// This must only be called from the priv side.
|
// 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)}
|
s.Shim = &shimParams{PrivPID: os.Getpid(), Verbose: msg.IsVerbose(), Ops: fromConfig(config)}
|
||||||
|
|
||||||
// enforce bounds and default early
|
// 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.
|
// populateLocal populates unexported fields from transmitted exported fields.
|
||||||
// These fields are cheaper to recompute per-process.
|
// 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 {
|
if !s.valid() || k == nil || msg == nil {
|
||||||
return newWithMessage("impossible outcome state reached")
|
return newWithMessage("impossible outcome state reached")
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal"
|
"hakurei.app/internal"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/message"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ type mainState struct {
|
|||||||
cmdWait chan error
|
cmdWait chan error
|
||||||
|
|
||||||
k *outcome
|
k *outcome
|
||||||
container.Msg
|
message.Msg
|
||||||
uintptr
|
uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +208,7 @@ func (ms mainState) fatal(fallback string, ferr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// main carries out outcome and terminates. main does not return.
|
// 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) {
|
if !k.active.CompareAndSwap(false, true) {
|
||||||
panic("outcome: attempted to run twice")
|
panic("outcome: attempted to run twice")
|
||||||
}
|
}
|
||||||
@ -312,10 +313,10 @@ func (k *outcome) main(msg container.Msg) {
|
|||||||
os.Exit(0)
|
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.
|
// or fallback prepended to err if an error message is not available.
|
||||||
func printMessageError(fallback string, err error) {
|
func printMessageError(fallback string, err error) {
|
||||||
m, ok := container.GetErrorMessage(err)
|
m, ok := message.GetMessage(err)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Println(fallback, err)
|
log.Println(fallback, err)
|
||||||
return
|
return
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"hakurei.app/container/bits"
|
"hakurei.app/container/bits"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
//#include "shim-signal.h"
|
//#include "shim-signal.h"
|
||||||
@ -57,7 +58,7 @@ func (p *shimParams) valid() bool {
|
|||||||
func ShimMain() {
|
func ShimMain() {
|
||||||
log.SetPrefix("shim: ")
|
log.SetPrefix("shim: ")
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
msg := container.NewMsg(log.Default())
|
msg := message.NewMsg(log.Default())
|
||||||
|
|
||||||
if err := container.SetDumpable(container.SUID_DUMP_DISABLE); err != nil {
|
if err := container.SetDumpable(container.SUID_DUMP_DISABLE); err != nil {
|
||||||
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
||||||
@ -81,7 +82,7 @@ func ShimMain() {
|
|||||||
closeSetup = f
|
closeSetup = f
|
||||||
|
|
||||||
if err = state.populateLocal(direct{}, msg); err != nil {
|
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)
|
log.Fatal(m)
|
||||||
} else {
|
} else {
|
||||||
log.Fatalf("cannot populate local state: %v", err)
|
log.Fatalf("cannot populate local state: %v", err)
|
||||||
@ -114,7 +115,7 @@ func ShimMain() {
|
|||||||
}
|
}
|
||||||
for _, op := range state.Shim.Ops {
|
for _, op := range state.Shim.Ops {
|
||||||
if err := op.toContainer(&stateParams); err != nil {
|
if err := op.toContainer(&stateParams); err != nil {
|
||||||
if m, ok := container.GetErrorMessage(err); ok {
|
if m, ok := message.GetMessage(err); ok {
|
||||||
log.Fatal(m)
|
log.Fatal(m)
|
||||||
} else {
|
} else {
|
||||||
log.Fatalf("cannot create container state: %v", err)
|
log.Fatalf("cannot create container state: %v", err)
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
"hakurei.app/system/dbus"
|
"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].
|
// 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 p, err := k.evalSymlinks(*v); err != nil {
|
||||||
if !errors.Is(err, fs.ErrNotExist) {
|
if !errors.Is(err, fs.ErrNotExist) {
|
||||||
return err
|
return err
|
||||||
|
@ -11,8 +11,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fine-grained locking and access
|
// fine-grained locking and access
|
||||||
@ -22,7 +22,7 @@ type multiStore struct {
|
|||||||
// initialised backends
|
// initialised backends
|
||||||
backends *sync.Map
|
backends *sync.Map
|
||||||
|
|
||||||
msg container.Msg
|
msg message.Msg
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ func (b *multiBackend) close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewMulti returns an instance of the multi-file store.
|
// 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{
|
return &multiStore{
|
||||||
msg: msg,
|
msg: msg,
|
||||||
base: path.Join(runDir, "state"),
|
base: path.Join(runDir, "state"),
|
||||||
|
@ -4,10 +4,10 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMulti(t *testing.T) {
|
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()))
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -25,7 +26,7 @@ var (
|
|||||||
msgStaticGlibc = []byte("not a dynamic executable")
|
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)
|
c, cancel := context.WithTimeout(ctx, lddTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -6,19 +7,19 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MessageError is an error with a user-facing message.
|
// Error is an error with a user-facing message.
|
||||||
type MessageError interface {
|
type Error interface {
|
||||||
// Message returns a user-facing error message.
|
// Message returns a user-facing error message.
|
||||||
Message() string
|
Message() string
|
||||||
|
|
||||||
error
|
error
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetErrorMessage returns whether an error implements [MessageError], and the message if it does.
|
// GetMessage returns whether an error implements [Error], and the message if it does.
|
||||||
func GetErrorMessage(err error) (string, bool) {
|
func GetMessage(err error) (string, bool) {
|
||||||
var e MessageError
|
var e Error
|
||||||
if !errors.As(err, &e) || e == nil {
|
if !errors.As(err, &e) || e == nil {
|
||||||
return zeroString, false
|
return "", false
|
||||||
}
|
}
|
||||||
return e.Message(), true
|
return e.Message(), true
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package container_test
|
package message_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMessageError(t *testing.T) {
|
func TestMessageError(t *testing.T) {
|
||||||
@ -29,12 +30,12 @@ func TestMessageError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
got, ok := container.GetErrorMessage(tc.err)
|
got, ok := message.GetMessage(tc.err)
|
||||||
if got != tc.want {
|
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 {
|
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("logger", func(t *testing.T) {
|
||||||
t.Run("nil", 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)
|
t.Errorf("GetLogger: Downstream = %#v", out)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,13 +60,13 @@ func TestDefaultMsg(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("takeover", func(t *testing.T) {
|
t.Run("takeover", func(t *testing.T) {
|
||||||
l := log.New(io.Discard, "\x00", 0xdeadbeef)
|
l := log.New(io.Discard, "\x00", 0xdeadbeef)
|
||||||
got := container.NewMsg(l)
|
got := message.NewMsg(l)
|
||||||
|
|
||||||
if logger := got.GetLogger(); logger != l {
|
if logger := got.GetLogger(); logger != l {
|
||||||
t.Errorf("GetLogger: %#v, want %#v", 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)
|
t.Errorf("GetLogger: Downstream = %#v", ds)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -78,93 +79,93 @@ func TestDefaultMsg(t *testing.T) {
|
|||||||
pt, next []byte
|
pt, next []byte
|
||||||
err error
|
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() {
|
if msg.IsVerbose() {
|
||||||
t.Error("IsVerbose unexpected true")
|
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) {
|
if msg.SwapVerbose(false) {
|
||||||
t.Error("SwapVerbose unexpected true")
|
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.Verbose("\x00")
|
||||||
msg.Verbosef("\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() {
|
if msg.IsVerbose() {
|
||||||
t.Error("IsVerbose unexpected true")
|
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) {
|
if msg.SwapVerbose(true) {
|
||||||
t.Error("SwapVerbose unexpected 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")
|
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")
|
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() {
|
if !msg.IsVerbose() {
|
||||||
t.Error("IsVerbose unexpected false")
|
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() {
|
if msg.Resume() {
|
||||||
t.Error("Resume unexpected success")
|
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()
|
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()
|
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()
|
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() {
|
if msg.Resume() {
|
||||||
t.Error("Resume unexpected success")
|
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()
|
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")
|
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() {
|
if !msg.Resume() {
|
||||||
t.Error("Resume unexpected failure")
|
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()
|
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))
|
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() {
|
if !msg.Resume() {
|
||||||
t.Error("Resume unexpected failure")
|
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 {
|
for _, step := range steps {
|
||||||
// these share the same writer, so cannot be subtests
|
// these share the same writer, so cannot be subtests
|
||||||
t.Logf("running step %q", step.name)
|
t.Logf("running step %q", step.name)
|
@ -1,4 +1,4 @@
|
|||||||
package container
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package container_test
|
package message_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -8,8 +8,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSuspendable(t *testing.T) {
|
func TestSuspendable(t *testing.T) {
|
||||||
@ -74,7 +74,7 @@ func TestSuspendable(t *testing.T) {
|
|||||||
|
|
||||||
var dw expectWriter
|
var dw expectWriter
|
||||||
|
|
||||||
w := container.Suspendable{Downstream: &dw}
|
w := message.Suspendable{Downstream: &dw}
|
||||||
for _, step := range steps {
|
for _, step := range steps {
|
||||||
// these share the same writer, so cannot be subtests
|
// these share the same writer, so cannot be subtests
|
||||||
t.Logf("writing step %q", step.name)
|
t.Logf("writing step %q", step.name)
|
@ -11,8 +11,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/helper"
|
"hakurei.app/helper"
|
||||||
|
"hakurei.app/message"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -93,9 +93,9 @@ func testProxyFinaliseStartWaitCloseString(t *testing.T, useSandbox bool) {
|
|||||||
|
|
||||||
t.Run("invalid start", func(t *testing.T) {
|
t.Run("invalid start", func(t *testing.T) {
|
||||||
if !useSandbox {
|
if !useSandbox {
|
||||||
p = dbus.NewDirect(t.Context(), container.NewMsg(nil), nil, nil)
|
p = dbus.NewDirect(t.Context(), message.NewMsg(nil), nil, nil)
|
||||||
} else {
|
} 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) {
|
if err := p.Start(); !errors.Is(err, syscall.ENOTRECOVERABLE) {
|
||||||
@ -128,9 +128,9 @@ func testProxyFinaliseStartWaitCloseString(t *testing.T, useSandbox bool) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
output := new(strings.Builder)
|
output := new(strings.Builder)
|
||||||
if !useSandbox {
|
if !useSandbox {
|
||||||
p = dbus.NewDirect(ctx, container.NewMsg(nil), final, output)
|
p = dbus.NewDirect(ctx, message.NewMsg(nil), final, output)
|
||||||
} else {
|
} 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) {
|
t.Run("invalid wait", func(t *testing.T) {
|
||||||
|
@ -4,11 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDirect returns a new instance of [Proxy] with its sandbox disabled.
|
// 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 := New(ctx, msg, final, output)
|
||||||
p.useSandbox = false
|
p.useSandbox = false
|
||||||
return p
|
return p
|
||||||
|
@ -6,9 +6,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/helper"
|
"hakurei.app/helper"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProxyName is the file name or path to the proxy program.
|
// ProxyName is the file name or path to the proxy program.
|
||||||
@ -19,7 +19,7 @@ var ProxyName = "xdg-dbus-proxy"
|
|||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
helper helper.Helper
|
helper helper.Helper
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
msg container.Msg
|
msg message.Msg
|
||||||
|
|
||||||
cancel context.CancelCauseFunc
|
cancel context.CancelCauseFunc
|
||||||
cause func() error
|
cause func() error
|
||||||
@ -100,6 +100,6 @@ func Finalise(sessionBus, systemBus ProxyPair, session, system *hst.BusConfig) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new instance of [Proxy].
|
// 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}
|
return &Proxy{name: ProxyName, ctx: ctx, msg: msg, final: final, output: output, useSandbox: true}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OpError is returned by [I.Commit] and [I.Revert].
|
// OpError is returned by [I.Commit] and [I.Revert].
|
||||||
@ -70,14 +71,14 @@ func printJoinedError(println func(v ...any), fallback string, err error) {
|
|||||||
error
|
error
|
||||||
}
|
}
|
||||||
if !errors.As(err, &joinErr) {
|
if !errors.As(err, &joinErr) {
|
||||||
if m, ok := container.GetErrorMessage(err); ok {
|
if m, ok := message.GetMessage(err); ok {
|
||||||
println(m)
|
println(m)
|
||||||
} else {
|
} else {
|
||||||
println(fallback, err)
|
println(fallback, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, err = range joinErr.Unwrap() {
|
for _, err = range joinErr.Unwrap() {
|
||||||
if m, ok := container.GetErrorMessage(err); ok {
|
if m, ok := message.GetMessage(err); ok {
|
||||||
println(m)
|
println(m)
|
||||||
} else {
|
} else {
|
||||||
println(err.Error())
|
println(err.Error())
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOpError(t *testing.T) {
|
func TestOpError(t *testing.T) {
|
||||||
@ -64,13 +65,13 @@ func TestOpError(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("msg", func(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 != "" {
|
if tc.msg != "" {
|
||||||
t.Errorf("GetErrorMessage: err does not implement MessageError")
|
t.Errorf("GetMessage: err does not implement MessageError")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else if got != tc.msg {
|
} else if got != tc.msg {
|
||||||
t.Errorf("GetErrorMessage: %q, want %q", got, tc.msg)
|
t.Errorf("GetMessage: %q, want %q", got, tc.msg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -6,8 +6,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -68,7 +68,7 @@ func TypeString(e hst.Enablement) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New returns the address of a new [I] targeting uid.
|
// 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 {
|
if ctx == nil || msg == nil || uid < 0 {
|
||||||
panic("invalid call to New")
|
panic("invalid call to New")
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ type I struct {
|
|||||||
// the behaviour of Revert is only defined for up to one call
|
// the behaviour of Revert is only defined for up to one call
|
||||||
reverted bool
|
reverted bool
|
||||||
|
|
||||||
msg container.Msg
|
msg message.Msg
|
||||||
syscallDispatcher
|
syscallDispatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/message"
|
||||||
"hakurei.app/system/internal/xcb"
|
"hakurei.app/system/internal/xcb"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ func TestNew(t *testing.T) {
|
|||||||
t.Errorf("recover: %v, want %v", r, want)
|
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) {
|
t.Run("msg", func(t *testing.T) {
|
||||||
@ -94,11 +94,11 @@ func TestNew(t *testing.T) {
|
|||||||
t.Errorf("recover: %v, want %v", r, want)
|
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 {
|
if sys.ctx == nil {
|
||||||
t.Error("New: ctx = nil")
|
t.Error("New: ctx = nil")
|
||||||
}
|
}
|
||||||
@ -115,51 +115,51 @@ func TestEqual(t *testing.T) {
|
|||||||
want bool
|
want bool
|
||||||
}{
|
}{
|
||||||
{"simple UID",
|
{"simple UID",
|
||||||
New(t.Context(), container.NewMsg(nil), 150),
|
New(t.Context(), message.NewMsg(nil), 150),
|
||||||
New(t.Context(), container.NewMsg(nil), 150),
|
New(t.Context(), message.NewMsg(nil), 150),
|
||||||
true},
|
true},
|
||||||
|
|
||||||
{"simple UID differ",
|
{"simple UID differ",
|
||||||
New(t.Context(), container.NewMsg(nil), 150),
|
New(t.Context(), message.NewMsg(nil), 150),
|
||||||
New(t.Context(), container.NewMsg(nil), 151),
|
New(t.Context(), message.NewMsg(nil), 151),
|
||||||
false},
|
false},
|
||||||
|
|
||||||
{"simple UID nil",
|
{"simple UID nil",
|
||||||
New(t.Context(), container.NewMsg(nil), 150),
|
New(t.Context(), message.NewMsg(nil), 150),
|
||||||
nil,
|
nil,
|
||||||
false},
|
false},
|
||||||
|
|
||||||
{"op length mismatch",
|
{"op length mismatch",
|
||||||
New(t.Context(), container.NewMsg(nil), 150).
|
New(t.Context(), message.NewMsg(nil), 150).
|
||||||
ChangeHosts("chronos"),
|
ChangeHosts("chronos"),
|
||||||
New(t.Context(), container.NewMsg(nil), 150).
|
New(t.Context(), message.NewMsg(nil), 150).
|
||||||
ChangeHosts("chronos").
|
ChangeHosts("chronos").
|
||||||
Ensure(m("/run"), 0755),
|
Ensure(m("/run"), 0755),
|
||||||
false},
|
false},
|
||||||
|
|
||||||
{"op value mismatch",
|
{"op value mismatch",
|
||||||
New(t.Context(), container.NewMsg(nil), 150).
|
New(t.Context(), message.NewMsg(nil), 150).
|
||||||
ChangeHosts("chronos").
|
ChangeHosts("chronos").
|
||||||
Ensure(m("/run"), 0644),
|
Ensure(m("/run"), 0644),
|
||||||
New(t.Context(), container.NewMsg(nil), 150).
|
New(t.Context(), message.NewMsg(nil), 150).
|
||||||
ChangeHosts("chronos").
|
ChangeHosts("chronos").
|
||||||
Ensure(m("/run"), 0755),
|
Ensure(m("/run"), 0755),
|
||||||
false},
|
false},
|
||||||
|
|
||||||
{"op type mismatch",
|
{"op type mismatch",
|
||||||
New(t.Context(), container.NewMsg(nil), 150).
|
New(t.Context(), message.NewMsg(nil), 150).
|
||||||
ChangeHosts("chronos").
|
ChangeHosts("chronos").
|
||||||
CopyFile(new([]byte), m("/home/ophestra/xdg/config/pulse/cookie"), 0, 256),
|
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").
|
ChangeHosts("chronos").
|
||||||
Ensure(m("/run"), 0755),
|
Ensure(m("/run"), 0755),
|
||||||
false},
|
false},
|
||||||
|
|
||||||
{"op equals",
|
{"op equals",
|
||||||
New(t.Context(), container.NewMsg(nil), 150).
|
New(t.Context(), message.NewMsg(nil), 150).
|
||||||
ChangeHosts("chronos").
|
ChangeHosts("chronos").
|
||||||
Ensure(m("/run"), 0755),
|
Ensure(m("/run"), 0755),
|
||||||
New(t.Context(), container.NewMsg(nil), 150).
|
New(t.Context(), message.NewMsg(nil), 150).
|
||||||
ChangeHosts("chronos").
|
ChangeHosts("chronos").
|
||||||
Ensure(m("/run"), 0755),
|
Ensure(m("/run"), 0755),
|
||||||
true},
|
true},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user