-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.go
104 lines (81 loc) · 2.14 KB
/
parse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package lsmod
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
"github.com/pkg/errors"
)
const (
// ProcModules is a path to pseudo-file to parse
ProcModules = "/proc/modules"
minFieldsPerLine = 6
maxFieldsPerLine = 7
noDeps = "-"
delimDeps = ","
)
func parse(fileName string) (map[string]ModInfo, error) {
file, err := os.Open(fileName) // nolint: gosec
if err != nil {
return nil, errors.Wrapf(err, "Error opening %q", fileName)
}
defer file.Close() // nolint: errcheck
mods := make(map[string]ModInfo)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) < minFieldsPerLine || len(fields) > maxFieldsPerLine {
return nil, fmt.Errorf("invalid input line %q", line)
}
info, err := parseInfo(fields) // nolint: govet
if err != nil {
return nil, errors.Wrapf(err, "error parsing %q", ProcModules)
}
mods[fields[0]] = info
}
err = scanner.Err()
if err != nil {
return nil, errors.Wrapf(err, "Error reading %q", ProcModules)
}
return mods, nil
}
func parseInfo(fields []string) (info ModInfo, err error) {
info.Mem, err = parseUint(fields[1])
if err != nil {
return info, errors.Wrap(err, "invalid mem (field 2)")
}
info.Instances, err = parseUint(fields[2])
if err != nil {
return info, errors.Wrap(err, "invalid instances (field 3)")
}
info.Depends = splitDeps(fields[3])
info.State, err = parseState(fields[4])
if err != nil {
return info, errors.Wrap(err, "unknown state (field 5)")
}
info.Offset, err = parseUint(fields[5])
if err != nil {
return info, errors.Wrap(err, "invalid offset (field 6)")
}
if len(fields) == maxFieldsPerLine {
info.Tained, err = parseTained(fields[6])
if err != nil {
return info, errors.Wrap(err, "unknown tained (field 7)")
}
}
return info, nil
}
func splitDeps(line string) []string {
if line == noDeps {
return nil
}
return strings.Split(strings.TrimRight(line, delimDeps), delimDeps)
}
func parseUint(line string) (uint64, error) {
if strings.HasPrefix(line, "0x") {
return strconv.ParseUint(line[2:], 16, 64)
}
return strconv.ParseUint(line, 10, 64)
}