mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-01-11 19:03:37 +00:00
Modernize database code (again)
This commit is contained in:
parent
6597b7adc0
commit
370015a853
@ -752,7 +752,7 @@ core_only:
|
||||
} else {
|
||||
// Check whether we have a valid manager installed
|
||||
db_strings str;
|
||||
get_db_strings(&str, SU_MANAGER);
|
||||
get_db_strings(str, SU_MANAGER);
|
||||
if (validate_manager(str[SU_MANAGER], 0, nullptr)) {
|
||||
// There is no manager installed, install the stub
|
||||
exec_command_sync("/sbin/magiskinit", "-x", "manager", "/data/magisk.apk");
|
||||
|
@ -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 (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;
|
||||
}
|
||||
if (key[0] && value >= 0) {
|
||||
cfg[key] = value;
|
||||
LOGD("magiskdb: query %s=[%d]\n", key, value);
|
||||
}
|
||||
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,
|
||||
|
@ -1,8 +1,11 @@
|
||||
#ifndef DB_H
|
||||
#define DB_H
|
||||
#pragma once
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <sys/stat.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <functional>
|
||||
|
||||
#define db_err(e) db_err_cmd(e, )
|
||||
#define db_err_cmd(e, cmd) if (e) { \
|
||||
@ -11,6 +14,30 @@
|
||||
cmd;\
|
||||
}
|
||||
|
||||
template <class T, size_t num>
|
||||
class db_data_base {
|
||||
public:
|
||||
T& operator [](std::string_view key) {
|
||||
return data[getKeyIdx(key)];
|
||||
}
|
||||
|
||||
const T& operator [](std::string_view key) const {
|
||||
return data[getKeyIdx(key)];
|
||||
}
|
||||
|
||||
T& operator [](int key) {
|
||||
return data[key];
|
||||
}
|
||||
|
||||
const T& operator [](int key) const {
|
||||
return data[key];
|
||||
}
|
||||
|
||||
protected:
|
||||
T data[num + 1];
|
||||
virtual int getKeyIdx(std::string_view key) const = 0;
|
||||
};
|
||||
|
||||
/***************
|
||||
* DB Settings *
|
||||
***************/
|
||||
@ -55,17 +82,12 @@ enum {
|
||||
NAMESPACE_MODE_ISOLATE
|
||||
};
|
||||
|
||||
class db_settings {
|
||||
class db_settings : public db_data_base<int, DB_SETTINGS_NUM> {
|
||||
public:
|
||||
db_settings();
|
||||
int& operator [](const char *);
|
||||
const int& operator [](const char *) const;
|
||||
int& operator [](const int);
|
||||
const int& operator [](const int) const;
|
||||
|
||||
private:
|
||||
int data[DB_SETTINGS_NUM + 1];
|
||||
int getKeyIdx(const char *) const;
|
||||
protected:
|
||||
int getKeyIdx(std::string_view key) const override;
|
||||
};
|
||||
|
||||
/**************
|
||||
@ -84,17 +106,9 @@ enum {
|
||||
SU_MANAGER = 0
|
||||
};
|
||||
|
||||
class db_strings {
|
||||
public:
|
||||
db_strings();
|
||||
char * operator [](const char *);
|
||||
const char * operator [](const char *) const;
|
||||
char * operator [](const int);
|
||||
const char * operator [](const int) const;
|
||||
|
||||
private:
|
||||
char data[DB_STRING_NUM + 1][128];
|
||||
int getKeyIdx(const char *) const;
|
||||
class db_strings : public db_data_base<std::string, DB_STRING_NUM> {
|
||||
protected:
|
||||
int getKeyIdx(std::string_view key) const override;
|
||||
};
|
||||
|
||||
/*************
|
||||
@ -135,12 +149,14 @@ struct su_access {
|
||||
* Public Functions *
|
||||
********************/
|
||||
|
||||
sqlite3 *get_magiskdb(sqlite3 *&db);
|
||||
int get_db_settings(db_settings *dbs, int key = -1);
|
||||
int get_db_strings(db_strings *str, int key = -1);
|
||||
int get_uid_policy(int uid, struct su_access *su);
|
||||
int validate_manager(char *alt_pkg, int userid, struct stat *st);
|
||||
void exec_sql(int client);
|
||||
char *db_exec(const char *sql, int (*cb)(void *, int, char**, char**) = nullptr, void *v = nullptr);
|
||||
typedef std::map<std::string_view, std::string_view> db_row;
|
||||
typedef std::function<bool(db_row&)> db_row_cb;
|
||||
|
||||
int get_db_settings(db_settings &cfg, int key = -1);
|
||||
int get_db_strings(db_strings &str, int key = -1);
|
||||
int get_uid_policy(int uid, su_access &su);
|
||||
int validate_manager(std::string &alt_pkg, int userid, struct stat *st);
|
||||
void exec_sql(int client);
|
||||
char *db_exec(const char *sql);
|
||||
char *db_exec(const char *sql, const db_row_cb &fn);
|
||||
|
||||
#endif //DB_H
|
||||
|
@ -204,24 +204,15 @@ static void init_list(const char *pkg, const char *proc) {
|
||||
kill_process(proc);
|
||||
}
|
||||
|
||||
static int db_init_list(void *, int col_num, char **data, char **cols) {
|
||||
char *pkg, *proc;
|
||||
for (int i = 0; i < col_num; ++i) {
|
||||
if (strcmp(cols[i], "package_name") == 0)
|
||||
pkg = data[i];
|
||||
else if (strcmp(cols[i], "process") == 0)
|
||||
proc = data[i];
|
||||
}
|
||||
init_list(pkg, proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LEGACY_LIST MODULEROOT "/.core/hidelist"
|
||||
|
||||
bool init_list() {
|
||||
LOGD("hide_list: initialize\n");
|
||||
|
||||
char *err = db_exec("SELECT * FROM hidelist", db_init_list);
|
||||
char *err = db_exec("SELECT * FROM hidelist", [](db_row &row) -> bool {
|
||||
init_list(row["package_name"].data(), row["process"].data());
|
||||
return true;
|
||||
});
|
||||
db_err_cmd(err, return false);
|
||||
|
||||
// Migrate old hide list into database
|
||||
@ -328,7 +319,7 @@ int stop_magiskhide() {
|
||||
|
||||
void auto_start_magiskhide() {
|
||||
db_settings dbs;
|
||||
get_db_settings(&dbs, HIDE_CONFIG);
|
||||
get_db_settings(dbs, HIDE_CONFIG);
|
||||
if (dbs[HIDE_CONFIG]) {
|
||||
new_daemon_thread([](auto) -> void* {
|
||||
launch_magiskhide(-1);
|
||||
|
@ -33,7 +33,7 @@ static inline const char *get_command(const struct su_request *to) {
|
||||
|
||||
static void silent_run(const char **args, struct su_info *info) {
|
||||
char component[128];
|
||||
sprintf(component, "%s/a.h", info->str[SU_MANAGER]);
|
||||
sprintf(component, "%s/a.h", info->str[SU_MANAGER].data());
|
||||
args[5] = component;
|
||||
exec_t exec {
|
||||
.pre_exec = []() -> void {
|
||||
|
@ -23,9 +23,9 @@ public:
|
||||
int count; /* Just a count for debugging purpose */
|
||||
|
||||
/* These values should be guarded with internal lock */
|
||||
struct db_settings cfg;
|
||||
struct db_strings str;
|
||||
struct su_access access;
|
||||
db_settings cfg;
|
||||
db_strings str;
|
||||
su_access access;
|
||||
struct stat mgr_st;
|
||||
|
||||
/* These should be guarded with global cache lock */
|
||||
|
@ -63,8 +63,8 @@ void su_info::deRef() {
|
||||
|
||||
static void database_check(su_info *info) {
|
||||
int uid = info->uid;
|
||||
get_db_settings(&info->cfg);
|
||||
get_db_strings(&info->str);
|
||||
get_db_settings(info->cfg);
|
||||
get_db_strings(info->str);
|
||||
|
||||
// Check multiuser settings
|
||||
switch (info->cfg[SU_MULTIUSER_MODE]) {
|
||||
@ -83,7 +83,7 @@ static void database_check(su_info *info) {
|
||||
}
|
||||
|
||||
if (uid > 0)
|
||||
get_uid_policy(uid, &info->access);
|
||||
get_uid_policy(uid, info->access);
|
||||
|
||||
// We need to check our manager
|
||||
if (info->access.log || info->access.notify)
|
||||
|
Loading…
x
Reference in New Issue
Block a user