mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 09:17:50 +00:00
Support persist props bypassing property_service
This commit is contained in:
parent
f8d62a4b6c
commit
dc61033b2c
@ -75,6 +75,9 @@ PB_BIND(PersistentProperties_PersistentPropertyRecord, PersistentProperties_Pers
|
|||||||
* End of auto generated code
|
* End of auto generated code
|
||||||
* ***************************/
|
* ***************************/
|
||||||
|
|
||||||
|
#define PERSIST_PROP_DIR "/data/property"
|
||||||
|
#define PERSIST_PROP PERSIST_PROP_DIR "/persistent_properties"
|
||||||
|
|
||||||
static bool name_decode(pb_istream_t *stream, const pb_field_t *, void **arg) {
|
static bool name_decode(pb_istream_t *stream, const pb_field_t *, void **arg) {
|
||||||
string &name = *static_cast<string *>(*arg);
|
string &name = *static_cast<string *>(*arg);
|
||||||
name.resize(stream->bytes_left);
|
name.resize(stream->bytes_left);
|
||||||
@ -102,7 +105,7 @@ static bool prop_encode(pb_ostream_t *stream, const pb_field_t *field, void * co
|
|||||||
PersistentProperties_PersistentPropertyRecord prop{};
|
PersistentProperties_PersistentPropertyRecord prop{};
|
||||||
prop.name.funcs.encode = name_encode;
|
prop.name.funcs.encode = name_encode;
|
||||||
prop.has_value = true;
|
prop.has_value = true;
|
||||||
auto &list = *static_cast<prop_list *>(*arg);
|
prop_list &list = *static_cast<prop_list *>(*arg);
|
||||||
for (auto &p : list) {
|
for (auto &p : list) {
|
||||||
if (!pb_encode_tag_for_field(stream, field))
|
if (!pb_encode_tag_for_field(stream, field))
|
||||||
return false;
|
return false;
|
||||||
@ -119,8 +122,7 @@ static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t coun
|
|||||||
return xwrite(fd, buf, count) == count;
|
return xwrite(fd, buf, count) == count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pb_ostream_t create_ostream(const char *filename) {
|
static pb_ostream_t create_ostream(int fd) {
|
||||||
int fd = creat(filename, 0644);
|
|
||||||
pb_ostream_t o = {
|
pb_ostream_t o = {
|
||||||
.callback = write_callback,
|
.callback = write_callback,
|
||||||
.state = (void*)(intptr_t)fd,
|
.state = (void*)(intptr_t)fd,
|
||||||
@ -130,19 +132,40 @@ static pb_ostream_t create_ostream(const char *filename) {
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pb_getprop(prop_cb *prop_cb) {
|
static void pb_get_prop(prop_cb *prop_cb) {
|
||||||
LOGD("resetprop: decode with protobuf [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n");
|
LOGD("resetprop: decode with protobuf [" PERSIST_PROP "]\n");
|
||||||
PersistentProperties props = {};
|
PersistentProperties props{};
|
||||||
props.properties.funcs.decode = prop_decode;
|
props.properties.funcs.decode = prop_decode;
|
||||||
props.properties.arg = prop_cb;
|
props.properties.arg = prop_cb;
|
||||||
auto m = mmap_data(PERSISTENT_PROPERTY_DIR "/persistent_properties");
|
auto m = mmap_data(PERSIST_PROP);
|
||||||
pb_istream_t stream = pb_istream_from_buffer(m.buf, m.sz);
|
pb_istream_t stream = pb_istream_from_buffer(m.buf, m.sz);
|
||||||
pb_decode(&stream, &PersistentProperties_msg, &props);
|
pb_decode(&stream, &PersistentProperties_msg, &props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool file_getprop(const char *name, char *value) {
|
static bool pb_write_props(prop_list &list) {
|
||||||
|
char tmp[4096];
|
||||||
|
strscpy(tmp, PERSIST_PROP ".XXXXXX", sizeof(tmp));
|
||||||
|
int fd = mkostemp(tmp, O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pb_ostream_t ostream = create_ostream(fd);
|
||||||
|
PersistentProperties props{};
|
||||||
|
props.properties.funcs.encode = prop_encode;
|
||||||
|
props.properties.arg = &list;
|
||||||
|
LOGD("resetprop: encode with protobuf [%s]\n", tmp);
|
||||||
|
bool ret = pb_encode(&ostream, &PersistentProperties_msg, &props);
|
||||||
|
close(fd);
|
||||||
|
if (!ret)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
clone_attr(PERSIST_PROP, tmp);
|
||||||
|
return rename(tmp, PERSIST_PROP) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool file_get_prop(const char *name, char *value) {
|
||||||
char path[4096];
|
char path[4096];
|
||||||
ssprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
|
ssprintf(path, sizeof(path), PERSIST_PROP_DIR "/%s", name);
|
||||||
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return false;
|
return false;
|
||||||
@ -152,20 +175,38 @@ static bool file_getprop(const char *name, char *value) {
|
|||||||
return value[0] != '\0';
|
return value[0] != '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool file_set_prop(const char *name, const char *value) {
|
||||||
|
char tmp[4096];
|
||||||
|
strscpy(tmp, PERSIST_PROP_DIR "/prop.XXXXXX", sizeof(tmp));
|
||||||
|
int fd = mkostemp(tmp, O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
return false;
|
||||||
|
auto len = strlen(value);
|
||||||
|
LOGD("resetprop: write prop to [%s]\n", tmp);
|
||||||
|
bool ret = write(fd, value, len) == len;
|
||||||
|
close(fd);
|
||||||
|
if (!ret)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char path[4096];
|
||||||
|
ssprintf(path, sizeof(path), PERSIST_PROP_DIR "/%s", name);
|
||||||
|
return rename(tmp, path) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool check_pb() {
|
static bool check_pb() {
|
||||||
static bool use_pb = access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0;
|
static bool use_pb = access(PERSIST_PROP, R_OK) == 0;
|
||||||
return use_pb;
|
return use_pb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void persist_getprops(prop_cb *prop_cb) {
|
void persist_get_props(prop_cb *prop_cb) {
|
||||||
if (check_pb()) {
|
if (check_pb()) {
|
||||||
pb_getprop(prop_cb);
|
pb_get_prop(prop_cb);
|
||||||
} else {
|
} else {
|
||||||
auto dir = open_dir(PERSISTENT_PROPERTY_DIR);
|
auto dir = open_dir(PERSIST_PROP_DIR);
|
||||||
if (!dir) return;
|
if (!dir) return;
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
|
||||||
char value[PROP_VALUE_MAX];
|
char value[PROP_VALUE_MAX];
|
||||||
if (file_getprop(entry->d_name, value))
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
|
if (file_get_prop(entry->d_name, value))
|
||||||
prop_cb->exec(entry->d_name, value);
|
prop_cb->exec(entry->d_name, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,63 +215,48 @@ void persist_getprops(prop_cb *prop_cb) {
|
|||||||
struct match_prop_name : prop_cb {
|
struct match_prop_name : prop_cb {
|
||||||
explicit match_prop_name(const char *name) : _name(name) { value[0] = '\0'; }
|
explicit match_prop_name(const char *name) : _name(name) { value[0] = '\0'; }
|
||||||
void exec(const char *name, const char *val) override {
|
void exec(const char *name, const char *val) override {
|
||||||
if (std::strcmp(name, _name) == 0)
|
if (value[0] == '\0' && _name == name)
|
||||||
strscpy(value, val, sizeof(value));
|
strscpy(value, val, sizeof(value));
|
||||||
}
|
}
|
||||||
char value[PROP_VALUE_MAX];
|
char value[PROP_VALUE_MAX];
|
||||||
private:
|
private:
|
||||||
const char *_name;
|
string_view _name;
|
||||||
};
|
};
|
||||||
|
|
||||||
string persist_getprop(const char *name) {
|
string persist_get_prop(const char *name) {
|
||||||
if (check_pb()) {
|
if (check_pb()) {
|
||||||
auto prop = match_prop_name(name);
|
match_prop_name cb(name);
|
||||||
pb_getprop(&prop);
|
pb_get_prop(&cb);
|
||||||
if (prop.value[0]) {
|
if (cb.value[0]) {
|
||||||
LOGD("resetprop: get prop (persist) [%s]: [%s]\n", name, prop.value);
|
LOGD("resetprop: get prop (persist) [%s]: [%s]\n", name, cb.value);
|
||||||
return prop.value;
|
return cb.value;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Try to read from file
|
// Try to read from file
|
||||||
char value[PROP_VALUE_MAX];
|
char value[PROP_VALUE_MAX];
|
||||||
if (file_getprop(name, value)) {
|
if (file_get_prop(name, value)) {
|
||||||
LOGD("resetprop: get prop (persist) [%s]: [%s]\n", name, value);
|
LOGD("resetprop: get prop (persist) [%s]: [%s]\n", name, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return string();
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool persist_deleteprop(const char *name) {
|
bool persist_delete_prop(const char *name) {
|
||||||
if (check_pb()) {
|
if (check_pb()) {
|
||||||
prop_list list;
|
prop_list list;
|
||||||
prop_collector collector(list);
|
prop_collector collector(list);
|
||||||
persist_getprops(&collector);
|
pb_get_prop(&collector);
|
||||||
|
|
||||||
for (auto it = list.begin(); it != list.end(); ++it) {
|
auto it = list.find(name);
|
||||||
if (it->first == name) {
|
if (it != list.end()) {
|
||||||
list.erase(it);
|
list.erase(it);
|
||||||
// Dump the props back
|
return pb_write_props(list);
|
||||||
PersistentProperties props{};
|
|
||||||
pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR
|
|
||||||
"/persistent_properties.tmp");
|
|
||||||
props.properties.funcs.encode = prop_encode;
|
|
||||||
props.properties.arg = &list;
|
|
||||||
LOGD("resetprop: encode with protobuf [" PERSISTENT_PROPERTY_DIR
|
|
||||||
"/persistent_properties.tmp]\n");
|
|
||||||
if (!pb_encode(&ostream, &PersistentProperties_msg, &props))
|
|
||||||
return false;
|
|
||||||
clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties",
|
|
||||||
PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp");
|
|
||||||
rename(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp",
|
|
||||||
PERSISTENT_PROPERTY_DIR "/persistent_properties");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
char path[4096];
|
char path[4096];
|
||||||
ssprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
|
ssprintf(path, sizeof(path), PERSIST_PROP_DIR "/%s", name);
|
||||||
if (unlink(path) == 0) {
|
if (unlink(path) == 0) {
|
||||||
LOGD("resetprop: unlink [%s]\n", path);
|
LOGD("resetprop: unlink [%s]\n", path);
|
||||||
return true;
|
return true;
|
||||||
@ -238,3 +264,15 @@ bool persist_deleteprop(const char *name) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool persist_set_prop(const char *name, const char *value) {
|
||||||
|
if (check_pb()) {
|
||||||
|
prop_list list;
|
||||||
|
prop_collector collector(list);
|
||||||
|
pb_get_prop(&collector);
|
||||||
|
list[name] = value;
|
||||||
|
return pb_write_props(list);
|
||||||
|
} else {
|
||||||
|
return file_set_prop(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -154,6 +154,12 @@ static int set_prop(const char *name, const char *value, PropFlags flags) {
|
|||||||
LOGD("resetprop: create prop [%s]: [%s] by %s\n", name, value, msg);
|
LOGD("resetprop: create prop [%s]: [%s] by %s\n", name, value, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When bypassing property_service, persistent props won't be stored in storage.
|
||||||
|
// Explicitly handle this situation.
|
||||||
|
if (ret == 0 && flags.isSkipSvc() && flags.isPersist() && str_starts(name, "persist.")) {
|
||||||
|
ret = persist_set_prop(name, value) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
LOGW("resetprop: set prop error\n");
|
LOGW("resetprop: set prop error\n");
|
||||||
}
|
}
|
||||||
@ -172,15 +178,15 @@ static string get_prop(const char *name, PropFlags flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string val;
|
string val;
|
||||||
auto pi = system_property_find(name);
|
if (auto pi = system_property_find(name)) {
|
||||||
if (pi == nullptr)
|
prop_to_string cb(val);
|
||||||
return val;
|
|
||||||
auto cb = prop_to_string(val);
|
|
||||||
read_prop_with_cb(pi, &cb);
|
read_prop_with_cb(pi, &cb);
|
||||||
LOGD("resetprop: get prop [%s]: [%s]\n", name, val.data());
|
LOGD("resetprop: get prop [%s]: [%s]\n", name, val.data());
|
||||||
|
}
|
||||||
|
|
||||||
if (val.empty() && flags.isPersist() && str_starts(name, "persist."))
|
if (val.empty() && flags.isPersist() && str_starts(name, "persist."))
|
||||||
val = persist_getprop(name);
|
val = persist_get_prop(name);
|
||||||
|
|
||||||
if (val.empty())
|
if (val.empty())
|
||||||
LOGD("resetprop: prop [%s] does not exist\n", name);
|
LOGD("resetprop: prop [%s] does not exist\n", name);
|
||||||
return val;
|
return val;
|
||||||
@ -191,7 +197,7 @@ static void print_props(PropFlags flags) {
|
|||||||
prop_collector collector(list);
|
prop_collector collector(list);
|
||||||
system_property_foreach(read_prop_with_cb, &collector);
|
system_property_foreach(read_prop_with_cb, &collector);
|
||||||
if (flags.isPersist())
|
if (flags.isPersist())
|
||||||
persist_getprops(&collector);
|
persist_get_props(&collector);
|
||||||
for (auto &[key, val] : list) {
|
for (auto &[key, val] : list) {
|
||||||
const char *v = flags.isContext() ?
|
const char *v = flags.isContext() ?
|
||||||
(__system_property_get_context(key.data()) ?: "") :
|
(__system_property_get_context(key.data()) ?: "") :
|
||||||
@ -208,7 +214,7 @@ static int delete_prop(const char *name, PropFlags flags) {
|
|||||||
|
|
||||||
int ret = __system_property_delete(name, true);
|
int ret = __system_property_delete(name, true);
|
||||||
if (flags.isPersist() && str_starts(name, "persist.")) {
|
if (flags.isPersist() && str_starts(name, "persist.")) {
|
||||||
if (persist_deleteprop(name))
|
if (persist_delete_prop(name))
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
||||||
#include <api/_system_properties.h>
|
#include <api/_system_properties.h>
|
||||||
|
|
||||||
#define PERSISTENT_PROPERTY_DIR "/data/property"
|
|
||||||
|
|
||||||
struct prop_cb {
|
struct prop_cb {
|
||||||
virtual void exec(const char *name, const char *value) = 0;
|
virtual void exec(const char *name, const char *value) = 0;
|
||||||
};
|
};
|
||||||
@ -23,6 +21,7 @@ private:
|
|||||||
prop_list &list;
|
prop_list &list;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string persist_getprop(const char *name);
|
std::string persist_get_prop(const char *name);
|
||||||
void persist_getprops(prop_cb *prop_cb);
|
void persist_get_props(prop_cb *prop_cb);
|
||||||
bool persist_deleteprop(const char *name);
|
bool persist_delete_prop(const char *name);
|
||||||
|
bool persist_set_prop(const char *name, const char *value);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user