mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-18 04:48:30 +00:00
Migrate resetprop to C++
This commit is contained in:
parent
b8a3cc8b60
commit
11c33d4447
@ -43,8 +43,8 @@ LOCAL_SRC_FILES := \
|
|||||||
magiskhide/magiskhide.cpp \
|
magiskhide/magiskhide.cpp \
|
||||||
magiskhide/proc_monitor.cpp \
|
magiskhide/proc_monitor.cpp \
|
||||||
magiskhide/hide_utils.cpp \
|
magiskhide/hide_utils.cpp \
|
||||||
resetprop/persist_properties.c \
|
resetprop/persist_properties.cpp \
|
||||||
resetprop/resetprop.c \
|
resetprop/resetprop.cpp \
|
||||||
resetprop/system_property_api.cpp \
|
resetprop/system_property_api.cpp \
|
||||||
resetprop/system_property_set.cpp \
|
resetprop/system_property_set.cpp \
|
||||||
su/su.c \
|
su/su.c \
|
||||||
|
@ -8,21 +8,49 @@
|
|||||||
#include "resetprop/private/system_properties.h"
|
#include "resetprop/private/system_properties.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
extern int prop_verbose;
|
|
||||||
|
|
||||||
struct prop_t {
|
struct prop_t {
|
||||||
char *name;
|
char *name;
|
||||||
char value[PROP_VALUE_MAX];
|
char value[PROP_VALUE_MAX];
|
||||||
|
prop_t() = default;
|
||||||
|
prop_t(const char *name) {
|
||||||
|
this->name = strdup(name);
|
||||||
|
}
|
||||||
|
prop_t(const char *name, const char *value) {
|
||||||
|
this->name = strdup(name);
|
||||||
|
strcpy(this->value, value);
|
||||||
|
}
|
||||||
|
prop_t& operator= (prop_t&& prop) {
|
||||||
|
if (this != &prop) {
|
||||||
|
free(name);
|
||||||
|
name = prop.name;
|
||||||
|
strcpy(value, prop.value);
|
||||||
|
prop.name = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
};
|
||||||
|
~prop_t() {
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct read_cb_t {
|
struct read_cb_t {
|
||||||
void (*func)(const char *name, const char *value, void *cookie);
|
void (*cb)(const char *, const char *, void *);
|
||||||
void *cookie;
|
void *arg;
|
||||||
|
read_cb_t() = default;
|
||||||
|
read_cb_t(void (*cb)(const char *, const char *, void *), void *arg)
|
||||||
|
: cb(cb), arg(arg) {}
|
||||||
|
void exec(const char *name, const char *value) {
|
||||||
|
cb(name, value, arg);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PERSISTENT_PROPERTY_DIR "/data/property"
|
||||||
|
|
||||||
|
extern bool use_pb;
|
||||||
|
|
||||||
char *persist_getprop(const char *name);
|
char *persist_getprop(const char *name);
|
||||||
void persist_getprop_all(struct read_cb_t *read_cb);
|
void persist_getprop_all(read_cb_t *read_cb);
|
||||||
bool persist_deleteprop(const char *name);
|
bool persist_deleteprop(const char *name);
|
||||||
void collect_props(const char *name, const char *value, void *prop_list);
|
void collect_props(const char *name, const char *value, void *v_plist);
|
||||||
|
|
||||||
#endif //MAGISK_PROPS_H
|
#endif //MAGISK_PROPS_H
|
||||||
|
@ -11,9 +11,7 @@
|
|||||||
|
|
||||||
#include "_resetprop.h"
|
#include "_resetprop.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "vector.h"
|
#include "array.h"
|
||||||
|
|
||||||
#define PERSISTENT_PROPERTY_DIR "/data/property"
|
|
||||||
|
|
||||||
/* ***********************************************************************
|
/* ***********************************************************************
|
||||||
* Auto generated header and constant definitions compiled from
|
* Auto generated header and constant definitions compiled from
|
||||||
@ -89,7 +87,7 @@ const pb_field_t PersistentProperties_fields[2] = {
|
|||||||
* ***************************/
|
* ***************************/
|
||||||
|
|
||||||
static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
|
static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
|
||||||
uint8_t *name = xmalloc(stream->bytes_left + 1);
|
uint8_t *name = (uint8_t *) xmalloc(stream->bytes_left + 1);
|
||||||
name[stream->bytes_left] = '\0';
|
name[stream->bytes_left] = '\0';
|
||||||
if (!pb_read(stream, name, stream->bytes_left))
|
if (!pb_read(stream, name, stream->bytes_left))
|
||||||
return false;
|
return false;
|
||||||
@ -98,7 +96,8 @@ static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **ar
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool name_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
|
static bool name_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
|
||||||
return pb_encode_tag_for_field(stream, field) && pb_encode_string(stream, *arg, strlen(*arg));
|
return pb_encode_tag_for_field(stream, field) &&
|
||||||
|
pb_encode_string(stream, (const pb_byte_t *) *arg, strlen((const char *) *arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
|
static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
|
||||||
@ -106,8 +105,7 @@ static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **ar
|
|||||||
prop.name.funcs.decode = name_decode;
|
prop.name.funcs.decode = name_decode;
|
||||||
if (!pb_decode(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop))
|
if (!pb_decode(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop))
|
||||||
return false;
|
return false;
|
||||||
struct read_cb_t *read_cb = *arg;
|
((read_cb_t *) *arg)->exec((const char *) prop.name.arg, prop.value);
|
||||||
read_cb->func(prop.name.arg, prop.value, read_cb->cookie);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,19 +113,14 @@ 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;
|
||||||
struct vector *v = *arg;
|
Array<prop_t> &prop_list = *(Array<prop_t> *) *arg;
|
||||||
struct prop_t *e;
|
for (auto &p : prop_list) {
|
||||||
vec_for_each(v, e) {
|
|
||||||
if (e == NULL)
|
|
||||||
continue;
|
|
||||||
if (!pb_encode_tag_for_field(stream, field))
|
if (!pb_encode_tag_for_field(stream, field))
|
||||||
return false;
|
return false;
|
||||||
prop.name.arg = e->name;
|
prop.name.arg = p.name;
|
||||||
strcpy(prop.value, e->value);
|
strcpy(prop.value, p.value);
|
||||||
if (!pb_encode_submessage(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop))
|
if (!pb_encode_submessage(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop))
|
||||||
return false;
|
return false;
|
||||||
free(e->name);
|
|
||||||
free(e);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -139,22 +132,27 @@ static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t coun
|
|||||||
|
|
||||||
static pb_ostream_t create_ostream(const char *filename) {
|
static pb_ostream_t create_ostream(const char *filename) {
|
||||||
int fd = creat(filename, 0644);
|
int fd = creat(filename, 0644);
|
||||||
pb_ostream_t o = {&write_callback, (void*)(intptr_t)fd, SIZE_MAX, 0};
|
pb_ostream_t o = {
|
||||||
|
.callback = write_callback,
|
||||||
|
.state = (void*)(intptr_t)fd,
|
||||||
|
.max_size = SIZE_MAX,
|
||||||
|
.bytes_written = 0,
|
||||||
|
};
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pb_getprop_cb(const char *name, const char *value, void *v) {
|
static void pb_getprop_cb(const char *name, const char *value, void *v) {
|
||||||
struct prop_t *prop = v;
|
struct prop_t *prop = static_cast<prop_t *>(v);
|
||||||
if (prop->name && strcmp(name, prop->name) == 0) {
|
if (prop->name && strcmp(name, prop->name) == 0) {
|
||||||
strcpy(prop->value, value);
|
strcpy(prop->value, value);
|
||||||
prop->name = NULL;
|
free(prop->name);
|
||||||
|
prop->name = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void persist_getprop_all(struct read_cb_t *read_cb) {
|
static void pb_getprop_all(read_cb_t *read_cb) {
|
||||||
if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) {
|
LOGD("resetprop: decode with protobuf [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n");
|
||||||
LOGD("resetprop: decode with protobuf from [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n");
|
PersistentProperties props = {};
|
||||||
PersistentProperties props = PersistentProperties_init_zero;
|
|
||||||
props.properties.funcs.decode = prop_decode;
|
props.properties.funcs.decode = prop_decode;
|
||||||
props.properties.arg = read_cb;
|
props.properties.arg = read_cb;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
@ -163,83 +161,82 @@ void persist_getprop_all(struct read_cb_t *read_cb) {
|
|||||||
pb_istream_t stream = pb_istream_from_buffer(buf, size);
|
pb_istream_t stream = pb_istream_from_buffer(buf, size);
|
||||||
pb_decode(&stream, PersistentProperties_fields, &props);
|
pb_decode(&stream, PersistentProperties_fields, &props);
|
||||||
munmap(buf, size);
|
munmap(buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void file_getprop(const char *name, char *value) {
|
||||||
|
value[0] = '\0';
|
||||||
|
char path[PATH_MAX];
|
||||||
|
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
|
||||||
|
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
return;
|
||||||
|
LOGD("resetprop: read prop from [%s]\n", path);
|
||||||
|
value[read(fd, value, sizeof(PROP_VALUE_MAX))] = '\0'; // Null terminate the read value
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void persist_getprop_all(read_cb_t *read_cb) {
|
||||||
|
if (use_pb) {
|
||||||
|
pb_getprop_all(read_cb);
|
||||||
} else {
|
} else {
|
||||||
DIR *dir = opendir(PERSISTENT_PROPERTY_DIR);
|
DIR *dir = opendir(PERSISTENT_PROPERTY_DIR);
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
while ((entry = readdir(dir))) {
|
while ((entry = readdir(dir))) {
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 )
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 )
|
||||||
continue;
|
continue;
|
||||||
char *value = persist_getprop(entry->d_name);
|
char value[PROP_VALUE_MAX];
|
||||||
if (value) {
|
file_getprop(entry->d_name, value);
|
||||||
read_cb->func(strdup(entry->d_name), value, read_cb->cookie);
|
if (value[0])
|
||||||
free(value);
|
read_cb->exec(entry->d_name, value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *persist_getprop(const char *name) {
|
char *persist_getprop(const char *name) {
|
||||||
struct prop_t prop;
|
prop_t prop(name);
|
||||||
prop.name = (char *) name;
|
if (use_pb) {
|
||||||
if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) {
|
struct read_cb_t read_cb(pb_getprop_cb, &prop);
|
||||||
struct read_cb_t read_cb = {
|
pb_getprop_all(&read_cb);
|
||||||
.func = pb_getprop_cb,
|
if (prop.name == nullptr)
|
||||||
.cookie = &prop
|
return strdup(prop.value);
|
||||||
};
|
|
||||||
persist_getprop_all(&read_cb);
|
|
||||||
if (prop.name)
|
|
||||||
return NULL;
|
|
||||||
} else {
|
} else {
|
||||||
// Try to read from file
|
// Try to read from file
|
||||||
char path[PATH_MAX];
|
char value[PROP_VALUE_MAX];
|
||||||
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
|
file_getprop(name, value);
|
||||||
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
if (value[0])
|
||||||
if (fd < 0)
|
return strdup(value);
|
||||||
return NULL;
|
|
||||||
LOGD("resetprop: read prop from [%s]\n", path);
|
|
||||||
prop.value[read(fd, prop.value, sizeof(PROP_VALUE_MAX))] = '\0'; // Null terminate the read value
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
return strdup(prop.value);
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool persist_deleteprop(const char *name) {
|
bool persist_deleteprop(const char *name) {
|
||||||
if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) {
|
if (use_pb) {
|
||||||
struct vector v;
|
auto prop_list = Array<prop_t>();
|
||||||
vec_init(&v);
|
struct read_cb_t read_cb(collect_props, &prop_list);
|
||||||
struct read_cb_t read_cb = {
|
|
||||||
.func = collect_props,
|
|
||||||
.cookie = &v
|
|
||||||
};
|
|
||||||
persist_getprop_all(&read_cb);
|
persist_getprop_all(&read_cb);
|
||||||
struct prop_t *p;
|
|
||||||
bool reencode = false;
|
|
||||||
vec_for_each(&v, p) {
|
|
||||||
if (strcmp(p->name, name) == 0) {
|
|
||||||
// Remove the prop from the list
|
|
||||||
free(p->name);
|
|
||||||
free(p);
|
|
||||||
vec_cur(&v) = NULL;
|
|
||||||
reencode = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reencode) {
|
for (auto it = prop_list.begin(); it != prop_list.end(); ++it) {
|
||||||
|
if (strcmp((*it).name, name) == 0) {
|
||||||
|
prop_list.erase(it);
|
||||||
// Dump the props back
|
// Dump the props back
|
||||||
PersistentProperties props = PersistentProperties_init_zero;
|
PersistentProperties props = PersistentProperties_init_zero;
|
||||||
pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp");
|
pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR
|
||||||
|
"/persistent_properties.tmp");
|
||||||
props.properties.funcs.encode = prop_encode;
|
props.properties.funcs.encode = prop_encode;
|
||||||
props.properties.arg = &v;
|
props.properties.arg = &prop_list;
|
||||||
LOGD("resetprop: encode with protobuf to [" PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp]\n");
|
LOGD("resetprop: encode with protobuf [" PERSISTENT_PROPERTY_DIR
|
||||||
|
"/persistent_properties.tmp]\n");
|
||||||
if (!pb_encode(&ostream, PersistentProperties_fields, &props))
|
if (!pb_encode(&ostream, PersistentProperties_fields, &props))
|
||||||
return false;
|
return false;
|
||||||
clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties", PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp");
|
clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties",
|
||||||
rename(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp", 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec_destroy(&v);
|
return false;
|
||||||
return reencode;
|
|
||||||
} else {
|
} else {
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
|
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
|
@ -20,13 +20,14 @@
|
|||||||
#include "magisk.h"
|
#include "magisk.h"
|
||||||
#include "resetprop.h"
|
#include "resetprop.h"
|
||||||
#include "_resetprop.h"
|
#include "_resetprop.h"
|
||||||
#include "vector.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "array.h"
|
||||||
#include "flags.h"
|
#include "flags.h"
|
||||||
|
|
||||||
int prop_verbose = 0;
|
bool use_pb = false;
|
||||||
|
static bool verbose = false;
|
||||||
|
|
||||||
static int check_legal_property_name(const char *name) {
|
static bool check_legal_property_name(const char *name) {
|
||||||
int namelen = strlen(name);
|
int namelen = strlen(name);
|
||||||
|
|
||||||
if (namelen < 1) goto illegal;
|
if (namelen < 1) goto illegal;
|
||||||
@ -48,14 +49,14 @@ static int check_legal_property_name(const char *name) {
|
|||||||
goto illegal;
|
goto illegal;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
|
|
||||||
illegal:
|
illegal:
|
||||||
LOGE("Illegal property name: [%s]\n", name);
|
LOGE("Illegal property name: [%s]\n", name);
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage(char* arg0) {
|
[[noreturn]] static void usage(char* arg0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"resetprop v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu & nkk71) - System Props Modification Tool\n\n"
|
"resetprop v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu & nkk71) - System Props Modification Tool\n\n"
|
||||||
"Usage: %s [flags] [options...]\n"
|
"Usage: %s [flags] [options...]\n"
|
||||||
@ -77,53 +78,39 @@ static int usage(char* arg0) {
|
|||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
, arg0);
|
, arg0);
|
||||||
return 1;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The callback passes to __system_property_read_callback, actually runs the callback in read_cb
|
// Define the way to sort prop_t
|
||||||
static void callback_wrapper(void *read_cb, const char *name, const char *value, uint32_t serial) {
|
template<>
|
||||||
((struct read_cb_t *) read_cb)->func(name, value, ((struct read_cb_t *) read_cb)->cookie);
|
int(*Array<prop_t>::_cmp)(prop_t&, prop_t&) = [](auto a, auto b) -> int {
|
||||||
|
return strcmp(a.name, b.name);
|
||||||
|
};
|
||||||
|
|
||||||
|
static void read_props(const prop_info *pi, void *read_cb) {
|
||||||
|
__system_property_read_callback(
|
||||||
|
pi, [](auto cb, auto name, auto value, auto) -> void
|
||||||
|
{
|
||||||
|
((read_cb_t *) cb)->exec(name, value);
|
||||||
|
}, read_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* **********************************
|
void collect_props(const char *name, const char *value, void *v_plist) {
|
||||||
* Callback functions for read_cb_t
|
Array<prop_t> &prop_list = *static_cast<Array<prop_t> *>(v_plist);
|
||||||
* **********************************/
|
prop_list.push_back(prop_t(name, value));
|
||||||
|
|
||||||
void collect_props(const char *name, const char *value, void *prop_list) {
|
|
||||||
struct prop_t *p = (struct prop_t *) xmalloc(sizeof(*p));
|
|
||||||
p->name = strdup(name);
|
|
||||||
strcpy(p->value, value);
|
|
||||||
vec_push_back(prop_list, p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collect_unique_props(const char *name, const char *value, void *prop_list) {
|
static void collect_unique_props(const char *name, const char *value, void *v_plist) {
|
||||||
struct vector *v = prop_list;
|
Array<prop_t> &prop_list = *static_cast<Array<prop_t> *>(v_plist);
|
||||||
struct prop_t *p;
|
for (auto &prop : prop_list) {
|
||||||
bool uniq = true;
|
if (strcmp(name, prop.name) == 0)
|
||||||
vec_for_each(v, p) {
|
return;
|
||||||
if (strcmp(name, p->name) == 0) {
|
|
||||||
uniq = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
collect_props(name, value, v_plist);
|
||||||
if (uniq)
|
|
||||||
collect_props(name, value, prop_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void store_prop_value(const char *name, const char *value, void *dst) {
|
|
||||||
strcpy(dst, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void prop_foreach_cb(const prop_info* pi, void* read_cb) {
|
|
||||||
__system_property_read_callback(pi, callback_wrapper, read_cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comparision function used to sort prop vectors
|
|
||||||
static int prop_cmp(const void *p1, const void *p2) {
|
|
||||||
return strcmp(((struct prop_t *) p1)->name, ((struct prop_t *) p2)->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_resetprop() {
|
static int init_resetprop() {
|
||||||
|
use_pb = use_pb ? true : access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0;
|
||||||
if (__system_properties_init()) {
|
if (__system_properties_init()) {
|
||||||
LOGE("resetprop: Initialize error\n");
|
LOGE("resetprop: Initialize error\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -132,24 +119,15 @@ static int init_resetprop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void print_props(int persist) {
|
static void print_props(int persist) {
|
||||||
struct prop_t *p;
|
auto prop_list = Array<prop_t>();
|
||||||
struct vector prop_list;
|
|
||||||
vec_init(&prop_list);
|
|
||||||
getprop_all(collect_props, &prop_list);
|
getprop_all(collect_props, &prop_list);
|
||||||
if (persist) {
|
if (persist) {
|
||||||
struct read_cb_t read_cb = {
|
read_cb_t read_cb(collect_unique_props, &prop_list);
|
||||||
.func = collect_unique_props,
|
|
||||||
.cookie = &prop_list
|
|
||||||
};
|
|
||||||
persist_getprop_all(&read_cb);
|
persist_getprop_all(&read_cb);
|
||||||
}
|
}
|
||||||
vec_sort(&prop_list, prop_cmp);
|
prop_list.sort();
|
||||||
vec_for_each(&prop_list, p) {
|
for (auto &prop : prop_list)
|
||||||
printf("[%s]: [%s]\n", p->name, p->value);
|
printf("[%s]: [%s]\n", prop.name, prop.value);
|
||||||
free(p->name);
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
vec_destroy(&prop_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* **************************************************
|
/* **************************************************
|
||||||
@ -158,7 +136,7 @@ static void print_props(int persist) {
|
|||||||
|
|
||||||
int prop_exist(const char *name) {
|
int prop_exist(const char *name) {
|
||||||
if (init_resetprop()) return 0;
|
if (init_resetprop()) return 0;
|
||||||
return __system_property_find(name) != NULL;
|
return __system_property_find(name) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *getprop(const char *name) {
|
char *getprop(const char *name) {
|
||||||
@ -167,25 +145,23 @@ char *getprop(const char *name) {
|
|||||||
|
|
||||||
// Get prop by name, return string (should free manually!)
|
// Get prop by name, return string (should free manually!)
|
||||||
char *getprop2(const char *name, int persist) {
|
char *getprop2(const char *name, int persist) {
|
||||||
if (check_legal_property_name(name))
|
if (!check_legal_property_name(name) || init_resetprop())
|
||||||
return NULL;
|
return nullptr;
|
||||||
if (init_resetprop()) return NULL;
|
|
||||||
const prop_info *pi = __system_property_find(name);
|
const prop_info *pi = __system_property_find(name);
|
||||||
if (pi == NULL) {
|
if (pi == nullptr) {
|
||||||
if (persist && strncmp(name, "persist.", 8) == 0) {
|
if (persist && strncmp(name, "persist.", 8) == 0) {
|
||||||
char *value = persist_getprop(name);
|
char *value = persist_getprop(name);
|
||||||
if (value)
|
if (value)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
LOGD("resetprop: prop [%s] does not exist\n", name);
|
LOGD("resetprop: prop [%s] does not exist\n", name);
|
||||||
return NULL;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
char value[PROP_VALUE_MAX];
|
char value[PROP_VALUE_MAX];
|
||||||
struct read_cb_t read_cb = {
|
read_cb_t read_cb;
|
||||||
.func = store_prop_value,
|
read_cb.cb = [](auto, auto value, auto dst) -> void { strcpy((char *) dst, value); };
|
||||||
.cookie = value
|
read_cb.arg = value;
|
||||||
};
|
read_props(pi, &read_cb);
|
||||||
__system_property_read_callback(pi, callback_wrapper, &read_cb);
|
|
||||||
LOGD("resetprop: getprop [%s]: [%s]\n", name, value);
|
LOGD("resetprop: getprop [%s]: [%s]\n", name, value);
|
||||||
return strdup(value);
|
return strdup(value);
|
||||||
}
|
}
|
||||||
@ -193,11 +169,8 @@ char *getprop2(const char *name, int persist) {
|
|||||||
|
|
||||||
void getprop_all(void (*callback)(const char *, const char *, void *), void *cookie) {
|
void getprop_all(void (*callback)(const char *, const char *, void *), void *cookie) {
|
||||||
if (init_resetprop()) return;
|
if (init_resetprop()) return;
|
||||||
struct read_cb_t read_cb = {
|
read_cb_t read_cb(callback, cookie);
|
||||||
.func = callback,
|
__system_property_foreach(read_props, &read_cb);
|
||||||
.cookie = cookie
|
|
||||||
};
|
|
||||||
__system_property_foreach(prop_foreach_cb, &read_cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int setprop(const char *name, const char *value) {
|
int setprop(const char *name, const char *value) {
|
||||||
@ -205,13 +178,15 @@ int setprop(const char *name, const char *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int setprop2(const char *name, const char *value, const int trigger) {
|
int setprop2(const char *name, const char *value, const int trigger) {
|
||||||
if (check_legal_property_name(name))
|
if (!check_legal_property_name(name))
|
||||||
return 1;
|
return 1;
|
||||||
if (init_resetprop()) return -1;
|
if (init_resetprop())
|
||||||
|
return -1;
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
prop_info *pi = (prop_info*) __system_property_find(name);
|
prop_info *pi = (prop_info*) __system_property_find(name);
|
||||||
if (pi != NULL) {
|
if (pi != nullptr) {
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
if (strncmp(name, "ro.", 3) == 0) deleteprop(name);
|
if (strncmp(name, "ro.", 3) == 0) deleteprop(name);
|
||||||
ret = __system_property_set(name, value);
|
ret = __system_property_set(name, value);
|
||||||
@ -241,7 +216,7 @@ int deleteprop(const char *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int deleteprop2(const char *name, int persist) {
|
int deleteprop2(const char *name, int persist) {
|
||||||
if (check_legal_property_name(name))
|
if (!check_legal_property_name(name))
|
||||||
return 1;
|
return 1;
|
||||||
if (init_resetprop()) return -1;
|
if (init_resetprop()) return -1;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
@ -256,11 +231,11 @@ int read_prop_file(const char* filename, const int trigger) {
|
|||||||
if (init_resetprop()) return -1;
|
if (init_resetprop()) return -1;
|
||||||
LOGD("resetprop: Load prop file [%s]\n", filename);
|
LOGD("resetprop: Load prop file [%s]\n", filename);
|
||||||
FILE *fp = fopen(filename, "r");
|
FILE *fp = fopen(filename, "r");
|
||||||
if (fp == NULL) {
|
if (fp == nullptr) {
|
||||||
LOGE("Cannot open [%s]\n", filename);
|
LOGE("Cannot open [%s]\n", filename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
char *line = NULL, *pch;
|
char *line = nullptr, *pch;
|
||||||
size_t len;
|
size_t len;
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
int comment = 0, i;
|
int comment = 0, i;
|
||||||
@ -283,7 +258,7 @@ int read_prop_file(const char* filename, const int trigger) {
|
|||||||
if (comment) continue;
|
if (comment) continue;
|
||||||
pch = strchr(line, '=');
|
pch = strchr(line, '=');
|
||||||
// Ignore invalid formats
|
// Ignore invalid formats
|
||||||
if ( ((pch == NULL) || (i >= (pch - line))) || (pch >= line + read - 1) ) continue;
|
if ( ((pch == nullptr) || (i >= (pch - line))) || (pch >= line + read - 1) ) continue;
|
||||||
// Separate the string
|
// Separate the string
|
||||||
*pch = '\0';
|
*pch = '\0';
|
||||||
setprop2(line + i, pch + 1, trigger);
|
setprop2(line + i, pch + 1, trigger);
|
||||||
@ -293,12 +268,8 @@ int read_prop_file(const char* filename, const int trigger) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int verbose_logging(const char *fmt, va_list ap) {
|
|
||||||
return prop_verbose ? vfprintf(stderr, fmt, ap) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int resetprop_main(int argc, char *argv[]) {
|
int resetprop_main(int argc, char *argv[]) {
|
||||||
log_cb.d = verbose_logging;
|
log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; };
|
||||||
|
|
||||||
int trigger = 1, persist = 0;
|
int trigger = 1, persist = 0;
|
||||||
char *argv0 = argv[0], *prop;
|
char *argv0 = argv[0], *prop;
|
||||||
@ -316,10 +287,10 @@ int resetprop_main(int argc, char *argv[]) {
|
|||||||
} else if (strcmp(argv[0], "--delete") == 0 && argc == 2) {
|
} else if (strcmp(argv[0], "--delete") == 0 && argc == 2) {
|
||||||
return deleteprop2(argv[1], persist);
|
return deleteprop2(argv[1], persist);
|
||||||
} else if (strcmp(argv[0], "--help") == 0) {
|
} else if (strcmp(argv[0], "--help") == 0) {
|
||||||
goto usage;
|
usage(argv0);
|
||||||
}
|
}
|
||||||
case 'v':
|
case 'v':
|
||||||
prop_verbose = 1;
|
verbose = true;
|
||||||
continue;
|
continue;
|
||||||
case 'p':
|
case 'p':
|
||||||
persist = 1;
|
persist = 1;
|
||||||
@ -331,8 +302,7 @@ int resetprop_main(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
default:
|
default:
|
||||||
usage:
|
usage(argv0);
|
||||||
return usage(argv0);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -346,7 +316,7 @@ int resetprop_main(int argc, char *argv[]) {
|
|||||||
return 0;
|
return 0;
|
||||||
case 1:
|
case 1:
|
||||||
prop = getprop2(argv[0], persist);
|
prop = getprop2(argv[0], persist);
|
||||||
if (prop == NULL) return 1;
|
if (prop == nullptr) return 1;
|
||||||
printf("%s\n", prop);
|
printf("%s\n", prop);
|
||||||
free(prop);
|
free(prop);
|
||||||
return 0;
|
return 0;
|
||||||
@ -354,6 +324,5 @@ int resetprop_main(int argc, char *argv[]) {
|
|||||||
return setprop2(argv[0], argv[1], trigger);
|
return setprop2(argv[0], argv[1], trigger);
|
||||||
default:
|
default:
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,15 +22,18 @@ public:
|
|||||||
++_node;
|
++_node;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator operator ++ (int) {
|
iterator operator ++ (int) {
|
||||||
iterator temp = *this;
|
iterator temp = *this;
|
||||||
++_node;
|
++_node;
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator& operator -- () {
|
iterator& operator -- () {
|
||||||
--_node;
|
--_node;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator operator -- (int) {
|
iterator operator -- (int) {
|
||||||
iterator temp = *this;
|
iterator temp = *this;
|
||||||
--_node;
|
--_node;
|
||||||
@ -42,6 +45,7 @@ public:
|
|||||||
temp += i;
|
temp += i;
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator& operator += (int i) {
|
iterator& operator += (int i) {
|
||||||
_node += i;
|
_node += i;
|
||||||
return (*this);
|
return (*this);
|
||||||
@ -55,6 +59,7 @@ public:
|
|||||||
bool operator != (const iterator& i) const {
|
bool operator != (const iterator& i) const {
|
||||||
return _node != i._node;
|
return _node != i._node;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator == (const iterator& i) const { return !(*this != i); }
|
bool operator == (const iterator& i) const { return !(*this != i); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -62,11 +67,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
iterator begin() const { return iterator(_data); }
|
iterator begin() const { return iterator(_data); }
|
||||||
|
|
||||||
iterator end() const { return iterator(_data + _size); }
|
iterator end() const { return iterator(_data + _size); }
|
||||||
|
|
||||||
bool empty() const { return !_size; }
|
bool empty() const { return !_size; }
|
||||||
|
|
||||||
size_t size() const { return _size; }
|
size_t size() const { return _size; }
|
||||||
|
|
||||||
T& operator [] (size_t i) { return _data[i]; }
|
T& operator [] (size_t i) { return _data[i]; }
|
||||||
|
|
||||||
const T& operator [] (size_t i) const { return _data[i]; }
|
const T& operator [] (size_t i) const { return _data[i]; }
|
||||||
|
|
||||||
const T& back() const { return _data[_size - 1]; }
|
const T& back() const { return _data[_size - 1]; }
|
||||||
@ -78,6 +87,13 @@ public:
|
|||||||
++_size;
|
++_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push_back(T&& x) {
|
||||||
|
if(_size == _capacity)
|
||||||
|
expand();
|
||||||
|
_data[_size] = (T&&) x;
|
||||||
|
++_size;
|
||||||
|
}
|
||||||
|
|
||||||
void pop_front() { erase(begin()); }
|
void pop_front() { erase(begin()); }
|
||||||
|
|
||||||
void pop_back() { if(_size) --_size; }
|
void pop_back() { if(_size) --_size; }
|
||||||
@ -87,7 +103,7 @@ public:
|
|||||||
if (_size == 0 || d < _data || d >= _data + _size)
|
if (_size == 0 || d < _data || d >= _data + _size)
|
||||||
return false;
|
return false;
|
||||||
for (; d < _data + _size - 1; ++d)
|
for (; d < _data + _size - 1; ++d)
|
||||||
*d = *(d + 1);
|
*d = (T&&) *(d + 1);
|
||||||
--_size;
|
--_size;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -129,7 +145,7 @@ private:
|
|||||||
_capacity *= 2;
|
_capacity *= 2;
|
||||||
T* temp = _data;
|
T* temp = _data;
|
||||||
_data = new T[_capacity];
|
_data = new T[_capacity];
|
||||||
for(int i = 0; i < _size; ++i) _data[i] = temp[i];
|
for(int i = 0; i < _size; ++i) _data[i] = (T&&) temp[i];
|
||||||
delete [] temp;
|
delete [] temp;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user