Skip to content

Commit 9a75fe6

Browse files
authored
Merge pull request #50 from cyphar/mountinfo-improvements
mountinfo: correctness improvements
2 parents 95f2efb + 2847623 commit 9a75fe6

File tree

3 files changed

+43
-20
lines changed

3 files changed

+43
-20
lines changed

mountinfo/mountinfo_filters.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import "strings"
66
// used to filter out mountinfo entries we're not interested in,
77
// and/or stop further processing if we found what we wanted.
88
//
9-
// It takes a pointer to the Info struct (not fully populated,
10-
// currently only Mountpoint, FSType, Source, and (on Linux)
11-
// VFSOptions are filled in), and returns two booleans:
9+
// It takes a pointer to the Info struct (fully populated with all available
10+
// fields on the GOOS platform), and returns two booleans:
1211
//
1312
// skip: true if the entry should be skipped;
1413
//

mountinfo/mountinfo_linux.go

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ import (
1818
func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
1919
s := bufio.NewScanner(r)
2020
out := []*Info{}
21-
var err error
2221
for s.Scan() {
23-
if err = s.Err(); err != nil {
24-
return nil, err
25-
}
22+
var err error
23+
2624
/*
2725
See http://man7.org/linux/man-pages/man5/proc.5.html
2826
@@ -74,7 +72,6 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
7472

7573
p := &Info{}
7674

77-
// Fill in the fields that a filter might check
7875
p.Mountpoint, err = unescape(fields[4])
7976
if err != nil {
8077
return nil, fmt.Errorf("Parsing '%s' failed: mount point: %w", fields[4], err)
@@ -89,18 +86,6 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
8986
}
9087
p.VFSOptions = fields[sepIdx+3]
9188

92-
// Run a filter early so we can skip parsing/adding entries
93-
// the caller is not interested in
94-
var skip, stop bool
95-
if filter != nil {
96-
skip, stop = filter(p)
97-
if skip {
98-
continue
99-
}
100-
}
101-
102-
// Fill in the rest of the fields
103-
10489
// ignore any numbers parsing errors, as there should not be any
10590
p.ID, _ = strconv.Atoi(fields[0])
10691
p.Parent, _ = strconv.Atoi(fields[1])
@@ -128,11 +113,23 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
128113
p.Optional = strings.Join(fields[6:sepIdx-1], " ")
129114
}
130115

116+
// Run the filter after parsing all of the fields.
117+
var skip, stop bool
118+
if filter != nil {
119+
skip, stop = filter(p)
120+
if skip {
121+
continue
122+
}
123+
}
124+
131125
out = append(out, p)
132126
if stop {
133127
break
134128
}
135129
}
130+
if err := s.Err(); err != nil {
131+
return nil, err
132+
}
136133
return out, nil
137134
}
138135

mountinfo/mountinfo_linux_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,33 @@ func TestParseFedoraMountinfoFields(t *testing.T) {
477477
}
478478
}
479479

480+
func TestParseFedoraMountinfoFilterFields(t *testing.T) {
481+
r := bytes.NewBuffer([]byte(fedoraMountinfo))
482+
_, err := GetMountsFromReader(r, func(info *Info) (skip bool, stop bool) {
483+
mi := Info{
484+
ID: 15,
485+
Parent: 35,
486+
Major: 0,
487+
Minor: 3,
488+
Root: "/",
489+
Mountpoint: "/proc",
490+
Options: "rw,nosuid,nodev,noexec,relatime",
491+
Optional: "shared:5",
492+
FSType: "proc",
493+
Source: "proc",
494+
VFSOptions: "rw",
495+
}
496+
if *info != mi {
497+
t.Fatalf("expected %#v, got %#v", mi, *info)
498+
}
499+
// Only match the first entry as in TestParseFedoraMountinfoFields.
500+
return false, true
501+
})
502+
if err != nil {
503+
t.Fatal(err)
504+
}
505+
}
506+
480507
func TestParseMountinfoWithSpaces(t *testing.T) {
481508
r := bytes.NewBuffer([]byte(mountInfoWithSpaces))
482509
infos, err := GetMountsFromReader(r, nil)

0 commit comments

Comments
 (0)