...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package procfs
15
16 import (
17 "bufio"
18 "fmt"
19 "os"
20 "regexp"
21 "strconv"
22 )
23
24
25
26
27 type ProcLimits struct {
28
29 CPUTime uint64
30
31 FileSize uint64
32
33
34 DataSize uint64
35
36 StackSize uint64
37
38 CoreFileSize uint64
39
40 ResidentSet uint64
41
42
43 Processes uint64
44
45
46 OpenFiles uint64
47
48 LockedMemory uint64
49
50 AddressSpace uint64
51
52
53 FileLocks uint64
54
55
56 PendingSignals uint64
57
58
59 MsqqueueSize uint64
60
61 NicePriority uint64
62
63
64 RealtimePriority uint64
65
66
67
68 RealtimeTimeout uint64
69 }
70
71 const (
72 limitsFields = 4
73 limitsUnlimited = "unlimited"
74 )
75
76 var (
77 limitsMatch = regexp.MustCompile(`(Max \w+\s{0,1}?\w*\s{0,1}\w*)\s{2,}(\w+)\s+(\w+)`)
78 )
79
80
81
82
83 func (p Proc) NewLimits() (ProcLimits, error) {
84 return p.Limits()
85 }
86
87
88 func (p Proc) Limits() (ProcLimits, error) {
89 f, err := os.Open(p.path("limits"))
90 if err != nil {
91 return ProcLimits{}, err
92 }
93 defer f.Close()
94
95 var (
96 l = ProcLimits{}
97 s = bufio.NewScanner(f)
98 )
99
100 s.Scan()
101
102 for s.Scan() {
103
104 fields := limitsMatch.FindStringSubmatch(s.Text())
105 if len(fields) != limitsFields {
106 return ProcLimits{}, fmt.Errorf("%w: couldn't parse %q line %q", ErrFileParse, f.Name(), s.Text())
107 }
108
109 switch fields[1] {
110 case "Max cpu time":
111 l.CPUTime, err = parseUint(fields[2])
112 case "Max file size":
113 l.FileSize, err = parseUint(fields[2])
114 case "Max data size":
115 l.DataSize, err = parseUint(fields[2])
116 case "Max stack size":
117 l.StackSize, err = parseUint(fields[2])
118 case "Max core file size":
119 l.CoreFileSize, err = parseUint(fields[2])
120 case "Max resident set":
121 l.ResidentSet, err = parseUint(fields[2])
122 case "Max processes":
123 l.Processes, err = parseUint(fields[2])
124 case "Max open files":
125 l.OpenFiles, err = parseUint(fields[2])
126 case "Max locked memory":
127 l.LockedMemory, err = parseUint(fields[2])
128 case "Max address space":
129 l.AddressSpace, err = parseUint(fields[2])
130 case "Max file locks":
131 l.FileLocks, err = parseUint(fields[2])
132 case "Max pending signals":
133 l.PendingSignals, err = parseUint(fields[2])
134 case "Max msgqueue size":
135 l.MsqqueueSize, err = parseUint(fields[2])
136 case "Max nice priority":
137 l.NicePriority, err = parseUint(fields[2])
138 case "Max realtime priority":
139 l.RealtimePriority, err = parseUint(fields[2])
140 case "Max realtime timeout":
141 l.RealtimeTimeout, err = parseUint(fields[2])
142 }
143 if err != nil {
144 return ProcLimits{}, err
145 }
146 }
147
148 return l, s.Err()
149 }
150
151 func parseUint(s string) (uint64, error) {
152 if s == limitsUnlimited {
153 return 18446744073709551615, nil
154 }
155 i, err := strconv.ParseUint(s, 10, 64)
156 if err != nil {
157 return 0, fmt.Errorf("%s: couldn't parse value %q: %w", ErrFileParse, s, err)
158 }
159 return i, nil
160 }
161
View as plain text