All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m6s
Test / Hakurei (push) Successful in 3m4s
Test / Hpkg (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 4m18s
Test / Hakurei (race detector) (push) Successful in 4m57s
Test / Flake checks (push) Successful in 1m21s
These keep track of some internal state, and they don't make sense to have multiple instances of anyway, so instead of dealing with that, just make them nonrepetable. Signed-off-by: Ophestra <cat@gensokyo.uk>
74 lines
1.8 KiB
Go
74 lines
1.8 KiB
Go
package container
|
|
|
|
import (
|
|
"encoding/gob"
|
|
"fmt"
|
|
"os"
|
|
"syscall"
|
|
)
|
|
|
|
func init() { gob.Register(new(AutoEtcOp)) }
|
|
|
|
// Etc appends an [Op] that 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.
|
|
func (f *Ops) Etc(host *Absolute, prefix string) *Ops {
|
|
e := &AutoEtcOp{prefix}
|
|
f.Mkdir(AbsFHSEtc, 0755)
|
|
f.Bind(host, e.hostPath(), 0)
|
|
*f = append(*f, e)
|
|
return f
|
|
}
|
|
|
|
type AutoEtcOp struct{ Prefix string }
|
|
|
|
func (e *AutoEtcOp) early(*setupState) error { return nil }
|
|
func (e *AutoEtcOp) apply(state *setupState) error {
|
|
if state.nonrepeatable&nrAutoEtc != 0 {
|
|
return msg.WrapErr(syscall.EINVAL, "autoetc is not repeatable")
|
|
}
|
|
state.nonrepeatable |= nrAutoEtc
|
|
|
|
const target = sysrootPath + FHSEtc
|
|
rel := e.hostRel() + "/"
|
|
|
|
if err := os.MkdirAll(target, 0755); err != nil {
|
|
return wrapErrSelf(err)
|
|
}
|
|
if d, err := os.ReadDir(toSysroot(e.hostPath().String())); err != nil {
|
|
return wrapErrSelf(err)
|
|
} else {
|
|
for _, ent := range d {
|
|
n := ent.Name()
|
|
switch n {
|
|
case ".host":
|
|
|
|
case "passwd":
|
|
case "group":
|
|
|
|
case "mtab":
|
|
if err = os.Symlink(FHSProc+"mounts", target+n); err != nil {
|
|
return wrapErrSelf(err)
|
|
}
|
|
|
|
default:
|
|
if err = os.Symlink(rel+n, target+n); err != nil {
|
|
return wrapErrSelf(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// bypasses abs check, use with caution!
|
|
func (e *AutoEtcOp) hostPath() *Absolute { return &Absolute{FHSEtc + 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 == nil && ve == nil) || (e != nil && ve != nil && *e == *ve))
|
|
}
|
|
func (*AutoEtcOp) prefix() string { return "setting up" }
|
|
func (e *AutoEtcOp) String() string { return fmt.Sprintf("auto etc %s", e.Prefix) }
|