Handle tmpfs with 5 fields in /proc/mounts parsing.
PiperOrigin-RevId: 370565903
This commit is contained in:
parent
5b7b7daa42
commit
36fdc6c9ef
|
@ -45,6 +45,7 @@ namespace testing {
|
|||
|
||||
namespace {
|
||||
|
||||
using ::testing::AnyOf;
|
||||
using ::testing::Contains;
|
||||
using ::testing::Pair;
|
||||
|
||||
|
@ -360,7 +361,8 @@ TEST(MountTest, MountInfo) {
|
|||
if (e.mount_point == dir.path()) {
|
||||
EXPECT_EQ(e.fstype, "tmpfs");
|
||||
auto mopts = ParseMountOptions(e.mount_opts);
|
||||
EXPECT_THAT(mopts, Contains(Pair("mode", "0123")));
|
||||
EXPECT_THAT(mopts, AnyOf(Contains(Pair("mode", "0123")),
|
||||
Contains(Pair("mode", "123"))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,7 +373,8 @@ TEST(MountTest, MountInfo) {
|
|||
if (e.mount_point == dir.path()) {
|
||||
EXPECT_EQ(e.fstype, "tmpfs");
|
||||
auto mopts = ParseMountOptions(e.super_opts);
|
||||
EXPECT_THAT(mopts, Contains(Pair("mode", "0123")));
|
||||
EXPECT_THAT(mopts, AnyOf(Contains(Pair("mode", "0123")),
|
||||
Contains(Pair("mode", "123"))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue