Public source validation / validate (push) Failing after 3m8s
68 lines
1.7 KiB
Go
68 lines
1.7 KiB
Go
package hostcollect
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// readLimited reads at most limit bytes from path. Every /proc file the collector
|
|
// touches is small, but /proc is a kernel interface and a bounded read keeps a
|
|
// pathological or hostile file from becoming an unbounded allocation.
|
|
func readLimited(path string, limit int64) ([]byte, error) {
|
|
file, err := os.Open(path) //nolint:gosec // paths are derived from the configured procfs root
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() { _ = file.Close() }()
|
|
data, err := io.ReadAll(io.LimitReader(file, limit))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
func readTrimmed(path string, limit int64) (string, error) {
|
|
data, err := readLimited(path, limit)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return strings.TrimSpace(string(data)), nil
|
|
}
|
|
|
|
// parseUint accepts the decimal unsigned values procfs uses and reports failure
|
|
// instead of guessing, so a malformed line degrades one field rather than producing a
|
|
// plausible-looking zero.
|
|
func parseUint(value string) (uint64, bool) {
|
|
parsed, err := strconv.ParseUint(strings.TrimSpace(value), 10, 64)
|
|
if err != nil {
|
|
return 0, false
|
|
}
|
|
return parsed, true
|
|
}
|
|
|
|
func parseFloat(value string) (float64, bool) {
|
|
parsed, err := strconv.ParseFloat(strings.TrimSpace(value), 64)
|
|
if err != nil {
|
|
return 0, false
|
|
}
|
|
return parsed, true
|
|
}
|
|
|
|
func truncate(value string, max int) string {
|
|
if len(value) > max {
|
|
return value[:max]
|
|
}
|
|
return value
|
|
}
|
|
|
|
// lines splits procfs content without allocating a scanner per file.
|
|
func lines(data []byte) []string {
|
|
text := strings.TrimRight(string(data), "\n")
|
|
if text == "" {
|
|
return nil
|
|
}
|
|
return strings.Split(text, "\n")
|
|
}
|