lib/ec2macosinit/fatalcount.go (49 lines of code) (raw):
package ec2macosinit
import (
"encoding/json"
"fmt"
"os"
)
// FatalCount contains a Count for tracking the number of Fatal exits for this boot
type FatalCount struct {
Count int `json:"count"`
}
// fatalCountFile is the file that contains the fatal counter, this is cleared on reboot
const fatalCountFile = "/tmp/.ec2-macos-init-fatal-counts.json"
// readFatalCount reads the file contents into FatalCount or returns an initialized counter.
func (r *FatalCount) readFatalCount() (err error) {
// Check if fatal count file exists, if not, create it but leave it empty, then return 0, otherwise read and return
_, err = os.Stat(fatalCountFile)
if !os.IsNotExist(err) {
err = r.readFatalFile()
if err != nil {
return fmt.Errorf("ec2macosinit: Failed to read %s: %s", fatalCountFile, err)
}
} else {
// Take initial values for first run
*r = FatalCount{1}
}
return nil
}
// IncrementFatalCount takes the current count, increments it, and saves to the temporary file.
func (r *FatalCount) IncrementFatalCount() (err error) {
// Get the current count
err = r.readFatalCount()
if err != nil {
return fmt.Errorf("ec2macosinit: unable to read run count file: %s", err)
}
r.Count++ // Increment the counter in the struct
// Marshall the FatalCount struct to json
rcBytes, err := json.Marshal(r)
if err != nil {
return fmt.Errorf("ec2macosinit: failed to save run counts: %s", err)
}
// Write the bytes to the counter file
err = os.WriteFile(fatalCountFile, rcBytes, 0644)
if err != nil {
return fmt.Errorf("ec2macosinit: failed to save run counts: %s", err)
}
return nil
}
// readFatalFile reads the temporary file for count.
func (r *FatalCount) readFatalFile() (err error) {
// Read the contents into bytes
countsBytes, err := os.ReadFile(fatalCountFile)
if err != nil {
return fmt.Errorf("ec2macosinit: Failed to read %s: %s", fatalCountFile, err)
}
// Unmarshal to the struct
err = json.Unmarshal(countsBytes, &r)
if err != nil {
return fmt.Errorf("ec2macosinit: Failed to parse json: %s", err)
}
return nil
}