diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-10-29 04:32:43 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-10-29 04:33:13 +0900 |
| commit | a0b4e47acc228e48165966d8e139277b8f6f450e (patch) | |
| tree | d363a6781536ce946aa445271ca1d3df587e6031 /internal/outcome/finalise.go | |
| parent | a52f7038e5a607dd0901244abb791c96deaf9c2d (diff) | |
internal/outcome: rename from app
This is less ambiguous, and more accurately describes the purpose of the package.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/outcome/finalise.go')
| -rw-r--r-- | internal/outcome/finalise.go | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/internal/outcome/finalise.go b/internal/outcome/finalise.go new file mode 100644 index 00000000..184bd905 --- /dev/null +++ b/internal/outcome/finalise.go @@ -0,0 +1,85 @@ +package outcome + +import ( + "context" + "errors" + "fmt" + "os" + "os/user" + "sync/atomic" + + "hakurei.app/hst" + "hakurei.app/message" + "hakurei.app/system" +) + +func newWithMessage(msg string) error { return newWithMessageError(msg, os.ErrInvalid) } +func newWithMessageError(msg string, err error) error { + return &hst.AppError{Step: "finalise", Err: err, Msg: msg} +} + +// An outcome is the runnable state of a hakurei container via [hst.Config]. +type outcome struct { + // Supplementary group ids. Populated during finalise. + supp []string + // Resolved priv side operating system interactions. Populated during finalise. + sys *system.I + // Transmitted to shim. Populated during finalise. + state *outcomeState + // Kept for saving to [state]. + config *hst.Config + + // Whether the current process is in outcome.main. + active atomic.Bool + + ctx context.Context + syscallDispatcher +} + +func (k *outcome) finalise(ctx context.Context, msg message.Msg, id *hst.ID, config *hst.Config) error { + if ctx == nil || id == nil { + // unreachable + panic("invalid call to finalise") + } + if k.ctx != nil || k.sys != nil || k.state != nil { + // unreachable + panic("attempting to finalise twice") + } + k.ctx = ctx + + if err := config.Validate(); err != nil { + return err + } + + // hsu expects numerical group ids + supp := make([]string, len(config.Groups)) + for i, name := range config.Groups { + if gid, err := k.lookupGroupId(name); err != nil { + var unknownGroupError user.UnknownGroupError + if errors.As(err, &unknownGroupError) { + return newWithMessageError(fmt.Sprintf("unknown group %q", name), unknownGroupError) + } else { + return &hst.AppError{Step: "look up group by name", Err: err} + } + } else { + supp[i] = gid + } + } + + // early validation complete at this point + s := newOutcomeState(k.syscallDispatcher, msg, id, config, &Hsu{k: k}) + if err := s.populateLocal(k.syscallDispatcher, msg); err != nil { + return err + } + + sys := system.New(k.ctx, msg, s.uid.unwrap()) + if err := s.newSys(config, sys).toSystem(); err != nil { + return err + } + + k.sys = sys + k.supp = supp + k.state = s + k.config = config + return nil +} |
