package host import ( "bytes" "context" "os" "github.com/carlosframework/platform/internal/rootstate" ) // The caller holds the binding lock and has resolved the successor from the // current root installation. A route edit never reaches this transition. func (m claimUnitMaterializer) handover(ctx context.Context, old, next claimUnitBinding) error { if m.state == nil || m.read == nil || m.replace == nil || m.idle == nil || !old.valid() || !next.valid() || !old.Retired || next.Retiring || next.Retired || old.Shape != next.Shape || old.Owner == next.Owner { return os.ErrPermission } unlock, err := m.state.Lock(ctx, "materialize") if err != nil { return err } defer unlock() r, err := m.load(old.Owner.Host) if err != nil { return err } want, err := claimOwnedUnitDefinition(next) if err != nil { return err } previous := old previous.Retiring, previous.Retired = false, false if r.Binding == previous { if !r.Retired || r.Identity == (rootstate.FileIdentity{}) { return os.ErrPermission } raw, id, err := m.read(old.Shape.Unit) if err != nil { return err } if !id.Same(r.Identity) || !bytes.Equal(raw, claimRetiredUnitDefinition(old)) { return os.ErrPermission } r = claimUnitMaterialization{Binding: next, Digest: claimUnitDigest(want), Prior: old, PriorIdentity: r.Identity} } if r.Binding != next || r.Prior != old || r.Digest != claimUnitDigest(want) || r.Retiring || r.Retired { return os.ErrPermission } if err = m.save(r); err != nil { return err } raw, id, err := m.read(next.Shape.Unit) if err != nil { return err } if r.Identity == (rootstate.FileIdentity{}) && id.Same(r.PriorIdentity) && bytes.Equal(raw, claimRetiredUnitDefinition(old)) { if err = m.idle(next.Shape.Host); err != nil { return err } if err = m.replace(next.Shape.Unit, r.PriorIdentity, want); err != nil { return err } raw, id, err = m.read(next.Shape.Unit) if err != nil { return err } } if !bytes.Equal(raw, want) || id == (rootstate.FileIdentity{}) || (r.Identity != (rootstate.FileIdentity{}) && !r.Identity.Same(id)) { return os.ErrPermission } r.Identity = id return m.save(r) }