diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-01-15 13:07:06 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-01-15 13:07:06 +0000 |
commit | 0979e766bf2dee7f6ccf054ed2f59bc08835d125 (patch) | |
tree | 0fe5012e262a64b731e9ad784daacb6ba3c72761 | |
parent | 95231de8aa54492dc5d4cd2582d8893b464ad453 (diff) | |
parent | c0c59c6244381f2ed369e47c18a94d4a43d0c0b2 (diff) | |
download | core-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.bp | 3 | ||||
-rw-r--r-- | libcutils/canned_fs_config.cpp | 165 |
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; } |