fortify/internal/state/print.go
Ophestra Umiker eae3034260
All checks were successful
Tests / Go tests (push) Successful in 39s
Nix / NixOS tests (push) Successful in 3m26s
state: expose aids and use instance id as key
Fortify state store instances was specific to aids due to outdated design decisions carried over from the ego rewrite. That no longer makes sense in the current application, so the interface now enables a single store object to manage all transient state.

Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
2024-12-19 21:36:17 +09:00

119 lines
3.0 KiB
Go

package state
import (
"fmt"
"os"
"strings"
"text/tabwriter"
"time"
"git.ophivana.moe/security/fortify/internal/fmsg"
"git.ophivana.moe/security/fortify/internal/system"
)
// MustPrintLauncherStateSimpleGlobal prints active launcher states of all simple stores
// in an implementation-specific way.
func MustPrintLauncherStateSimpleGlobal(w **tabwriter.Writer, runDir string) {
now := time.Now().UTC()
s := NewMulti(runDir)
// read runtime directory to get all UIDs
if aids, err := s.List(); err != nil {
fmsg.Fatal("cannot list store:", err)
} else {
for _, aid := range aids {
// print states belonging to this store
s.(*multiStore).mustPrintLauncherState(aid, w, now)
}
}
// mustPrintLauncherState causes store activity so store needs to be closed
if err := s.Close(); err != nil {
fmsg.Printf("cannot close store: %v", err)
}
}
func (s *multiStore) mustPrintLauncherState(aid int, w **tabwriter.Writer, now time.Time) {
var innerErr error
if ok, err := s.Do(aid, func(c Cursor) {
innerErr = func() error {
// read launcher states
states, err := c.Load()
if err != nil {
return err
}
// initialise tabwriter if nil
if *w == nil {
*w = tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
// write header when initialising
if !fmsg.Verbose() {
_, _ = fmt.Fprintln(*w, "\tPID\tApp\tUptime\tEnablements\tCommand")
} else {
// argv is emitted in body when verbose
_, _ = fmt.Fprintln(*w, "\tPID\tApp\tArgv")
}
}
// print each state
for _, state := range states {
// skip nil states
if state == nil {
_, _ = fmt.Fprintln(*w, "\tnil state entry")
continue
}
// build enablements and command string
var (
ets *strings.Builder
cs = "(No command information)"
)
// check if enablements are provided
if state.Config != nil {
ets = new(strings.Builder)
// append enablement strings in order
for i := system.Enablement(0); i < system.Enablement(system.ELen); i++ {
if state.Config.Confinement.Enablements.Has(i) {
ets.WriteString(", " + i.String())
}
}
cs = fmt.Sprintf("%q", state.Config.Command)
}
if ets != nil {
// prevent an empty string
if ets.Len() == 0 {
ets.WriteString("(No enablements)")
}
} else {
ets = new(strings.Builder)
ets.WriteString("(No confinement information)")
}
if !fmsg.Verbose() {
_, _ = fmt.Fprintf(*w, "\t%d\t%d\t%s\t%s\t%s\n",
state.PID, aid, now.Sub(state.Time).Round(time.Second).String(), strings.TrimPrefix(ets.String(), ", "), cs)
} else {
// emit argv instead when verbose
_, _ = fmt.Fprintf(*w, "\t%d\t%d\t%s\n",
state.PID, aid, state.ID)
}
}
return nil
}()
}); err != nil {
fmsg.Printf("cannot perform action on app %d: %v", aid, err)
if !ok {
fmsg.Fatal("store faulted before printing")
}
}
if innerErr != nil {
fmsg.Fatalf("cannot print launcher state of app %d: %s", aid, innerErr)
}
}