From d8602917f0d8e595a130312e2f44b3805a9cdcae Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 13 Dec 2021 13:11:10 +0900 Subject: [PATCH] canned_fs_config.cpp is written in C++ This re-writes the file using C++, in preparation for a follow-up change. Also, removes debugging code that is no longer used. Bug: 209971551 Test: m Change-Id: I82a793cfdd7abd10024e304df7bd4ae323ffeabf --- libcutils/Android.bp | 3 +- libcutils/canned_fs_config.cpp | 150 ++++++++++++++++----------------- 2 files changed, 75 insertions(+), 78 deletions(-) diff --git a/libcutils/Android.bp b/libcutils/Android.bp index 0d9f2c79a..c8bfb0194 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..a7686e3cc 100644 --- a/libcutils/canned_fs_config.cpp +++ b/libcutils/canned_fs_config.cpp @@ -18,111 +18,107 @@ #include #include +#include + #include +#include #include #include #include #include #include -typedef struct { - const char* path; +#include +#include +#include +#include +#include + +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 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; - - while (canned_used >= canned_alloc) { - canned_alloc = (canned_alloc+1) * 2; - canned_data = (Path*) realloc(canned_data, canned_alloc * sizeof(Path)); + 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(), '/'); } - 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); + std::vector tokens = Tokenize(line, " "); + if (tokens.size() < 4) { + std::cerr << "Ill-formed line: " << line << " in " << fn << std::endl; + return -1; + } + + // Historical: remove the leading '/' if exists. + std::string path = tokens[0].front() == '/' ? std::string(tokens[0], 1) : tokens[0]; + + Entry e{ + .path = path, + .uid = static_cast(atoi(tokens[1].c_str())), + .gid = static_cast(atoi(tokens[2].c_str())), + // mode is in octal + .mode = static_cast(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); + std::sort(canned_data.begin(), canned_data.end(), + [](const Entry& a, const Entry& b) -> bool { return a.path < b.path; }); + 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, [[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 '/' -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; + 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()); + })); - 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; }