summaryrefslogtreecommitdiffhomepage
path: root/test/util
diff options
context:
space:
mode:
authorAdin Scannell <ascannell@google.com>2021-04-26 16:25:26 -0700
committergVisor bot <gvisor-bot@google.com>2021-04-26 16:27:45 -0700
commit36fdc6c9ef565be34f5ab27affed31eb2430e89a (patch)
treeb7f7abab391f1c9664b5a14ed6f786560d2afc49 /test/util
parent5b7b7daa425ffc93e98c12cbd37ea7b15a8bcc8d (diff)
Handle tmpfs with 5 fields in /proc/mounts parsing.
PiperOrigin-RevId: 370565903
Diffstat (limited to 'test/util')
-rw-r--r--test/util/BUILD12
-rw-r--r--test/util/mount_util.cc32
-rw-r--r--test/util/mount_util.h10
-rw-r--r--test/util/mount_util_test.cc47
4 files changed, 90 insertions, 11 deletions
diff --git a/test/util/BUILD b/test/util/BUILD
index 6feda0e26..8985b54af 100644
--- a/test/util/BUILD
+++ b/test/util/BUILD
@@ -149,6 +149,18 @@ cc_library(
],
)
+cc_test(
+ name = "mount_util_test",
+ size = "small",
+ srcs = ["mount_util_test.cc"],
+ deps = [
+ ":mount_util",
+ ":test_main",
+ ":test_util",
+ gtest,
+ ],
+)
+
cc_library(
name = "save_util",
testonly = 1,
diff --git a/test/util/mount_util.cc b/test/util/mount_util.cc
index a79ce6420..48640d6a1 100644
--- a/test/util/mount_util.cc
+++ b/test/util/mount_util.cc
@@ -26,9 +26,14 @@ namespace testing {
PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries() {
std::string content;
RETURN_IF_ERRNO(GetContents("/proc/self/mounts", &content));
+ return ProcSelfMountsEntriesFrom(content);
+}
+PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntriesFrom(
+ const std::string& content) {
std::vector<ProcMountsEntry> entries;
- std::vector<std::string> lines = absl::StrSplit(content, '\n');
+ std::vector<std::string> lines =
+ absl::StrSplit(content, absl::ByChar('\n'), absl::AllowEmpty());
std::cerr << "<contents of /proc/self/mounts>" << std::endl;
for (const std::string& line : lines) {
std::cerr << line << std::endl;
@@ -47,11 +52,11 @@ PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries() {
ProcMountsEntry entry;
std::vector<std::string> fields =
- absl::StrSplit(line, absl::ByChar(' '), absl::SkipEmpty());
+ absl::StrSplit(line, absl::ByChar(' '), absl::AllowEmpty());
if (fields.size() != 6) {
- return PosixError(EINVAL,
- absl::StrFormat("Not enough tokens, got %d, line: %s",
- fields.size(), line));
+ return PosixError(
+ EINVAL, absl::StrFormat("Not enough tokens, got %d, content: <<%s>>",
+ fields.size(), content));
}
entry.spec = fields[0];
@@ -71,9 +76,14 @@ PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries() {
PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntries() {
std::string content;
RETURN_IF_ERRNO(GetContents("/proc/self/mountinfo", &content));
+ return ProcSelfMountInfoEntriesFrom(content);
+}
+PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntriesFrom(
+ const std::string& content) {
std::vector<ProcMountInfoEntry> entries;
- std::vector<std::string> lines = absl::StrSplit(content, '\n');
+ std::vector<std::string> lines =
+ absl::StrSplit(content, absl::ByChar('\n'), absl::AllowEmpty());
std::cerr << "<contents of /proc/self/mountinfo>" << std::endl;
for (const std::string& line : lines) {
std::cerr << line << std::endl;
@@ -92,12 +102,12 @@ PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntries() {
ProcMountInfoEntry entry;
std::vector<std::string> fields =
- absl::StrSplit(line, absl::ByChar(' '), absl::SkipEmpty());
+ absl::StrSplit(line, absl::ByChar(' '), absl::AllowEmpty());
if (fields.size() < 10 || fields.size() > 11) {
return PosixError(
- EINVAL,
- absl::StrFormat("Unexpected number of tokens, got %d, line: %s",
- fields.size(), line));
+ EINVAL, absl::StrFormat(
+ "Unexpected number of tokens, got %d, content: <<%s>>",
+ fields.size(), content));
}
ASSIGN_OR_RETURN_ERRNO(entry.id, Atoi<uint64_t>(fields[0]));
@@ -142,7 +152,7 @@ absl::flat_hash_map<std::string, std::string> ParseMountOptions(
std::string mopts) {
absl::flat_hash_map<std::string, std::string> entries;
const std::vector<std::string> tokens =
- absl::StrSplit(mopts, absl::ByChar(','), absl::SkipEmpty());
+ absl::StrSplit(mopts, absl::ByChar(','), absl::AllowEmpty());
for (const auto& token : tokens) {
std::vector<std::string> kv =
absl::StrSplit(token, absl::MaxSplits('=', 1));
diff --git a/test/util/mount_util.h b/test/util/mount_util.h
index b75a490fb..3f8a1c0f1 100644
--- a/test/util/mount_util.h
+++ b/test/util/mount_util.h
@@ -58,6 +58,11 @@ struct ProcMountsEntry {
// ProcSelfMountsEntries returns a parsed representation of /proc/self/mounts.
PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries();
+// ProcSelfMountsEntries returns a parsed representation of mounts from the
+// provided content.
+PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntriesFrom(
+ const std::string& content);
+
struct ProcMountInfoEntry {
uint64_t id;
uint64_t parent_id;
@@ -76,6 +81,11 @@ struct ProcMountInfoEntry {
// /proc/self/mountinfo.
PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntries();
+// ProcSelfMountInfoEntriesFrom returns a parsed representation of
+// mountinfo from the provided content.
+PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntriesFrom(
+ const std::string&);
+
// Interprets the input string mopts as a comma separated list of mount
// options. A mount option can either be just a value, or a key=value pair. For
// example, the string "rw,relatime,fd=7" will be parsed into a map like { "rw":
diff --git a/test/util/mount_util_test.cc b/test/util/mount_util_test.cc
new file mode 100644
index 000000000..2bcb6cc43
--- /dev/null
+++ b/test/util/mount_util_test.cc
@@ -0,0 +1,47 @@
+// Copyright 2018 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "test/util/mount_util.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "test/util/test_util.h"
+
+namespace gvisor {
+namespace testing {
+
+namespace {
+
+TEST(ParseMounts, Mounts) {
+ auto entries = ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountsEntriesFrom(
+ R"proc(sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
+proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
+ /mnt tmpfs rw,noexec 0 0
+)proc"));
+ EXPECT_EQ(entries.size(), 3);
+}
+
+TEST(ParseMounts, MountInfo) {
+ auto entries = ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntriesFrom(
+ R"proc(22 28 0:20 / /sys rw,relatime shared:7 - sysfs sysfs rw
+23 28 0:21 / /proc rw,relatime shared:14 - proc proc rw
+2007 8844 0:278 / /mnt rw,noexec - tmpfs rw,mode=123,uid=268601820,gid=5000
+)proc"));
+ EXPECT_EQ(entries.size(), 3);
+}
+
+} // namespace
+
+} // namespace testing
+} // namespace gvisor