From 4bd3687422df9d3a53ffbcc3d60ba51f3f451fe6 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 13 Dec 2021 13:11:10 +0900 Subject: [PATCH] canned fs_config accepts multiple lines having the same path Previously, each file/dir in a filesystem had to have exactly one matching entry in the canned fs_config file. With this change, the config file can have multiple entries for the same path. e.g. /lib/libfoo.so 1000 1000 0644 /lib/libfoo.so 1000 2000 0644 capabilities=0x30 In this case, the last matching entry is chosen and used. This is to make it possible to customize system-provided (and thus generic) fs_config file with a user-provided (and thus context-specific) one. Bug: 209971551 Test: m Change-Id: I43902fed08db1b4968d02c75fac0a47976fff72a --- libcutils/canned_fs_config.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/libcutils/canned_fs_config.cpp b/libcutils/canned_fs_config.cpp index a7686e3cc..b677949ad 100644 --- a/libcutils/canned_fs_config.cpp +++ b/libcutils/canned_fs_config.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -67,10 +66,10 @@ int load_canned_fs_config(const char* fn) { } // Historical: remove the leading '/' if exists. - std::string path = tokens[0].front() == '/' ? std::string(tokens[0], 1) : tokens[0]; + std::string path(tokens[0].front() == '/' ? std::string(tokens[0], 1) : tokens[0]); Entry e{ - .path = path, + .path = std::move(path), .uid = static_cast(atoi(tokens[1].c_str())), .gid = static_cast(atoi(tokens[2].c_str())), // mode is in octal @@ -93,8 +92,15 @@ int load_canned_fs_config(const char* fn) { canned_data.emplace_back(std::move(e)); } - std::sort(canned_data.begin(), canned_data.end(), - [](const Entry& a, const Entry& b) -> bool { return a.path < b.path; }); + // Note: we used to sort the entries by path names. This was to improve the lookup performance + // by doing binary search. However, this is no longer the case. The lookup performance is not + // critical because this tool runs on the host, not on the device. Now, there can be multiple + // entries for the same path. Then the one that comes the last wins. This is to allow overriding + // platform provided fs_config with a user provided fs_config by appending the latter to the + // former. + // + // To implement the strategy, reverse the entries order, and search from the top. + std::reverse(canned_data.begin(), canned_data.end()); std::cout << "loaded " << canned_data.size() << " fs_config entries" << std::endl; return 0; @@ -105,12 +111,15 @@ void canned_fs_config(const char* path, [[maybe_unused]] int dir, unsigned* mode, uint64_t* capabilities) { if (path != nullptr && path[0] == '/') path++; // canned paths lack the leading '/' - const Entry* found = static_cast( - bsearch(path, &canned_data[0], canned_data.size(), sizeof(Entry), - [](const void* a, const void* b) -> int { - return strcmp(static_cast(a), - static_cast(b)->path.c_str()); - })); + const Entry* found = nullptr; + // canned_data is already reversed. First match wins. + for (const auto& entry : canned_data) { + if (path == entry.path) { + found = &entry; + break; + } + continue; + } if (found == nullptr) { std::cerr << "failed to find " << path << " in canned fs_config" << std::endl;