1 package fscommon
2
3 import (
4 "errors"
5 "fmt"
6 "math"
7 "path"
8 "strconv"
9 "strings"
10
11 "github.com/opencontainers/runc/libcontainer/cgroups"
12 )
13
14 var (
15
16 OpenFile = cgroups.OpenFile
17
18 ReadFile = cgroups.ReadFile
19
20 WriteFile = cgroups.WriteFile
21 )
22
23
24 type ParseError struct {
25 Path string
26 File string
27 Err error
28 }
29
30 func (e *ParseError) Error() string {
31 return "unable to parse " + path.Join(e.Path, e.File) + ": " + e.Err.Error()
32 }
33
34 func (e *ParseError) Unwrap() error { return e.Err }
35
36
37
38
39 func ParseUint(s string, base, bitSize int) (uint64, error) {
40 value, err := strconv.ParseUint(s, base, bitSize)
41 if err != nil {
42 intValue, intErr := strconv.ParseInt(s, base, bitSize)
43
44
45 if intErr == nil && intValue < 0 {
46 return 0, nil
47 } else if errors.Is(intErr, strconv.ErrRange) && intValue < 0 {
48 return 0, nil
49 }
50
51 return value, err
52 }
53
54 return value, nil
55 }
56
57
58
59
60
61 func ParseKeyValue(t string) (string, uint64, error) {
62 parts := strings.SplitN(t, " ", 3)
63 if len(parts) != 2 {
64 return "", 0, fmt.Errorf("line %q is not in key value format", t)
65 }
66
67 value, err := ParseUint(parts[1], 10, 64)
68 if err != nil {
69 return "", 0, err
70 }
71
72 return parts[0], value, nil
73 }
74
75
76
77
78 func GetValueByKey(path, file, key string) (uint64, error) {
79 content, err := cgroups.ReadFile(path, file)
80 if err != nil {
81 return 0, err
82 }
83
84 lines := strings.Split(content, "\n")
85 for _, line := range lines {
86 arr := strings.Split(line, " ")
87 if len(arr) == 2 && arr[0] == key {
88 val, err := ParseUint(arr[1], 10, 64)
89 if err != nil {
90 err = &ParseError{Path: path, File: file, Err: err}
91 }
92 return val, err
93 }
94 }
95
96 return 0, nil
97 }
98
99
100
101 func GetCgroupParamUint(path, file string) (uint64, error) {
102 contents, err := GetCgroupParamString(path, file)
103 if err != nil {
104 return 0, err
105 }
106 contents = strings.TrimSpace(contents)
107 if contents == "max" {
108 return math.MaxUint64, nil
109 }
110
111 res, err := ParseUint(contents, 10, 64)
112 if err != nil {
113 return res, &ParseError{Path: path, File: file, Err: err}
114 }
115 return res, nil
116 }
117
118
119
120 func GetCgroupParamInt(path, file string) (int64, error) {
121 contents, err := cgroups.ReadFile(path, file)
122 if err != nil {
123 return 0, err
124 }
125 contents = strings.TrimSpace(contents)
126 if contents == "max" {
127 return math.MaxInt64, nil
128 }
129
130 res, err := strconv.ParseInt(contents, 10, 64)
131 if err != nil {
132 return res, &ParseError{Path: path, File: file, Err: err}
133 }
134 return res, nil
135 }
136
137
138 func GetCgroupParamString(path, file string) (string, error) {
139 contents, err := cgroups.ReadFile(path, file)
140 if err != nil {
141 return "", err
142 }
143
144 return strings.TrimSpace(contents), nil
145 }
146
View as plain text