Files
hakurei/container/autoetc.go
T
cat 1c3761bb53
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 3m0s
Test / Hakurei (push) Successful in 4m48s
Test / Sandbox (race detector) (push) Successful in 6m6s
Test / Hakurei (race detector) (push) Successful in 7m32s
Test / ShareFS (push) Successful in 7m54s
Test / Flake checks (push) Successful in 1m19s
container: enter init path early
There is generally no use case where any setup is required before init, and requiring the explicit function call is error-prone and unnecessary. It also causes trouble with packages using a similar trick. This change moves argv0 check early and makes it an import side effect. The stub will be removed in v0.5.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-25 14:53:29 +09:00

72 lines
1.9 KiB
Go

package container
import (
"fmt"
"hakurei.app/check"
"hakurei.app/fhs"
)
// Etc is a helper for appending [AutoEtcOp] to [Ops].
func (f *Ops) Etc(host *check.Absolute, prefix string) *Ops {
e := &AutoEtcOp{prefix}
f.Mkdir(fhs.AbsEtc, 0755)
f.Bind(host, e.hostPath(), 0)
*f = append(*f, e)
return f
}
// AutoEtcOp expands host /etc into a toplevel symlink mirror with /etc semantics.
//
// This is not a generic setup op. It is implemented here to reduce ipc overhead.
type AutoEtcOp struct{ Prefix string }
func (e *AutoEtcOp) Valid() bool { return e != nil }
func (e *AutoEtcOp) early(*setupState, syscallDispatcher) error { return nil }
func (e *AutoEtcOp) apply(state *setupState, k syscallDispatcher) error {
if state.nonrepeatable&nrAutoEtc != 0 {
return OpRepeatError("autoetc")
}
state.nonrepeatable |= nrAutoEtc
const target = sysrootPath + fhs.Etc
rel := e.hostRel() + "/"
if err := k.mkdirAll(target, 0755); err != nil {
return err
}
if d, err := k.readdir(toSysroot(e.hostPath().String())); err != nil {
return err
} else {
for _, ent := range d {
n := ent.Name()
switch n {
case ".host", "passwd", "group":
case "mtab":
if err = k.symlink(fhs.Proc+"mounts", target+n); err != nil {
return err
}
default:
if err = k.symlink(rel+n, target+n); err != nil {
return err
}
}
}
}
return nil
}
func (e *AutoEtcOp) late(*setupState, syscallDispatcher) error { return nil }
func (e *AutoEtcOp) hostPath() *check.Absolute { return fhs.AbsEtc.Append(e.hostRel()) }
func (e *AutoEtcOp) hostRel() string { return ".host/" + e.Prefix }
func (e *AutoEtcOp) Is(op Op) bool {
ve, ok := op.(*AutoEtcOp)
return ok && e.Valid() && ve.Valid() && *e == *ve
}
func (*AutoEtcOp) prefix() (string, bool) { return "setting up", true }
func (e *AutoEtcOp) String() string { return fmt.Sprintf("auto etc %s", e.Prefix) }