1
2
3
4
5
6
7
8
9
10
11
12
13
14 package procfs
15
16 import (
17 "bufio"
18 "bytes"
19 "fmt"
20 "io"
21 "strconv"
22 "strings"
23
24 "github.com/prometheus/procfs/internal/util"
25 )
26
27
28 type Wireless struct {
29 Name string
30
31
32 Status uint64
33
34
35 QualityLink int
36
37
38 QualityLevel int
39
40
41 QualityNoise int
42
43
44 DiscardedNwid int
45
46
47 DiscardedCrypt int
48
49
50 DiscardedFrag int
51
52
53 DiscardedRetry int
54
55
56 DiscardedMisc int
57
58
59 MissedBeacon int
60 }
61
62
63 func (fs FS) Wireless() ([]*Wireless, error) {
64 b, err := util.ReadFileNoStat(fs.proc.Path("net/wireless"))
65 if err != nil {
66 return nil, err
67 }
68
69 m, err := parseWireless(bytes.NewReader(b))
70 if err != nil {
71 return nil, fmt.Errorf("%s: wireless: %w", ErrFileParse, err)
72 }
73
74 return m, nil
75 }
76
77
78
84 func parseWireless(r io.Reader) ([]*Wireless, error) {
85 var (
86 interfaces []*Wireless
87 scanner = bufio.NewScanner(r)
88 )
89
90 for n := 0; scanner.Scan(); n++ {
91
92 if n < 2 {
93 continue
94 }
95
96 line := scanner.Text()
97
98 parts := strings.Split(line, ":")
99 if len(parts) != 2 {
100 return nil, fmt.Errorf("%w: expected 2 parts after splitting line by ':', got %d for line %q", ErrFileParse, len(parts), line)
101 }
102
103 name := strings.TrimSpace(parts[0])
104 stats := strings.Fields(parts[1])
105
106 if len(stats) < 10 {
107 return nil, fmt.Errorf("%w: invalid number of fields in line %d, expected 10+, got %d: %q", ErrFileParse, n, len(stats), line)
108 }
109
110 status, err := strconv.ParseUint(stats[0], 16, 16)
111 if err != nil {
112 return nil, fmt.Errorf("%w: invalid status in line %d: %q", ErrFileParse, n, line)
113 }
114
115 qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], "."))
116 if err != nil {
117 return nil, fmt.Errorf("%s: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err)
118 }
119
120 qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], "."))
121 if err != nil {
122 return nil, fmt.Errorf("%s: Quality:level as integer %q: %w", ErrFileParse, qlevel, err)
123 }
124
125 qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], "."))
126 if err != nil {
127 return nil, fmt.Errorf("%s: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err)
128 }
129
130 dnwid, err := strconv.Atoi(stats[4])
131 if err != nil {
132 return nil, fmt.Errorf("%s: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err)
133 }
134
135 dcrypt, err := strconv.Atoi(stats[5])
136 if err != nil {
137 return nil, fmt.Errorf("%s: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err)
138 }
139
140 dfrag, err := strconv.Atoi(stats[6])
141 if err != nil {
142 return nil, fmt.Errorf("%s: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err)
143 }
144
145 dretry, err := strconv.Atoi(stats[7])
146 if err != nil {
147 return nil, fmt.Errorf("%s: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err)
148 }
149
150 dmisc, err := strconv.Atoi(stats[8])
151 if err != nil {
152 return nil, fmt.Errorf("%s: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err)
153 }
154
155 mbeacon, err := strconv.Atoi(stats[9])
156 if err != nil {
157 return nil, fmt.Errorf("%s: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err)
158 }
159
160 w := &Wireless{
161 Name: name,
162 Status: status,
163 QualityLink: qlink,
164 QualityLevel: qlevel,
165 QualityNoise: qnoise,
166 DiscardedNwid: dnwid,
167 DiscardedCrypt: dcrypt,
168 DiscardedFrag: dfrag,
169 DiscardedRetry: dretry,
170 DiscardedMisc: dmisc,
171 MissedBeacon: mbeacon,
172 }
173
174 interfaces = append(interfaces, w)
175 }
176
177 if err := scanner.Err(); err != nil {
178 return nil, fmt.Errorf("%s: Failed to scan /proc/net/wireless: %w", ErrFileRead, err)
179 }
180
181 return interfaces, nil
182 }
183
View as plain text