internal/app/paths: defer extra formatting
All checks were successful
Test / Create distribution (push) Successful in 1m14s
Test / Hakurei (push) Successful in 3m50s
Test / Hpkg (push) Successful in 4m44s
Test / Sandbox (race detector) (push) Successful in 4m51s
Test / Sandbox (push) Successful in 1m37s
Test / Hakurei (race detector) (push) Successful in 3m12s
Test / Flake checks (push) Successful in 1m41s
All checks were successful
Test / Create distribution (push) Successful in 1m14s
Test / Hakurei (push) Successful in 3m50s
Test / Hpkg (push) Successful in 4m44s
Test / Sandbox (race detector) (push) Successful in 4m51s
Test / Sandbox (push) Successful in 1m37s
Test / Hakurei (race detector) (push) Successful in 3m12s
Test / Flake checks (push) Successful in 1m41s
This reduces payload size for params to shim. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
71e70b7b5f
commit
e58181a930
@ -231,7 +231,7 @@ func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningE
|
|||||||
var flagShort bool
|
var flagShort bool
|
||||||
c.NewCommand("ps", "List active instances", func(args []string) error {
|
c.NewCommand("ps", "List active instances", func(args []string) error {
|
||||||
var sc hst.Paths
|
var sc hst.Paths
|
||||||
app.CopyPaths(&sc, new(app.Hsu).MustID())
|
app.CopyPaths().Copy(&sc, new(app.Hsu).MustID())
|
||||||
printPs(os.Stdout, time.Now().UTC(), state.NewMulti(msg, sc.RunDirPath.String()), flagShort, flagJSON)
|
printPs(os.Stdout, time.Now().UTC(), state.NewMulti(msg, sc.RunDirPath.String()), flagShort, flagJSON)
|
||||||
return errSuccess
|
return errSuccess
|
||||||
}).Flag(&flagShort, "short", command.BoolFlag(false), "Print instance id")
|
}).Flag(&flagShort, "short", command.BoolFlag(false), "Print instance id")
|
||||||
|
@ -89,7 +89,7 @@ func tryShort(msg container.Msg, name string) (config *hst.Config, entry *state.
|
|||||||
msg.Verbose("argument looks like prefix")
|
msg.Verbose("argument looks like prefix")
|
||||||
|
|
||||||
var sc hst.Paths
|
var sc hst.Paths
|
||||||
app.CopyPaths(&sc, new(app.Hsu).MustID())
|
app.CopyPaths().Copy(&sc, new(app.Hsu).MustID())
|
||||||
s := state.NewMulti(msg, sc.RunDirPath.String())
|
s := state.NewMulti(msg, sc.RunDirPath.String())
|
||||||
if entries, err := state.Join(s); err != nil {
|
if entries, err := state.Join(s); err != nil {
|
||||||
log.Printf("cannot join store: %v", err)
|
log.Printf("cannot join store: %v", err)
|
||||||
|
@ -22,7 +22,7 @@ func printShowSystem(output io.Writer, short, flagJSON bool) {
|
|||||||
defer t.MustFlush()
|
defer t.MustFlush()
|
||||||
|
|
||||||
info := &hst.Info{User: new(app.Hsu).MustID()}
|
info := &hst.Info{User: new(app.Hsu).MustID()}
|
||||||
app.CopyPaths(&info.Paths, info.User)
|
app.CopyPaths().Copy(&info.Paths, info.User)
|
||||||
|
|
||||||
if flagJSON {
|
if flagJSON {
|
||||||
printJSON(output, short, info)
|
printJSON(output, short, info)
|
||||||
|
26
internal/app/dispatcher_test.go
Normal file
26
internal/app/dispatcher_test.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"hakurei.app/container"
|
||||||
|
)
|
||||||
|
|
||||||
|
type panicDispatcher struct{}
|
||||||
|
|
||||||
|
func (panicDispatcher) new(func(k syscallDispatcher)) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) getuid() int { panic("unreachable") }
|
||||||
|
func (panicDispatcher) getgid() int { panic("unreachable") }
|
||||||
|
func (panicDispatcher) lookupEnv(string) (string, bool) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) stat(string) (os.FileInfo, error) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) readdir(string) ([]os.DirEntry, error) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) tempdir() string { panic("unreachable") }
|
||||||
|
func (panicDispatcher) evalSymlinks(string) (string, error) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) lookPath(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) mustHsuPath() *container.Absolute { panic("unreachable") }
|
||||||
|
func (panicDispatcher) fatalf(string, ...any) { panic("unreachable") }
|
@ -275,7 +275,7 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
|
|||||||
|
|
||||||
// TODO(ophestra): revert this after params to shim
|
// TODO(ophestra): revert this after params to shim
|
||||||
share := &shareHost{seal: k}
|
share := &shareHost{seal: k}
|
||||||
copyPaths(k.syscallDispatcher, &share.sc, hsu.MustIDMsg(msg))
|
copyPaths(k.syscallDispatcher).Copy(&share.sc, hsu.MustIDMsg(msg))
|
||||||
msg.Verbosef("process share directory at %q, runtime directory at %q", share.sc.SharePath, share.sc.RunDirPath)
|
msg.Verbosef("process share directory at %q, runtime directory at %q", share.sc.SharePath, share.sc.RunDirPath)
|
||||||
|
|
||||||
var mapuid, mapgid *stringPair[int]
|
var mapuid, mapgid *stringPair[int]
|
||||||
|
@ -7,28 +7,53 @@ import (
|
|||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CopyPaths populates a [hst.Paths] struct.
|
// EnvPaths holds paths copied from the environment and is used to create [hst.Paths].
|
||||||
func CopyPaths(v *hst.Paths, userid int) { copyPaths(direct{}, v, userid) }
|
type EnvPaths struct {
|
||||||
|
// TempDir is returned by [os.TempDir].
|
||||||
// copyPaths populates a [hst.Paths] struct.
|
TempDir *container.Absolute
|
||||||
func copyPaths(k syscallDispatcher, v *hst.Paths, userid int) {
|
// RuntimePath is copied from $XDG_RUNTIME_DIR.
|
||||||
const xdgRuntimeDir = "XDG_RUNTIME_DIR"
|
RuntimePath *container.Absolute
|
||||||
|
|
||||||
if tempDir, err := container.NewAbs(k.tempdir()); err != nil {
|
|
||||||
k.fatalf("invalid TMPDIR: %v", err)
|
|
||||||
} else {
|
|
||||||
v.TempDir = tempDir
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v.SharePath = v.TempDir.Append("hakurei." + strconv.Itoa(userid))
|
// Copy expands [EnvPaths] into [hst.Paths].
|
||||||
|
func (env *EnvPaths) Copy(v *hst.Paths, userid int) {
|
||||||
|
if env == nil || env.TempDir == nil || v == nil {
|
||||||
|
panic("attempting to use an invalid EnvPaths")
|
||||||
|
}
|
||||||
|
|
||||||
r, _ := k.lookupEnv(xdgRuntimeDir)
|
v.TempDir = env.TempDir
|
||||||
if a, err := container.NewAbs(r); err != nil {
|
v.SharePath = env.TempDir.Append("hakurei." + strconv.Itoa(userid))
|
||||||
|
|
||||||
|
if env.RuntimePath == nil {
|
||||||
// fall back to path in share since hakurei has no hard XDG dependency
|
// fall back to path in share since hakurei has no hard XDG dependency
|
||||||
v.RunDirPath = v.SharePath.Append("run")
|
v.RunDirPath = v.SharePath.Append("run")
|
||||||
v.RuntimePath = v.RunDirPath.Append("compat")
|
v.RuntimePath = v.RunDirPath.Append("compat")
|
||||||
} else {
|
} else {
|
||||||
v.RuntimePath = a
|
v.RuntimePath = env.RuntimePath
|
||||||
v.RunDirPath = v.RuntimePath.Append("hakurei")
|
v.RunDirPath = env.RuntimePath.Append("hakurei")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CopyPaths returns a populated [EnvPaths].
|
||||||
|
func CopyPaths() *EnvPaths { return copyPaths(direct{}) }
|
||||||
|
|
||||||
|
// copyPaths returns a populated [EnvPaths].
|
||||||
|
func copyPaths(k syscallDispatcher) *EnvPaths {
|
||||||
|
const xdgRuntimeDir = "XDG_RUNTIME_DIR"
|
||||||
|
|
||||||
|
var env EnvPaths
|
||||||
|
|
||||||
|
if tempDir, err := container.NewAbs(k.tempdir()); err != nil {
|
||||||
|
k.fatalf("invalid TMPDIR: %v", err)
|
||||||
|
panic("unreachable")
|
||||||
|
} else {
|
||||||
|
env.TempDir = tempDir
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _ := k.lookupEnv(xdgRuntimeDir)
|
||||||
|
if a, err := container.NewAbs(r); err == nil {
|
||||||
|
env.RuntimePath = a
|
||||||
|
}
|
||||||
|
|
||||||
|
return &env
|
||||||
|
}
|
||||||
|
129
internal/app/paths_test.go
Normal file
129
internal/app/paths_test.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/container/stub"
|
||||||
|
"hakurei.app/hst"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnvPaths(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
env *EnvPaths
|
||||||
|
want hst.Paths
|
||||||
|
|
||||||
|
wantPanic string
|
||||||
|
}{
|
||||||
|
{"nil", nil, hst.Paths{}, "attempting to use an invalid EnvPaths"},
|
||||||
|
{"zero", new(EnvPaths), hst.Paths{}, "attempting to use an invalid EnvPaths"},
|
||||||
|
|
||||||
|
{"nil tempdir", &EnvPaths{
|
||||||
|
RuntimePath: container.AbsFHSTmp,
|
||||||
|
}, hst.Paths{}, "attempting to use an invalid EnvPaths"},
|
||||||
|
|
||||||
|
{"nil runtime", &EnvPaths{
|
||||||
|
TempDir: container.AbsFHSTmp,
|
||||||
|
}, hst.Paths{
|
||||||
|
TempDir: container.AbsFHSTmp,
|
||||||
|
SharePath: container.AbsFHSTmp.Append("hakurei.3735928559"),
|
||||||
|
RuntimePath: container.AbsFHSTmp.Append("hakurei.3735928559/run/compat"),
|
||||||
|
RunDirPath: container.AbsFHSTmp.Append("hakurei.3735928559/run"),
|
||||||
|
}, ""},
|
||||||
|
|
||||||
|
{"full", &EnvPaths{
|
||||||
|
TempDir: container.AbsFHSTmp,
|
||||||
|
RuntimePath: container.AbsFHSRunUser.Append("1000"),
|
||||||
|
}, hst.Paths{
|
||||||
|
TempDir: container.AbsFHSTmp,
|
||||||
|
SharePath: container.AbsFHSTmp.Append("hakurei.3735928559"),
|
||||||
|
RuntimePath: container.AbsFHSRunUser.Append("1000"),
|
||||||
|
RunDirPath: container.AbsFHSRunUser.Append("1000/hakurei"),
|
||||||
|
}, ""},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
if tc.wantPanic != "" {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != tc.wantPanic {
|
||||||
|
t.Errorf("Copy: panic = %#v, want %q", r, tc.wantPanic)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
var sc hst.Paths
|
||||||
|
tc.env.Copy(&sc, 0xdeadbeef)
|
||||||
|
if !reflect.DeepEqual(&sc, &tc.want) {
|
||||||
|
t.Errorf("Copy: %#v, want %#v", sc, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyPaths(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
env map[string]string
|
||||||
|
tmp string
|
||||||
|
fatal string
|
||||||
|
want EnvPaths
|
||||||
|
}{
|
||||||
|
{"invalid tempdir", nil, "\x00",
|
||||||
|
"invalid TMPDIR: path \"\\x00\" is not absolute", EnvPaths{}},
|
||||||
|
{"empty environment", make(map[string]string), container.Nonexistent,
|
||||||
|
"", EnvPaths{TempDir: container.MustAbs(container.Nonexistent)}},
|
||||||
|
{"invalid XDG_RUNTIME_DIR", map[string]string{"XDG_RUNTIME_DIR": "\x00"}, container.Nonexistent,
|
||||||
|
"", EnvPaths{TempDir: container.MustAbs(container.Nonexistent)}},
|
||||||
|
{"full", map[string]string{"XDG_RUNTIME_DIR": "/\x00"}, container.Nonexistent,
|
||||||
|
"", EnvPaths{TempDir: container.MustAbs(container.Nonexistent), RuntimePath: container.MustAbs("/\x00")}},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
if tc.fatal != "" {
|
||||||
|
defer stub.HandleExit(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
k := copyPathsDispatcher{t: t, env: tc.env, tmp: tc.tmp, expectsFatal: tc.fatal}
|
||||||
|
got := copyPaths(k)
|
||||||
|
|
||||||
|
if tc.fatal != "" {
|
||||||
|
t.Fatalf("copyPaths: expected fatal %q", tc.fatal)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, &tc.want) {
|
||||||
|
t.Errorf("copyPaths: %#v, want %#v", got, &tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copyPathsDispatcher implements enough of syscallDispatcher for all copyPaths code paths.
|
||||||
|
type copyPathsDispatcher struct {
|
||||||
|
env map[string]string
|
||||||
|
tmp string
|
||||||
|
|
||||||
|
// must be checked at the conclusion of the test
|
||||||
|
expectsFatal string
|
||||||
|
|
||||||
|
t *testing.T
|
||||||
|
panicDispatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k copyPathsDispatcher) tempdir() string { return k.tmp }
|
||||||
|
func (k copyPathsDispatcher) lookupEnv(key string) (value string, ok bool) {
|
||||||
|
value, ok = k.env[key]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (k copyPathsDispatcher) fatalf(format string, v ...any) {
|
||||||
|
if k.expectsFatal == "" {
|
||||||
|
k.t.Fatalf("unexpected call to fatalf: format = %q, v = %#v", format, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got := fmt.Sprintf(format, v...); got != k.expectsFatal {
|
||||||
|
k.t.Fatalf("fatalf: %q, want %q", got, k.expectsFatal)
|
||||||
|
}
|
||||||
|
panic(stub.PanicExit)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user