container: allow additional state between ops
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m12s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m21s
Test / Hakurei (race detector) (push) Successful in 5m8s
Test / Flake checks (push) Successful in 1m26s
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m12s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m21s
Test / Hakurei (race detector) (push) Successful in 5m8s
Test / Flake checks (push) Successful in 1m26s
This is useful for ops that need to be aware of previous instances of themselves. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
f9edec7e41
commit
8aa65f28c6
@ -20,8 +20,8 @@ func (f *Ops) Etc(host *Absolute, prefix string) *Ops {
|
||||
|
||||
type AutoEtcOp struct{ Prefix string }
|
||||
|
||||
func (e *AutoEtcOp) early(*Params) error { return nil }
|
||||
func (e *AutoEtcOp) apply(*Params) error {
|
||||
func (e *AutoEtcOp) early(*setupState) error { return nil }
|
||||
func (e *AutoEtcOp) apply(*setupState) error {
|
||||
const target = sysrootPath + FHSEtc
|
||||
rel := e.hostRel() + "/"
|
||||
|
||||
|
@ -28,7 +28,7 @@ type AutoRootOp struct {
|
||||
resolved []Op
|
||||
}
|
||||
|
||||
func (r *AutoRootOp) early(params *Params) error {
|
||||
func (r *AutoRootOp) early(state *setupState) error {
|
||||
if r.Host == nil {
|
||||
return syscall.EBADE
|
||||
}
|
||||
@ -45,7 +45,7 @@ func (r *AutoRootOp) early(params *Params) error {
|
||||
Target: AbsFHSRoot.Append(name),
|
||||
Flags: r.Flags,
|
||||
}
|
||||
if err = op.early(params); err != nil {
|
||||
if err = op.early(state); err != nil {
|
||||
return err
|
||||
}
|
||||
r.resolved = append(r.resolved, op)
|
||||
@ -55,10 +55,10 @@ func (r *AutoRootOp) early(params *Params) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *AutoRootOp) apply(params *Params) error {
|
||||
func (r *AutoRootOp) apply(state *setupState) error {
|
||||
for _, op := range r.resolved {
|
||||
msg.Verbosef("%s %s", op.prefix(), op)
|
||||
if err := op.apply(params); err != nil {
|
||||
if err := op.apply(state); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,8 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
||||
log.Fatalf("cannot make / rslave: %v", err)
|
||||
}
|
||||
|
||||
state := &setupState{Params: ¶ms.Params}
|
||||
|
||||
/* early is called right before pivot_root into intermediate root;
|
||||
this step is mostly for gathering information that would otherwise be difficult to obtain
|
||||
via library functions after pivot_root, and implementations are expected to avoid changing
|
||||
@ -130,7 +132,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
||||
log.Fatalf("invalid op %d", i)
|
||||
}
|
||||
|
||||
if err := op.early(¶ms.Params); err != nil {
|
||||
if err := op.early(state); err != nil {
|
||||
msg.PrintBaseErr(err,
|
||||
fmt.Sprintf("cannot prepare op %d:", i))
|
||||
msg.BeforeExit()
|
||||
@ -170,7 +172,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
||||
for i, op := range *params.Ops {
|
||||
// ops already checked during early setup
|
||||
msg.Verbosef("%s %s", op.prefix(), op)
|
||||
if err := op.apply(¶ms.Params); err != nil {
|
||||
if err := op.apply(state); err != nil {
|
||||
msg.PrintBaseErr(err,
|
||||
fmt.Sprintf("cannot apply op %d:", i))
|
||||
msg.BeforeExit()
|
||||
|
@ -31,14 +31,18 @@ type (
|
||||
// Implementations of this interface are sent as a stream of gobs.
|
||||
Op interface {
|
||||
// early is called in host root.
|
||||
early(params *Params) error
|
||||
early(state *setupState) error
|
||||
// apply is called in intermediate root.
|
||||
apply(params *Params) error
|
||||
apply(state *setupState) error
|
||||
|
||||
prefix() string
|
||||
Is(op Op) bool
|
||||
fmt.Stringer
|
||||
}
|
||||
|
||||
setupState struct {
|
||||
*Params
|
||||
}
|
||||
)
|
||||
|
||||
// Grow grows the slice Ops points to using [slices.Grow].
|
||||
@ -57,8 +61,8 @@ type RemountOp struct {
|
||||
Flags uintptr
|
||||
}
|
||||
|
||||
func (*RemountOp) early(*Params) error { return nil }
|
||||
func (r *RemountOp) apply(*Params) error {
|
||||
func (*RemountOp) early(*setupState) error { return nil }
|
||||
func (r *RemountOp) apply(*setupState) error {
|
||||
if r.Target == nil {
|
||||
return EBADE
|
||||
}
|
||||
@ -93,7 +97,7 @@ const (
|
||||
BindDevice
|
||||
)
|
||||
|
||||
func (b *BindMountOp) early(*Params) error {
|
||||
func (b *BindMountOp) early(*setupState) error {
|
||||
if b.Source == nil || b.Target == nil {
|
||||
return EBADE
|
||||
}
|
||||
@ -110,7 +114,7 @@ func (b *BindMountOp) early(*Params) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BindMountOp) apply(*Params) error {
|
||||
func (b *BindMountOp) apply(*setupState) error {
|
||||
if b.sourceFinal == nil {
|
||||
if b.Flags&BindOptional == 0 {
|
||||
// unreachable
|
||||
@ -166,13 +170,13 @@ type MountProcOp struct {
|
||||
Target *Absolute
|
||||
}
|
||||
|
||||
func (p *MountProcOp) early(*Params) error { return nil }
|
||||
func (p *MountProcOp) apply(params *Params) error {
|
||||
func (p *MountProcOp) early(*setupState) error { return nil }
|
||||
func (p *MountProcOp) apply(state *setupState) error {
|
||||
if p.Target == nil {
|
||||
return EBADE
|
||||
}
|
||||
target := toSysroot(p.Target.String())
|
||||
if err := os.MkdirAll(target, params.ParentPerm); err != nil {
|
||||
if err := os.MkdirAll(target, state.ParentPerm); err != nil {
|
||||
return wrapErrSelf(err)
|
||||
}
|
||||
return wrapErrSuffix(Mount(SourceProc, target, FstypeProc, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString),
|
||||
@ -207,20 +211,20 @@ type MountDevOp struct {
|
||||
Write bool
|
||||
}
|
||||
|
||||
func (d *MountDevOp) early(*Params) error { return nil }
|
||||
func (d *MountDevOp) apply(params *Params) error {
|
||||
func (d *MountDevOp) early(*setupState) error { return nil }
|
||||
func (d *MountDevOp) apply(state *setupState) error {
|
||||
if d.Target == nil {
|
||||
return EBADE
|
||||
}
|
||||
target := toSysroot(d.Target.String())
|
||||
|
||||
if err := mountTmpfs(SourceTmpfsDevtmpfs, target, MS_NOSUID|MS_NODEV, 0, params.ParentPerm); err != nil {
|
||||
if err := mountTmpfs(SourceTmpfsDevtmpfs, target, MS_NOSUID|MS_NODEV, 0, state.ParentPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, name := range []string{"null", "zero", "full", "random", "urandom", "tty"} {
|
||||
targetPath := path.Join(target, name)
|
||||
if err := ensureFile(targetPath, 0444, params.ParentPerm); err != nil {
|
||||
if err := ensureFile(targetPath, 0444, state.ParentPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hostProc.bindMount(
|
||||
@ -252,7 +256,7 @@ func (d *MountDevOp) apply(params *Params) error {
|
||||
|
||||
devPtsPath := path.Join(target, "pts")
|
||||
for _, name := range []string{path.Join(target, "shm"), devPtsPath} {
|
||||
if err := os.Mkdir(name, params.ParentPerm); err != nil {
|
||||
if err := os.Mkdir(name, state.ParentPerm); err != nil {
|
||||
return wrapErrSelf(err)
|
||||
}
|
||||
}
|
||||
@ -263,11 +267,11 @@ func (d *MountDevOp) apply(params *Params) error {
|
||||
fmt.Sprintf("cannot mount devpts on %q:", devPtsPath))
|
||||
}
|
||||
|
||||
if params.RetainSession {
|
||||
if state.RetainSession {
|
||||
var buf [8]byte
|
||||
if _, _, errno := Syscall(SYS_IOCTL, 1, TIOCGWINSZ, uintptr(unsafe.Pointer(&buf[0]))); errno == 0 {
|
||||
consolePath := path.Join(target, "console")
|
||||
if err := ensureFile(consolePath, 0444, params.ParentPerm); err != nil {
|
||||
if err := ensureFile(consolePath, 0444, state.ParentPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
if name, err := os.Readlink(hostProc.stdout()); err != nil {
|
||||
@ -285,7 +289,7 @@ func (d *MountDevOp) apply(params *Params) error {
|
||||
|
||||
if d.Mqueue {
|
||||
mqueueTarget := path.Join(target, "mqueue")
|
||||
if err := os.Mkdir(mqueueTarget, params.ParentPerm); err != nil {
|
||||
if err := os.Mkdir(mqueueTarget, state.ParentPerm); err != nil {
|
||||
return wrapErrSelf(err)
|
||||
}
|
||||
if err := Mount(SourceMqueue, mqueueTarget, FstypeMqueue, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString); err != nil {
|
||||
@ -331,8 +335,8 @@ type MountTmpfsOp struct {
|
||||
Perm os.FileMode
|
||||
}
|
||||
|
||||
func (t *MountTmpfsOp) early(*Params) error { return nil }
|
||||
func (t *MountTmpfsOp) apply(*Params) error {
|
||||
func (t *MountTmpfsOp) early(*setupState) error { return nil }
|
||||
func (t *MountTmpfsOp) apply(*setupState) error {
|
||||
if t.Path == nil {
|
||||
return EBADE
|
||||
}
|
||||
@ -394,7 +398,7 @@ type MountOverlayOp struct {
|
||||
ephemeral bool
|
||||
}
|
||||
|
||||
func (o *MountOverlayOp) early(*Params) error {
|
||||
func (o *MountOverlayOp) early(*setupState) error {
|
||||
if o.Work == nil && o.Upper != nil {
|
||||
switch o.Upper.String() {
|
||||
case FHSRoot: // ephemeral
|
||||
@ -444,12 +448,12 @@ func (o *MountOverlayOp) early(*Params) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *MountOverlayOp) apply(params *Params) error {
|
||||
func (o *MountOverlayOp) apply(state *setupState) error {
|
||||
if o.Target == nil {
|
||||
return EBADE
|
||||
}
|
||||
target := toSysroot(o.Target.String())
|
||||
if err := os.MkdirAll(target, params.ParentPerm); err != nil {
|
||||
if err := os.MkdirAll(target, state.ParentPerm); err != nil {
|
||||
return wrapErrSelf(err)
|
||||
}
|
||||
|
||||
@ -517,7 +521,7 @@ type SymlinkOp struct {
|
||||
Dereference bool
|
||||
}
|
||||
|
||||
func (l *SymlinkOp) early(*Params) error {
|
||||
func (l *SymlinkOp) early(*setupState) error {
|
||||
if l.Dereference {
|
||||
if !isAbs(l.LinkName) {
|
||||
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", l.LinkName))
|
||||
@ -531,12 +535,12 @@ func (l *SymlinkOp) early(*Params) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *SymlinkOp) apply(params *Params) error {
|
||||
func (l *SymlinkOp) apply(state *setupState) error {
|
||||
if l.Target == nil {
|
||||
return EBADE
|
||||
}
|
||||
target := toSysroot(l.Target.String())
|
||||
if err := os.MkdirAll(path.Dir(target), params.ParentPerm); err != nil {
|
||||
if err := os.MkdirAll(path.Dir(target), state.ParentPerm); err != nil {
|
||||
return wrapErrSelf(err)
|
||||
}
|
||||
if err := os.Symlink(l.LinkName, target); err != nil {
|
||||
@ -564,8 +568,8 @@ type MkdirOp struct {
|
||||
Perm os.FileMode
|
||||
}
|
||||
|
||||
func (m *MkdirOp) early(*Params) error { return nil }
|
||||
func (m *MkdirOp) apply(*Params) error {
|
||||
func (m *MkdirOp) early(*setupState) error { return nil }
|
||||
func (m *MkdirOp) apply(*setupState) error {
|
||||
if m.Path == nil {
|
||||
return EBADE
|
||||
}
|
||||
@ -598,8 +602,8 @@ type TmpfileOp struct {
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (t *TmpfileOp) early(*Params) error { return nil }
|
||||
func (t *TmpfileOp) apply(params *Params) error {
|
||||
func (t *TmpfileOp) early(*setupState) error { return nil }
|
||||
func (t *TmpfileOp) apply(state *setupState) error {
|
||||
if t.Path == nil {
|
||||
return EBADE
|
||||
}
|
||||
@ -618,7 +622,7 @@ func (t *TmpfileOp) apply(params *Params) error {
|
||||
}
|
||||
|
||||
target := toSysroot(t.Path.String())
|
||||
if err := ensureFile(target, 0444, params.ParentPerm); err != nil {
|
||||
if err := ensureFile(target, 0444, state.ParentPerm); err != nil {
|
||||
return err
|
||||
} else if err = hostProc.bindMount(
|
||||
tmpPath,
|
||||
|
Loading…
x
Reference in New Issue
Block a user