Merge "canned_fs_config.cpp is written in C++"
This commit is contained in:
commit
badd64bdbd
2 changed files with 75 additions and 78 deletions
|
@ -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",
|
||||
|
|
|
@ -18,111 +18,107 @@
|
|||
#include <private/canned_fs_config.h>
|
||||
#include <private/fs_config.h>
|
||||
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
|
||||
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<std::string> 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<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);
|
||||
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<Entry*>(
|
||||
bsearch(path, &canned_data[0], canned_data.size(), sizeof(Entry),
|
||||
[](const void* a, const void* b) -> int {
|
||||
return strcmp(static_cast<const char*>(a),
|
||||
static_cast<const Entry*>(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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue