Modernize database code (again)

This commit is contained in:
topjohnwu
2019-03-06 08:16:12 -05:00
parent 6597b7adc0
commit 370015a853
7 changed files with 141 additions and 181 deletions

View File

@@ -11,64 +11,31 @@
#define DB_VERSION 9
using namespace std;
static sqlite3 *mDB = nullptr;
db_strings::db_strings() {
memset(data, 0, sizeof(data));
}
char *db_strings::operator[](const char *key) {
return data[getKeyIdx(key)];
}
const char *db_strings::operator[](const char *key) const {
return data[getKeyIdx(key)];
}
char *db_strings::operator[](const int idx) {
return data[idx];
}
const char *db_strings::operator[](const int idx) const {
return data[idx];
}
int db_strings::getKeyIdx(const char *key) const {
int db_strings::getKeyIdx(string_view key) const {
int idx = DB_STRING_NUM;
for (int i = 0; i < DB_STRING_NUM; ++i) {
if (strcmp(key, DB_STRING_KEYS[i]) == 0)
if (key == DB_STRING_KEYS[i])
idx = i;
}
return idx;
}
db_settings::db_settings() : data {
ROOT_ACCESS_APPS_AND_ADB,
MULTIUSER_MODE_OWNER_ONLY,
NAMESPACE_MODE_REQUESTER,
1
} {}
int &db_settings::operator[](const int idx) {
return data[idx];
db_settings::db_settings() {
// Default settings
data[0] = ROOT_ACCESS_APPS_AND_ADB;
data[1] = MULTIUSER_MODE_OWNER_ONLY;
data[2] = NAMESPACE_MODE_REQUESTER;
data[3] = 1;
}
const int &db_settings::operator[](const int idx) const {
return data[idx];
}
int &db_settings::operator[](const char *key) {
return data[getKeyIdx(key)];
}
const int &db_settings::operator[](const char *key) const {
return data[getKeyIdx(key)];
}
int db_settings::getKeyIdx(const char *key) const {
int db_settings::getKeyIdx(string_view key) const {
int idx = DB_SETTINGS_NUM;
for (int i = 0; i < DB_SETTINGS_NUM; ++i) {
if (strcmp(key, DB_SETTING_KEYS[i]) == 0)
if (key == DB_SETTING_KEYS[i])
idx = i;
}
return idx;
@@ -187,7 +154,7 @@ static char *open_and_init_db(sqlite3 *&db) {
return nullptr;
}
char *db_exec(const char *sql, int (*cb)(void *, int, char**, char**), void *v) {
char *db_exec(const char *sql) {
char *err;
if (mDB == nullptr) {
err = open_and_init_db(mDB);
@@ -199,139 +166,125 @@ char *db_exec(const char *sql, int (*cb)(void *, int, char**, char**), void *v)
);
}
if (mDB) {
sqlite3_exec(mDB, sql, cb, v, &err);
sqlite3_exec(mDB, sql, nullptr, nullptr, &err);
return err;
}
return nullptr;
}
static int settings_cb(void *v, int col_num, char **data, char **col_name) {
auto &cfg = *(db_settings *) v;
int value = -1;
const char *key = "";
for (int i = 0; i < col_num; ++i) {
if (strcmp(col_name[i], "key") == 0) {
key = data[i];
} else if (strcmp(col_name[i], "value") == 0) {
value = atoi(data[i]);
}
char *db_exec(const char *sql, const db_row_cb &fn) {
char *err;
if (mDB == nullptr) {
err = open_and_init_db(mDB);
db_err_cmd(err,
// Open fails, remove and reconstruct
unlink(MAGISKDB);
err = open_and_init_db(mDB);
err_ret(err);
);
}
if (key[0] && value >= 0) {
cfg[key] = value;
LOGD("magiskdb: query %s=[%d]\n", key, value);
if (mDB) {
sqlite3_exec(mDB, sql, [](void *cb, int col_num, char **data, char **col_name) -> int {
auto &func = *reinterpret_cast<const db_row_cb*>(cb);
db_row row;
for (int i = 0; i < col_num; ++i)
row[col_name[i]] = data[i];
return func(row) ? 0 : 1;
}, (void *) &fn, &err);
return err;
}
return 0;
return nullptr;
}
int get_db_settings(db_settings *dbs, int key) {
int get_db_settings(db_settings &cfg, int key) {
char *err;
auto settings_cb = [&](db_row &row) -> bool {
cfg[row["key"]] = atoi(row["value"].data());
LOGD("magiskdb: query %s=[%s]\n", row["key"].data(), row["value"].data());
return true;
};
if (key >= 0) {
char query[128];
sprintf(query, "SELECT key, value FROM settings WHERE key='%s'", DB_SETTING_KEYS[key]);
err = db_exec(query, settings_cb, dbs);
err = db_exec(query, settings_cb);
} else {
err = db_exec("SELECT key, value FROM settings", settings_cb, dbs);
err = db_exec("SELECT key, value FROM settings", settings_cb);
}
db_err_cmd(err, return 1);
return 0;
}
static int strings_cb(void *v, int col_num, char **data, char **col_name) {
auto &str = *(db_strings *) v;
const char *key = "", *value = "";
for (int i = 0; i < col_num; ++i) {
if (strcmp(col_name[i], "key") == 0) {
key = data[i];
} else if (strcmp(col_name[i], "value") == 0) {
value = data[i];
}
}
if (key[0] && value[0]) {
strcpy(str[key], value);
LOGD("magiskdb: query %s=[%s]\n", key, value);
}
return 0;
}
int get_db_strings(db_strings *str, int key) {
int get_db_strings(db_strings &str, int key) {
char *err;
auto string_cb = [&](db_row &row) -> bool {
str[row["key"]] = row["value"];
LOGD("magiskdb: query %s=[%s]\n", row["key"].data(), row["value"].data());
return true;
};
if (key >= 0) {
char query[128];
sprintf(query, "SELECT key, value FROM strings WHERE key='%s'", DB_STRING_KEYS[key]);
err = db_exec(query, strings_cb, str);
err = db_exec(query, string_cb);
} else {
err = db_exec("SELECT key, value FROM strings", strings_cb, str);
err = db_exec("SELECT key, value FROM strings", string_cb);
}
if (err) {
LOGE("sqlite3_exec: %s\n", err);
sqlite3_free(err);
return 1;
}
return 0;
}
static int policy_cb(void *v, int col_num, char **data, char **col_name) {
auto su = (su_access *) v;
for (int i = 0; i < col_num; i++) {
if (strcmp(col_name[i], "policy") == 0)
su->policy = (policy_t) atoi(data[i]);
else if (strcmp(col_name[i], "logging") == 0)
su->log = atoi(data[i]);
else if (strcmp(col_name[i], "notification") == 0)
su->notify = atoi(data[i]);
}
LOGD("magiskdb: query policy=[%d] log=[%d] notify=[%d]\n", su->policy, su->log, su->notify);
return 0;
}
int get_uid_policy(int uid, struct su_access *su) {
char query[256], *err;
sprintf(query, "SELECT policy, logging, notification FROM policies "
"WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr));
err = db_exec(query, policy_cb, su);
db_err_cmd(err, return 1);
return 0;
}
int validate_manager(char *alt_pkg, int userid, struct stat *st) {
if (st == nullptr) {
struct stat stat;
st = &stat;
}
int get_uid_policy(int uid, su_access &su) {
char query[256], *err;
sprintf(query, "SELECT policy, logging, notification FROM policies "
"WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr));
err = db_exec(query, [&](db_row &row) -> bool {
su.policy = (policy_t) atoi(row["policy"].data());
su.log = atoi(row["logging"].data());
su.notify = atoi(row["notification"].data());
LOGD("magiskdb: query policy=[%d] log=[%d] notify=[%d]\n", su.policy, su.log, su.notify);
return true;
});
db_err_cmd(err, return 1);
return 0;
}
int validate_manager(string &alt_pkg, int userid, struct stat *st) {
struct stat tmp_st;
if (st == nullptr)
st = &tmp_st;
// Prefer DE storage
const char *base = access("/data/user_de", F_OK) == 0 ? "/data/user_de" : "/data/user";
char app_path[128];
sprintf(app_path, "%s/%d/%s", base, userid, alt_pkg[0] ? alt_pkg : "xxx");
sprintf(app_path, "%s/%d/%s", base, userid, alt_pkg.empty() ? "xxx" : alt_pkg.data());
if (stat(app_path, st)) {
// Check the official package name
sprintf(app_path, "%s/%d/" JAVA_PACKAGE_NAME, base, userid);
if (stat(app_path, st)) {
LOGE("su: cannot find manager");
memset(st, 0, sizeof(*st));
alt_pkg[0] = '\0';
alt_pkg.clear();
return 1;
} else {
// Switch to official package if exists
strcpy(alt_pkg, JAVA_PACKAGE_NAME);
alt_pkg = JAVA_PACKAGE_NAME;
}
}
return 0;
}
static int print_cb(void *v, int col_num, char **data, char **col_name) {
FILE *out = (FILE *) v;
for (int i = 0; i < col_num; ++i) {
if (i) fprintf(out, "|");
fprintf(out, "%s=%s", col_name[i], data[i]);
}
fprintf(out, "\n");
return 0;
}
void exec_sql(int client) {
char *sql = read_string(client);
FILE *out = fdopen(recv_fd(client), "a");
char *err = db_exec(sql, print_cb, out);
char *err = db_exec(sql, [&](db_row &row) -> bool {
bool first = false;
for (auto it : row) {
if (first) fprintf(out, "|");
else first = true;
fprintf(out, "%s=%s", it.first.data(), it.second.data());
}
fprintf(out, "\n");
return true;
});
free(sql);
fclose(out);
db_err_cmd(err,