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 }
|
type AutoEtcOp struct{ Prefix string }
|
||||||
|
|
||||||
func (e *AutoEtcOp) early(*Params) error { return nil }
|
func (e *AutoEtcOp) early(*setupState) error { return nil }
|
||||||
func (e *AutoEtcOp) apply(*Params) error {
|
func (e *AutoEtcOp) apply(*setupState) error {
|
||||||
const target = sysrootPath + FHSEtc
|
const target = sysrootPath + FHSEtc
|
||||||
rel := e.hostRel() + "/"
|
rel := e.hostRel() + "/"
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ type AutoRootOp struct {
|
|||||||
resolved []Op
|
resolved []Op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AutoRootOp) early(params *Params) error {
|
func (r *AutoRootOp) early(state *setupState) error {
|
||||||
if r.Host == nil {
|
if r.Host == nil {
|
||||||
return syscall.EBADE
|
return syscall.EBADE
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ func (r *AutoRootOp) early(params *Params) error {
|
|||||||
Target: AbsFHSRoot.Append(name),
|
Target: AbsFHSRoot.Append(name),
|
||||||
Flags: r.Flags,
|
Flags: r.Flags,
|
||||||
}
|
}
|
||||||
if err = op.early(params); err != nil {
|
if err = op.early(state); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.resolved = append(r.resolved, op)
|
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 {
|
for _, op := range r.resolved {
|
||||||
msg.Verbosef("%s %s", op.prefix(), op)
|
msg.Verbosef("%s %s", op.prefix(), op)
|
||||||
if err := op.apply(params); err != nil {
|
if err := op.apply(state); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,8 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
log.Fatalf("cannot make / rslave: %v", err)
|
log.Fatalf("cannot make / rslave: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state := &setupState{Params: ¶ms.Params}
|
||||||
|
|
||||||
/* early is called right before pivot_root into intermediate root;
|
/* early is called right before pivot_root into intermediate root;
|
||||||
this step is mostly for gathering information that would otherwise be difficult to obtain
|
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
|
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)
|
log.Fatalf("invalid op %d", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := op.early(¶ms.Params); err != nil {
|
if err := op.early(state); err != nil {
|
||||||
msg.PrintBaseErr(err,
|
msg.PrintBaseErr(err,
|
||||||
fmt.Sprintf("cannot prepare op %d:", i))
|
fmt.Sprintf("cannot prepare op %d:", i))
|
||||||
msg.BeforeExit()
|
msg.BeforeExit()
|
||||||
@ -170,7 +172,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
for i, op := range *params.Ops {
|
for i, op := range *params.Ops {
|
||||||
// ops already checked during early setup
|
// ops already checked during early setup
|
||||||
msg.Verbosef("%s %s", op.prefix(), op)
|
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,
|
msg.PrintBaseErr(err,
|
||||||
fmt.Sprintf("cannot apply op %d:", i))
|
fmt.Sprintf("cannot apply op %d:", i))
|
||||||
msg.BeforeExit()
|
msg.BeforeExit()
|
||||||
|
@ -31,14 +31,18 @@ type (
|
|||||||
// Implementations of this interface are sent as a stream of gobs.
|
// Implementations of this interface are sent as a stream of gobs.
|
||||||
Op interface {
|
Op interface {
|
||||||
// early is called in host root.
|
// early is called in host root.
|
||||||
early(params *Params) error
|
early(state *setupState) error
|
||||||
// apply is called in intermediate root.
|
// apply is called in intermediate root.
|
||||||
apply(params *Params) error
|
apply(state *setupState) error
|
||||||
|
|
||||||
prefix() string
|
prefix() string
|
||||||
Is(op Op) bool
|
Is(op Op) bool
|
||||||
fmt.Stringer
|
fmt.Stringer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupState struct {
|
||||||
|
*Params
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Grow grows the slice Ops points to using [slices.Grow].
|
// Grow grows the slice Ops points to using [slices.Grow].
|
||||||
@ -57,8 +61,8 @@ type RemountOp struct {
|
|||||||
Flags uintptr
|
Flags uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*RemountOp) early(*Params) error { return nil }
|
func (*RemountOp) early(*setupState) error { return nil }
|
||||||
func (r *RemountOp) apply(*Params) error {
|
func (r *RemountOp) apply(*setupState) error {
|
||||||
if r.Target == nil {
|
if r.Target == nil {
|
||||||
return EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
@ -93,7 +97,7 @@ const (
|
|||||||
BindDevice
|
BindDevice
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *BindMountOp) early(*Params) error {
|
func (b *BindMountOp) early(*setupState) error {
|
||||||
if b.Source == nil || b.Target == nil {
|
if b.Source == nil || b.Target == nil {
|
||||||
return EBADE
|
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.sourceFinal == nil {
|
||||||
if b.Flags&BindOptional == 0 {
|
if b.Flags&BindOptional == 0 {
|
||||||
// unreachable
|
// unreachable
|
||||||
@ -166,13 +170,13 @@ type MountProcOp struct {
|
|||||||
Target *Absolute
|
Target *Absolute
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MountProcOp) early(*Params) error { return nil }
|
func (p *MountProcOp) early(*setupState) error { return nil }
|
||||||
func (p *MountProcOp) apply(params *Params) error {
|
func (p *MountProcOp) apply(state *setupState) error {
|
||||||
if p.Target == nil {
|
if p.Target == nil {
|
||||||
return EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
target := toSysroot(p.Target.String())
|
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 wrapErrSelf(err)
|
||||||
}
|
}
|
||||||
return wrapErrSuffix(Mount(SourceProc, target, FstypeProc, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString),
|
return wrapErrSuffix(Mount(SourceProc, target, FstypeProc, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString),
|
||||||
@ -207,20 +211,20 @@ type MountDevOp struct {
|
|||||||
Write bool
|
Write bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *MountDevOp) early(*Params) error { return nil }
|
func (d *MountDevOp) early(*setupState) error { return nil }
|
||||||
func (d *MountDevOp) apply(params *Params) error {
|
func (d *MountDevOp) apply(state *setupState) error {
|
||||||
if d.Target == nil {
|
if d.Target == nil {
|
||||||
return EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
target := toSysroot(d.Target.String())
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range []string{"null", "zero", "full", "random", "urandom", "tty"} {
|
for _, name := range []string{"null", "zero", "full", "random", "urandom", "tty"} {
|
||||||
targetPath := path.Join(target, name)
|
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
|
return err
|
||||||
}
|
}
|
||||||
if err := hostProc.bindMount(
|
if err := hostProc.bindMount(
|
||||||
@ -252,7 +256,7 @@ func (d *MountDevOp) apply(params *Params) error {
|
|||||||
|
|
||||||
devPtsPath := path.Join(target, "pts")
|
devPtsPath := path.Join(target, "pts")
|
||||||
for _, name := range []string{path.Join(target, "shm"), devPtsPath} {
|
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)
|
return wrapErrSelf(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,11 +267,11 @@ func (d *MountDevOp) apply(params *Params) error {
|
|||||||
fmt.Sprintf("cannot mount devpts on %q:", devPtsPath))
|
fmt.Sprintf("cannot mount devpts on %q:", devPtsPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.RetainSession {
|
if state.RetainSession {
|
||||||
var buf [8]byte
|
var buf [8]byte
|
||||||
if _, _, errno := Syscall(SYS_IOCTL, 1, TIOCGWINSZ, uintptr(unsafe.Pointer(&buf[0]))); errno == 0 {
|
if _, _, errno := Syscall(SYS_IOCTL, 1, TIOCGWINSZ, uintptr(unsafe.Pointer(&buf[0]))); errno == 0 {
|
||||||
consolePath := path.Join(target, "console")
|
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
|
return err
|
||||||
}
|
}
|
||||||
if name, err := os.Readlink(hostProc.stdout()); err != nil {
|
if name, err := os.Readlink(hostProc.stdout()); err != nil {
|
||||||
@ -285,7 +289,7 @@ func (d *MountDevOp) apply(params *Params) error {
|
|||||||
|
|
||||||
if d.Mqueue {
|
if d.Mqueue {
|
||||||
mqueueTarget := path.Join(target, "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)
|
return wrapErrSelf(err)
|
||||||
}
|
}
|
||||||
if err := Mount(SourceMqueue, mqueueTarget, FstypeMqueue, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString); err != nil {
|
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
|
Perm os.FileMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *MountTmpfsOp) early(*Params) error { return nil }
|
func (t *MountTmpfsOp) early(*setupState) error { return nil }
|
||||||
func (t *MountTmpfsOp) apply(*Params) error {
|
func (t *MountTmpfsOp) apply(*setupState) error {
|
||||||
if t.Path == nil {
|
if t.Path == nil {
|
||||||
return EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
@ -394,7 +398,7 @@ type MountOverlayOp struct {
|
|||||||
ephemeral bool
|
ephemeral bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *MountOverlayOp) early(*Params) error {
|
func (o *MountOverlayOp) early(*setupState) error {
|
||||||
if o.Work == nil && o.Upper != nil {
|
if o.Work == nil && o.Upper != nil {
|
||||||
switch o.Upper.String() {
|
switch o.Upper.String() {
|
||||||
case FHSRoot: // ephemeral
|
case FHSRoot: // ephemeral
|
||||||
@ -444,12 +448,12 @@ func (o *MountOverlayOp) early(*Params) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *MountOverlayOp) apply(params *Params) error {
|
func (o *MountOverlayOp) apply(state *setupState) error {
|
||||||
if o.Target == nil {
|
if o.Target == nil {
|
||||||
return EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
target := toSysroot(o.Target.String())
|
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)
|
return wrapErrSelf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -517,7 +521,7 @@ type SymlinkOp struct {
|
|||||||
Dereference bool
|
Dereference bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *SymlinkOp) early(*Params) error {
|
func (l *SymlinkOp) early(*setupState) error {
|
||||||
if l.Dereference {
|
if l.Dereference {
|
||||||
if !isAbs(l.LinkName) {
|
if !isAbs(l.LinkName) {
|
||||||
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *SymlinkOp) apply(params *Params) error {
|
func (l *SymlinkOp) apply(state *setupState) error {
|
||||||
if l.Target == nil {
|
if l.Target == nil {
|
||||||
return EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
target := toSysroot(l.Target.String())
|
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)
|
return wrapErrSelf(err)
|
||||||
}
|
}
|
||||||
if err := os.Symlink(l.LinkName, target); err != nil {
|
if err := os.Symlink(l.LinkName, target); err != nil {
|
||||||
@ -564,8 +568,8 @@ type MkdirOp struct {
|
|||||||
Perm os.FileMode
|
Perm os.FileMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MkdirOp) early(*Params) error { return nil }
|
func (m *MkdirOp) early(*setupState) error { return nil }
|
||||||
func (m *MkdirOp) apply(*Params) error {
|
func (m *MkdirOp) apply(*setupState) error {
|
||||||
if m.Path == nil {
|
if m.Path == nil {
|
||||||
return EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
@ -598,8 +602,8 @@ type TmpfileOp struct {
|
|||||||
Data []byte
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TmpfileOp) early(*Params) error { return nil }
|
func (t *TmpfileOp) early(*setupState) error { return nil }
|
||||||
func (t *TmpfileOp) apply(params *Params) error {
|
func (t *TmpfileOp) apply(state *setupState) error {
|
||||||
if t.Path == nil {
|
if t.Path == nil {
|
||||||
return EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
@ -618,7 +622,7 @@ func (t *TmpfileOp) apply(params *Params) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
target := toSysroot(t.Path.String())
|
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
|
return err
|
||||||
} else if err = hostProc.bindMount(
|
} else if err = hostProc.bindMount(
|
||||||
tmpPath,
|
tmpPath,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user