summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-01-15 13:07:06 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-01-15 13:07:06 +0000
commit0979e766bf2dee7f6ccf054ed2f59bc08835d125 (patch)
tree0fe5012e262a64b731e9ad784daacb6ba3c72761
parent95231de8aa54492dc5d4cd2582d8893b464ad453 (diff)
parentc0c59c6244381f2ed369e47c18a94d4a43d0c0b2 (diff)
downloadcore-android12-mainline-media-swcodec-release.tar.gz
Snap for 8083882 from c0c59c6244381f2ed369e47c18a94d4a43d0c0b2 to mainline-media-swcodec-releaseandroid-mainline-12.0.0_r91android-mainline-12.0.0_r75android-mainline-12.0.0_r105android12-mainline-media-swcodec-release
Change-Id: I8f1d743a28ab90d47cd2c56a3b9927d2f8140d48
-rw-r--r--libcutils/Android.bp3
-rw-r--r--libcutils/canned_fs_config.cpp165
2 files changed, 87 insertions, 81 deletions
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 68b21c6a0..f1333ddd1 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -156,7 +156,6 @@ cc_library {
},
srcs: [
"config_utils.cpp",
- "canned_fs_config.cpp",
"iosched_policy.cpp",
"load_file.cpp",
"native_handle.cpp",
@@ -173,6 +172,7 @@ cc_library {
not_windows: {
srcs: libcutils_nonwindows_sources + [
"ashmem-host.cpp",
+ "canned_fs_config.cpp",
"fs_config.cpp",
"trace-host.cpp",
],
@@ -193,6 +193,7 @@ cc_library {
srcs: libcutils_nonwindows_sources + [
"android_reboot.cpp",
"ashmem-dev.cpp",
+ "canned_fs_config.cpp",
"fs_config.cpp",
"klog.cpp",
"partition_utils.cpp",
diff --git a/libcutils/canned_fs_config.cpp b/libcutils/canned_fs_config.cpp
index 2772ef0e9..b677949ad 100644
--- a/libcutils/canned_fs_config.cpp
+++ b/libcutils/canned_fs_config.cpp
@@ -18,6 +18,8 @@
#include <private/canned_fs_config.h>
#include <private/fs_config.h>
+#include <android-base/strings.h>
+
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
@@ -25,104 +27,107 @@
#include <stdlib.h>
#include <string.h>
-typedef struct {
- const char* path;
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+using android::base::ConsumePrefix;
+using android::base::StartsWith;
+using android::base::Tokenize;
+
+struct Entry {
+ std::string path;
unsigned uid;
unsigned gid;
unsigned mode;
uint64_t capabilities;
-} Path;
+};
-static Path* canned_data = NULL;
-static int canned_alloc = 0;
-static int canned_used = 0;
-
-static int path_compare(const void* a, const void* b) {
- return strcmp(((Path*)a)->path, ((Path*)b)->path);
-}
+static std::vector<Entry> canned_data;
int load_canned_fs_config(const char* fn) {
- char buf[PATH_MAX + 200];
- FILE* f;
-
- f = fopen(fn, "r");
- if (f == NULL) {
- fprintf(stderr, "failed to open %s: %s\n", fn, strerror(errno));
- return -1;
- }
-
- while (fgets(buf, sizeof(buf), f)) {
- Path* p;
- char* token;
- char* line = buf;
- bool rootdir;
+ std::ifstream input(fn);
+ for (std::string line; std::getline(input, line);) {
+ // Historical: the root dir can be represented as a space character.
+ // e.g. " 1000 1000 0755" is parsed as
+ // path = " ", uid = 1000, gid = 1000, mode = 0755.
+ // But at the same time, we also have accepted
+ // "/ 1000 1000 0755".
+ if (StartsWith(line, " ")) {
+ line.insert(line.begin(), '/');
+ }
- while (canned_used >= canned_alloc) {
- canned_alloc = (canned_alloc+1) * 2;
- canned_data = (Path*) realloc(canned_data, canned_alloc * sizeof(Path));
+ std::vector<std::string> tokens = Tokenize(line, " ");
+ if (tokens.size() < 4) {
+ std::cerr << "Ill-formed line: " << line << " in " << fn << std::endl;
+ return -1;
}
- p = canned_data + canned_used;
- if (line[0] == '/') line++;
- rootdir = line[0] == ' ';
- p->path = strdup(rootdir ? "" : strtok(line, " "));
- p->uid = atoi(strtok(rootdir ? line : NULL, " "));
- p->gid = atoi(strtok(NULL, " "));
- p->mode = strtol(strtok(NULL, " "), NULL, 8); // mode is in octal
- p->capabilities = 0;
-
- do {
- token = strtok(NULL, " ");
- if (token && strncmp(token, "capabilities=", 13) == 0) {
- p->capabilities = strtoll(token+13, NULL, 0);
+
+ // Historical: remove the leading '/' if exists.
+ std::string path(tokens[0].front() == '/' ? std::string(tokens[0], 1) : tokens[0]);
+
+ Entry e{
+ .path = std::move(path),
+ .uid = static_cast<unsigned int>(atoi(tokens[1].c_str())),
+ .gid = static_cast<unsigned int>(atoi(tokens[2].c_str())),
+ // mode is in octal
+ .mode = static_cast<unsigned int>(strtol(tokens[3].c_str(), nullptr, 8)),
+ .capabilities = 0,
+ };
+
+ for (size_t i = 4; i < tokens.size(); i++) {
+ std::string_view sv = tokens[i];
+ if (ConsumePrefix(&sv, "capabilities=")) {
+ e.capabilities = strtoll(std::string(sv).c_str(), nullptr, 0);
break;
}
- } while (token);
+ // Historical: there can be tokens like "selabel=..." here. They have been ignored.
+ // It's not an error because selabels are applied separately in e2fsdroid using the
+ // file_contexts files set via -S option.
+ std::cerr << "info: ignored token \"" << sv << "\" in " << fn << std::endl;
+ }
- canned_used++;
+ canned_data.emplace_back(std::move(e));
}
- fclose(f);
-
- qsort(canned_data, canned_used, sizeof(Path), path_compare);
- printf("loaded %d fs_config entries\n", canned_used);
-
+ // 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;
}
-static const int kDebugCannedFsConfig = 0;
-
-void canned_fs_config(const char* path, int dir, const char* target_out_path,
- unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities) {
- Path key, *p;
+void canned_fs_config(const char* path, [[maybe_unused]] int dir,
+ [[maybe_unused]] const char* target_out_path, unsigned* uid, unsigned* gid,
+ unsigned* mode, uint64_t* capabilities) {
+ if (path != nullptr && path[0] == '/') path++; // canned paths lack the leading '/'
+
+ 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;
+ }
- key.path = path;
- if (path[0] == '/') key.path++; // canned paths lack the leading '/'
- p = (Path*) bsearch(&key, canned_data, canned_used, sizeof(Path), path_compare);
- if (p == NULL) {
- fprintf(stderr, "failed to find [%s] in canned fs_config\n", path);
+ if (found == nullptr) {
+ std::cerr << "failed to find " << path << " in canned fs_config" << std::endl;
exit(1);
}
- *uid = p->uid;
- *gid = p->gid;
- *mode = p->mode;
- *capabilities = p->capabilities;
-
- if (kDebugCannedFsConfig) {
- // for debugging, run the built-in fs_config and compare the results.
-
- unsigned c_uid, c_gid, c_mode;
- uint64_t c_capabilities;
-
- fs_config(path, dir, target_out_path, &c_uid, &c_gid, &c_mode, &c_capabilities);
-
- if (c_uid != *uid) printf("%s uid %d %d\n", path, *uid, c_uid);
- if (c_gid != *gid) printf("%s gid %d %d\n", path, *gid, c_gid);
- if (c_mode != *mode) printf("%s mode 0%o 0%o\n", path, *mode, c_mode);
- if (c_capabilities != *capabilities) {
- printf("%s capabilities %" PRIx64 " %" PRIx64 "\n",
- path,
- *capabilities,
- c_capabilities);
- }
- }
+
+ *uid = found->uid;
+ *gid = found->gid;
+ *mode = found->mode;
+ *capabilities = found->capabilities;
}