fortify/internal/app/app.go
Ophestra 3c80fd2b0f
All checks were successful
Test / Create distribution (push) Successful in 19s
Test / Run NixOS test (push) Successful in 49s
app: defer system.I revert
Just returning an error after a successful call of commit will leave garbage behind with no way for the caller to clean them. This change ensures revert is always called after successful commit with at least per-process state enabled.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-02-19 21:12:11 +09:00

70 lines
1.2 KiB
Go

package app
import (
"fmt"
"sync"
"git.gensokyo.uk/security/fortify/fst"
"git.gensokyo.uk/security/fortify/internal/fmsg"
"git.gensokyo.uk/security/fortify/internal/sys"
)
func New(os sys.State) (fst.App, error) {
a := new(app)
a.sys = os
id := new(fst.ID)
err := fst.NewAppID(id)
a.id = newID(id)
return a, err
}
type app struct {
id *stringPair[fst.ID]
sys sys.State
*appSeal
mu sync.RWMutex
}
func (a *app) ID() fst.ID { return a.id.unwrap() }
func (a *app) String() string {
if a == nil {
return "(invalid app)"
}
a.mu.RLock()
defer a.mu.RUnlock()
if a.appSeal != nil {
if a.appSeal.user.uid == nil {
return fmt.Sprintf("(sealed app %s with invalid uid)", a.id)
}
return fmt.Sprintf("(sealed app %s as uid %s)", a.id, a.appSeal.user.uid)
}
return fmt.Sprintf("(unsealed app %s)", a.id)
}
func (a *app) Seal(config *fst.Config) (err error) {
a.mu.Lock()
defer a.mu.Unlock()
if a.appSeal != nil {
panic("app sealed twice")
}
if config == nil {
return fmsg.WrapError(ErrConfig,
"attempted to seal app with nil config")
}
seal := new(appSeal)
err = seal.finalise(a.sys, config, a.id.String())
if err == nil {
a.appSeal = seal
}
return
}