...
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 "regexp"
21
22 "github.com/prometheus/procfs/internal/util"
23 )
24
25 var (
26 rPos = regexp.MustCompile(`^pos:\s+(\d+)$`)
27 rFlags = regexp.MustCompile(`^flags:\s+(\d+)$`)
28 rMntID = regexp.MustCompile(`^mnt_id:\s+(\d+)$`)
29 rIno = regexp.MustCompile(`^ino:\s+(\d+)$`)
30 rInotify = regexp.MustCompile(`^inotify`)
31 rInotifyParts = regexp.MustCompile(`^inotify\s+wd:([0-9a-f]+)\s+ino:([0-9a-f]+)\s+sdev:([0-9a-f]+)(?:\s+mask:([0-9a-f]+))?`)
32 )
33
34
35 type ProcFDInfo struct {
36
37 FD string
38
39 Pos string
40
41 Flags string
42
43 MntID string
44
45 Ino string
46
47 InotifyInfos []InotifyInfo
48 }
49
50
51 func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) {
52 data, err := util.ReadFileNoStat(p.path("fdinfo", fd))
53 if err != nil {
54 return nil, err
55 }
56
57 var text, pos, flags, mntid, ino string
58 var inotify []InotifyInfo
59
60 scanner := bufio.NewScanner(bytes.NewReader(data))
61 for scanner.Scan() {
62 text = scanner.Text()
63 if rPos.MatchString(text) {
64 pos = rPos.FindStringSubmatch(text)[1]
65 } else if rFlags.MatchString(text) {
66 flags = rFlags.FindStringSubmatch(text)[1]
67 } else if rMntID.MatchString(text) {
68 mntid = rMntID.FindStringSubmatch(text)[1]
69 } else if rIno.MatchString(text) {
70 ino = rIno.FindStringSubmatch(text)[1]
71 } else if rInotify.MatchString(text) {
72 newInotify, err := parseInotifyInfo(text)
73 if err != nil {
74 return nil, err
75 }
76 inotify = append(inotify, *newInotify)
77 }
78 }
79
80 i := &ProcFDInfo{
81 FD: fd,
82 Pos: pos,
83 Flags: flags,
84 MntID: mntid,
85 Ino: ino,
86 InotifyInfos: inotify,
87 }
88
89 return i, nil
90 }
91
92
93 type InotifyInfo struct {
94
95 WD string
96
97 Ino string
98
99 Sdev string
100
101 Mask string
102 }
103
104
105 func parseInotifyInfo(line string) (*InotifyInfo, error) {
106 m := rInotifyParts.FindStringSubmatch(line)
107 if len(m) >= 4 {
108 var mask string
109 if len(m) == 5 {
110 mask = m[4]
111 }
112 i := &InotifyInfo{
113 WD: m[1],
114 Ino: m[2],
115 Sdev: m[3],
116 Mask: mask,
117 }
118 return i, nil
119 }
120 return nil, fmt.Errorf("%w: invalid inode entry: %q", ErrFileParse, line)
121 }
122
123
124 type ProcFDInfos []ProcFDInfo
125
126 func (p ProcFDInfos) Len() int { return len(p) }
127 func (p ProcFDInfos) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
128 func (p ProcFDInfos) Less(i, j int) bool { return p[i].FD < p[j].FD }
129
130
131 func (p ProcFDInfos) InotifyWatchLen() (int, error) {
132 length := 0
133 for _, f := range p {
134 length += len(f.InotifyInfos)
135 }
136
137 return length, nil
138 }
139
View as plain text