template-jj/cmd/planctl/proc_stat_parse.go

35 lines
1.2 KiB
Go
Raw Permalink Normal View History

package main
import (
"fmt"
"strconv"
"strings"
)
// spec:26174-planctl-context-tokens/R6.3+D§3.3
// parseStatStartTime extracts field 22 (starttime — clock ticks since boot)
// from a /proc/<pid>/stat line. The `comm` field at position 2 is wrapped in
// parens and can contain any bytes including spaces and parens; we tokenize
// only the remainder after the LAST ')' so comm contents can't shift indices.
//
// Lives in a non-build-tagged file so it compiles — and is testable — on all
// platforms. Only proc_linux.go's processStartTimeSec actually consumes it.
func parseStatStartTime(stat string) (int64, error) {
i := strings.LastIndex(stat, ")")
if i < 0 || i+1 >= len(stat) {
return 0, fmt.Errorf("stat: no ')' terminator")
}
// After the ')' we have: " state ppid ... starttime ..."
// Fields counted from 1 in the man page: (1) pid, (2) (comm), (3) state, ..., (22) starttime.
// Remainder starts at field 3, so starttime is index 19 (22-3).
fields := strings.Fields(stat[i+1:])
if len(fields) < 20 {
return 0, fmt.Errorf("stat: only %d tail fields", len(fields))
}
n, err := strconv.ParseInt(fields[19], 10, 64)
if err != nil {
return 0, fmt.Errorf("stat: starttime parse: %w", err)
}
return n, nil
}