// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

// The pstore package provides functions for interfacing with the Linux kernel's
// pstore (persistent storage) system.
// Documentation for pstore itself can be found at
// https://docs.kernel.org/admin-guide/abi-testing.html#abi-sys-fs-pstore.
package pstore

import (
	"bufio"
	"errors"
	"fmt"
	"io/fs"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"time"
)

// CanonicalMountPath contains the canonical mount path of the pstore filesystem
const CanonicalMountPath = "/sys/fs/pstore"

// pstoreDmesgHeader contains parsed header data from a pstore header.
type pstoreDmesgHeader struct {
	Reason  string
	Counter uint64
	Part    uint64
}

var headerRegexp = regexp.MustCompile("^([^#]+)#([0-9]+) Part([0-9]+)$")

// parseDmesgHeader parses textual pstore entry headers as assembled by
// @linux//fs/pstore/platform.c:pstore_dump back into a structured format.
// The input must be the first line of a file with the terminating \n stripped.
func parseDmesgHeader(hdr string) (*pstoreDmesgHeader, error) {
	parts := headerRegexp.FindStringSubmatch(hdr)
	if parts == nil {
		return nil, errors.New("unable to parse pstore entry header")
	}
	counter, err := strconv.ParseUint(parts[2], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("failed to parse pstore header count: %w", err)
	}
	part, err := strconv.ParseUint(parts[3], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("failed to parse pstore header part: %w", err)
	}
	return &pstoreDmesgHeader{
		Reason:  parts[1],
		Counter: counter,
		Part:    part,
	}, nil
}

// KmsgDump reassembled a kernel message buffer dump from pstore.
type KmsgDump struct {
	// The reason why the dump was created. Common values include "Panic" and
	// "Oops", but depending on the setting `printk.always_kmsg_dump` and
	// potential future reasons this is likely unbounded.
	Reason string
	// The CLOCK_REALTIME value of the first entry in the dump (which is the
	// closest to the actual time the dump happened). This can be zero or
	// garbage if the RTC hasn't been initialized or the system has no working
	// clock source.
	OccurredAt time.Time
	// A counter counting up for every dump created. Can be used to order dumps
	// when the OccurredAt value is not usable due to system issues.
	Counter uint64
	// A list of kernel log lines in oldest-to-newest order, i.e. the oldest
	// message comes first. The actual cause is generally reported last.
	Lines []string
}

var dmesgFileRegexp = regexp.MustCompile("^dmesg-.*-([0-9]+)")

var pmsgFileRegexp = regexp.MustCompile("^pmsg-.*-([0-9]+)")

type pstoreDmesgFile struct {
	hdr   pstoreDmesgHeader
	ctime time.Time
	lines []string
}

// GetKmsgDumps returns a list of events where the kernel has dumped its kmsg
// (kernel log) buffer into pstore because of a kernel oops or panic.
func GetKmsgDumps() ([]KmsgDump, error) {
	return getKmsgDumpsFromFS(os.DirFS(CanonicalMountPath))
}

// GetPmsgDump returns lines written into /dev/pmsg0
func GetPmsgDump() ([]string, error) {
	var lines []string
	pstoreEntries, err := os.ReadDir(CanonicalMountPath)
	if err != nil {
		return nil, fmt.Errorf("failed to list files in pstore: %w", err)
	}
	for _, entry := range pstoreEntries {
		if !pmsgFileRegexp.MatchString(entry.Name()) {
			continue
		}
		f, err := os.Open(filepath.Join(CanonicalMountPath, entry.Name()))
		if err != nil {
			return lines, fmt.Errorf("failed to open pstore entry file: %w", err)
		}
		// This only closes after all files have been read, but the number of
		// files is heavily bound by very small amounts of pstore space.
		defer f.Close()
		s := bufio.NewScanner(f)
		for s.Scan() {
			lines = append(lines, s.Text())
		}
	}
	return lines, nil
}

// f is injected here for testing
func getKmsgDumpsFromFS(f fs.FS) ([]KmsgDump, error) {
	var events []KmsgDump
	eventMap := make(map[string][]pstoreDmesgFile)
	pstoreEntries, err := fs.ReadDir(f, ".")
	if err != nil {
		return events, fmt.Errorf("failed to list files in pstore: %w", err)
	}
	for _, entry := range pstoreEntries {
		if !dmesgFileRegexp.MatchString(entry.Name()) {
			continue
		}
		f, err := f.Open(entry.Name())
		if err != nil {
			return events, fmt.Errorf("failed to open pstore entry file: %w", err)
		}
		// This only closes after all files have been read, but the number of
		// files is heavily bound by very small amounts of pstore space.
		defer f.Close()
		finfo, err := f.Stat()
		if err != nil {
			return events, fmt.Errorf("failed to stat pstore entry file: %w", err)
		}
		s := bufio.NewScanner(f)
		if !s.Scan() {
			return events, fmt.Errorf("cannot read first line header of pstore entry %q: %w", entry.Name(), s.Err())
		}
		hdr, err := parseDmesgHeader(s.Text())
		if err != nil {
			return events, fmt.Errorf("failed to parse header of file %q: %w", entry.Name(), err)
		}
		var lines []string
		for s.Scan() {
			lines = append(lines, s.Text())
		}
		// Same textual encoding is used in the header itself, so this
		// is as unique as it gets.
		key := fmt.Sprintf("%v#%d", hdr.Reason, hdr.Counter)
		eventMap[key] = append(eventMap[key], pstoreDmesgFile{hdr: *hdr, ctime: finfo.ModTime(), lines: lines})
	}

	for _, event := range eventMap {
		sort.Slice(event, func(i, j int) bool {
			return event[i].hdr.Part > event[j].hdr.Part
		})
		ev := KmsgDump{
			Counter: event[len(event)-1].hdr.Counter,
			Reason:  event[len(event)-1].hdr.Reason,
			// Entries get created in reverse order, so the most accurate
			// timestamp is the first one.
			OccurredAt: event[len(event)-1].ctime,
		}
		for _, entry := range event {
			ev.Lines = append(ev.Lines, entry.lines...)
		}
		events = append(events, ev)
	}
	sort.Slice(events, func(i, j int) bool {
		return !events[i].OccurredAt.Before(events[j].OccurredAt)
	})
	return events, nil
}

// ClearAll clears out all existing entries from the pstore. This should be done
// after every start (after the relevant data has been read out) to ensure that
// there is always space to store new pstore entries and to minimize the risk
// of breaking badly-programmed firmware.
func ClearAll() error {
	pstoreEntries, err := os.ReadDir(CanonicalMountPath)
	if err != nil {
		return fmt.Errorf("failed to list files in pstore: %w", err)
	}
	for _, entry := range pstoreEntries {
		if err := os.Remove(filepath.Join(CanonicalMountPath, entry.Name())); err != nil {
			return fmt.Errorf("failed to clear pstore entry: %w", err)
		}
	}
	return nil
}
