From fb491cfdcf017294584b4a55ddae9918ce98f168 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 28 Apr 2018 20:22:42 +0800 Subject: [PATCH] Add Protobuf support to resetprop --- .gitmodules | 3 + native/jni/Android.mk | 9 +- native/jni/external/Android.mk | 10 + native/jni/external/nanopb | 1 + native/jni/include/magisk.h | 7 - native/jni/include/resetprop.h | 10 +- native/jni/magiskhide/hide_utils.c | 4 +- native/jni/resetprop/_resetprop.h | 31 +++ native/jni/resetprop/persist_props.c | 252 ++++++++++++++++++ .../resetprop/{resetprop.cpp => resetprop.c} | 197 +++++++------- 10 files changed, 400 insertions(+), 124 deletions(-) create mode 160000 native/jni/external/nanopb create mode 100644 native/jni/resetprop/_resetprop.h create mode 100644 native/jni/resetprop/persist_props.c rename native/jni/resetprop/{resetprop.cpp => resetprop.c} (69%) diff --git a/.gitmodules b/.gitmodules index f83db1bb1..a0fa7fecc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "xz"] path = native/jni/external/xz url = https://github.com/xz-mirror/xz.git +[submodule "nanopb"] + path = native/jni/external/nanopb + url = https://github.com/nanopb/nanopb.git diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 143d6ec39..a68f651c5 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -9,6 +9,7 @@ LIBLZMA := $(EXT_PATH)/xz/src/liblzma/api LIBLZ4 := $(EXT_PATH)/lz4/lib LIBBZ2 := $(EXT_PATH)/bzip2 LIBFDT := $(EXT_PATH)/dtc/libfdt +LIBNANOPB := $(EXT_PATH)/nanopb UTIL_SRC := utils/cpio.c \ utils/file.c \ utils/img.c \ @@ -28,12 +29,13 @@ ifneq "$(or $(PRECOMPILE), $(GRADLE))" "" include $(CLEAR_VARS) LOCAL_MODULE := magisk LOCAL_SHARED_LIBRARIES := libsqlite libselinux - +LOCAL_STATIC_LIBRARIES := libnanopb LOCAL_C_INCLUDES := \ jni/include \ jni/magiskpolicy \ $(EXT_PATH)/include \ - $(LIBSELINUX) + $(LIBSELINUX) \ + $(LIBNANOPB) LOCAL_SRC_FILES := \ core/magisk.c \ @@ -44,7 +46,8 @@ LOCAL_SRC_FILES := \ magiskhide/magiskhide.c \ magiskhide/proc_monitor.c \ magiskhide/hide_utils.c \ - resetprop/resetprop.cpp \ + resetprop/persist_props.c \ + resetprop/resetprop.c \ resetprop/system_properties.cpp \ su/su.c \ su/activity.c \ diff --git a/native/jni/external/Android.mk b/native/jni/external/Android.mk index c9250e355..00e2e54b4 100644 --- a/native/jni/external/Android.mk +++ b/native/jni/external/Android.mk @@ -28,6 +28,16 @@ LOCAL_SRC_FILES := \ mincrypt/sha256.c include $(BUILD_STATIC_LIBRARY) +# libnanopb.a +include $(CLEAR_VARS) +LOCAL_MODULE:= libnanopb +LOCAL_C_INCLUDES := $(LIBNANOPB) +LOCAL_SRC_FILES := \ + nanopb/pb_common.c \ + nanopb/pb_decode.c \ + nanopb/pb_encode.c +include $(BUILD_STATIC_LIBRARY) + # libfdt.a include $(CLEAR_VARS) LOCAL_MODULE:= libfdt diff --git a/native/jni/external/nanopb b/native/jni/external/nanopb new file mode 160000 index 000000000..04cd1f94c --- /dev/null +++ b/native/jni/external/nanopb @@ -0,0 +1 @@ +Subproject commit 04cd1f94cc513b4cb3eac924c74039ccc05a944b diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index 5caf80dc7..b2f5ee212 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -63,13 +63,6 @@ int create_links(const char *bin, const char *path); int magiskhide_main(int argc, char *argv[]); int magiskpolicy_main(int argc, char *argv[]); int su_client_main(int argc, char *argv[]); - -#ifdef __cplusplus -extern "C" { -#endif int resetprop_main(int argc, char *argv[]); -#ifdef __cplusplus -} -#endif #endif diff --git a/native/jni/include/resetprop.h b/native/jni/include/resetprop.h index 689abbeb7..f04822298 100644 --- a/native/jni/include/resetprop.h +++ b/native/jni/include/resetprop.h @@ -4,10 +4,6 @@ #ifndef _RESETPROP_H_ #define _RESETPROP_H_ -#ifdef __cplusplus -extern "C" { -#endif - int prop_exist(const char *name); int setprop(const char *name, const char *value); int setprop2(const char *name, const char *value, const int trigger); @@ -16,10 +12,6 @@ char *getprop2(const char *name, int persist); int deleteprop(const char *name); int deleteprop2(const char *name, const int persist); int read_prop_file(const char* filename, const int trigger); -void getprop_all(void (*callback)(const char*, const char*)); - -#ifdef __cplusplus -} -#endif +void getprop_all(void (*callback)(const char *, const char *, void *), void *cookie); #endif diff --git a/native/jni/magiskhide/hide_utils.c b/native/jni/magiskhide/hide_utils.c index 4476372e2..eac07cc9b 100644 --- a/native/jni/magiskhide/hide_utils.c +++ b/native/jni/magiskhide/hide_utils.c @@ -56,7 +56,7 @@ void hide_sensitive_props() { } } -static void rm_magisk_prop(const char *name, const char *value) { +static void rm_magisk_prop(const char *name, const char *value, void *v) { if (strstr(name, "magisk")) { deleteprop2(name, 0); } @@ -64,7 +64,7 @@ static void rm_magisk_prop(const char *name, const char *value) { void clean_magisk_props() { LOGD("hide_utils: Cleaning magisk props\n"); - getprop_all(rm_magisk_prop); + getprop_all(rm_magisk_prop, NULL); } int add_list(char *proc) { diff --git a/native/jni/resetprop/_resetprop.h b/native/jni/resetprop/_resetprop.h new file mode 100644 index 000000000..c14bfc0b9 --- /dev/null +++ b/native/jni/resetprop/_resetprop.h @@ -0,0 +1,31 @@ +/* resetprop.h - Internal struct definitions + */ + + +#ifndef MAGISK_PROPS_H +#define MAGISK_PROPS_H + +#include "system_properties.h" +#include "logging.h" + +extern int prop_verbose; + +#define PRINT_D(...) { LOGD(__VA_ARGS__); if (prop_verbose) fprintf(stderr, __VA_ARGS__); } +#define PRINT_E(...) { LOGE(__VA_ARGS__); fprintf(stderr, __VA_ARGS__); } + +struct prop_t { + char *name; + char value[PROP_VALUE_MAX]; +}; + +struct read_cb_t { + void (*func)(const char *name, const char *value, void *cookie); + void *cookie; +}; + +char *persist_getprop(const char *name); +void persist_getprop_all(struct read_cb_t *read_cb); +bool persist_deleteprop(const char *name); +void collect_props(const char *name, const char *value, void *prop_list); + +#endif //MAGISK_PROPS_H diff --git a/native/jni/resetprop/persist_props.c b/native/jni/resetprop/persist_props.c new file mode 100644 index 000000000..bff68e5ef --- /dev/null +++ b/native/jni/resetprop/persist_props.c @@ -0,0 +1,252 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "_resetprop.h" +#include "utils.h" +#include "vector.h" + +#define PERSISTENT_PROPERTY_DIR "/data/property" + +/* *********************************************************************** + * Auto generated header and constant definitions compiled from + * android/platform/system/core/master/init/persistent_properties.proto + * using Nanopb's protoc + * Nanopb: https://github.com/nanopb/nanopb + * ***********************************************************************/ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.1 at Sun Apr 22 14:36:22 2018. */ + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _PersistentProperties { + pb_callback_t properties; +/* @@protoc_insertion_point(struct:PersistentProperties) */ +} PersistentProperties; + +typedef struct _PersistentProperties_PersistentPropertyRecord { + pb_callback_t name; + bool has_value; + char value[92]; +/* @@protoc_insertion_point(struct:PersistentProperties_PersistentPropertyRecord) */ +} PersistentProperties_PersistentPropertyRecord; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define PersistentProperties_init_default {{{NULL}, NULL}} +#define PersistentProperties_PersistentPropertyRecord_init_default {{{NULL}, NULL}, false, ""} +#define PersistentProperties_init_zero {{{NULL}, NULL}} +#define PersistentProperties_PersistentPropertyRecord_init_zero {{{NULL}, NULL}, false, ""} + +/* Field tags (for use in manual encoding/decoding) */ +#define PersistentProperties_properties_tag 1 +#define PersistentProperties_PersistentPropertyRecord_name_tag 1 +#define PersistentProperties_PersistentPropertyRecord_value_tag 2 + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.1 at Sun Apr 22 14:36:22 2018. */ + +/* Struct field encoding specification for nanopb */ +const pb_field_t PersistentProperties_PersistentPropertyRecord_fields[3] = { + PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, PersistentProperties_PersistentPropertyRecord, name, name, 0), + PB_FIELD( 2, STRING , OPTIONAL, STATIC , OTHER, PersistentProperties_PersistentPropertyRecord, value, name, 0), + PB_LAST_FIELD +}; + +const pb_field_t PersistentProperties_fields[2] = { + PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, PersistentProperties, properties, properties, &PersistentProperties_PersistentPropertyRecord_fields), + PB_LAST_FIELD +}; + +/* Maximum encoded size of messages (where known) */ +/* PersistentProperties_size depends on runtime parameters */ +/* PersistentProperties_PersistentPropertyRecord_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define PROPS_MESSAGES \ + +#endif +/* @@protoc_insertion_point(eof) */ + + +/* *************************** + * End of auto generated code + * ***************************/ + +static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) { + uint8_t *name = xmalloc(stream->bytes_left + 1); + name[stream->bytes_left] = '\0'; + if (!pb_read(stream, name, stream->bytes_left)) + return false; + *arg = name; + return true; +} + +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)); +} + +static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) { + PersistentProperties_PersistentPropertyRecord prop = {}; + prop.name.funcs.decode = name_decode; + if (!pb_decode(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop)) + return false; + struct read_cb_t *read_cb = *arg; + read_cb->func(prop.name.arg, prop.value, read_cb->cookie); + return true; +} + +static bool prop_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { + PersistentProperties_PersistentPropertyRecord prop = {}; + prop.name.funcs.encode = name_encode; + prop.has_value = true; + struct vector *v = *arg; + struct prop_t *e; + vec_for_each(v, e) { + if (e == NULL) + continue; + if (!pb_encode_tag_for_field(stream, field)) + return false; + prop.name.arg = e->name; + strcpy(prop.value, e->value); + if (!pb_encode_submessage(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop)) + return false; + free(e->name); + free(e); + } + return true; +} + +static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count) { + int fd = (intptr_t)stream->state; + return xwrite(fd, buf, count) == count; +} + +static pb_ostream_t create_ostream(const char *filename) { + int fd = creat(filename, 0644); + pb_ostream_t o = {&write_callback, (void*)(intptr_t)fd, SIZE_MAX, 0}; + return o; +} + +static void pb_getprop_cb(const char *name, const char *value, void *v) { + struct prop_t *prop = v; + if (prop->name && strcmp(name, prop->name) == 0) { + strcpy(prop->value, value); + prop->name = NULL; + } +} + +void persist_getprop_all(struct read_cb_t *read_cb) { + if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) { + PRINT_D("resetprop: decode with protobuf from [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n"); + PersistentProperties props = PersistentProperties_init_zero; + props.properties.funcs.decode = prop_decode; + props.properties.arg = read_cb; + uint8_t *buf; + size_t size; + mmap_ro(PERSISTENT_PROPERTY_DIR "/persistent_properties", (void **) &buf, &size); + pb_istream_t stream = pb_istream_from_buffer(buf, size); + pb_decode(&stream, PersistentProperties_fields, &props); + munmap(buf, size); + } else { + DIR *dir = opendir(PERSISTENT_PROPERTY_DIR); + struct dirent *entry; + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 ) + continue; + char *value = persist_getprop(entry->d_name); + if (value) { + read_cb->func(strdup(entry->d_name), value, read_cb->cookie); + free(value); + } + } + } +} + +char *persist_getprop(const char *name) { + struct prop_t prop; + prop.name = (char *) name; + if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) { + struct read_cb_t read_cb = { + .func = pb_getprop_cb, + .cookie = &prop + }; + persist_getprop_all(&read_cb); + if (prop.name) + return NULL; + } else { + // Try to read from file + 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 NULL; + PRINT_D("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); +} + +bool persist_deleteprop(const char *name) { + if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) { + struct vector v; + vec_init(&v); + struct read_cb_t read_cb = { + .func = collect_props, + .cookie = &v + }; + 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) { + // Dump the props back + PersistentProperties props = PersistentProperties_init_zero; + pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp"); + props.properties.funcs.encode = prop_encode; + props.properties.arg = &v; + PRINT_D("resetprop: encode with protobuf to [" PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp]\n"); + if (!pb_encode(&ostream, PersistentProperties_fields, &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"); + } + + vec_destroy(&v); + return reencode; + } else { + char path[PATH_MAX]; + snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); + if (unlink(path) == 0) { + PRINT_D("resetprop: unlink [%s]\n", path); + return true; + } + } + return false; +} diff --git a/native/jni/resetprop/resetprop.cpp b/native/jni/resetprop/resetprop.c similarity index 69% rename from native/jni/resetprop/resetprop.cpp rename to native/jni/resetprop/resetprop.c index 00454e1e3..0c99f548a 100644 --- a/native/jni/resetprop/resetprop.cpp +++ b/native/jni/resetprop/resetprop.c @@ -19,15 +19,11 @@ #include "magisk.h" #include "resetprop.h" -extern "C" { +#include "_resetprop.h" #include "vector.h" -} +#include "utils.h" -#define PRINT_D(...) { LOGD(__VA_ARGS__); if (verbose) fprintf(stderr, __VA_ARGS__); } -#define PRINT_E(...) { LOGE(__VA_ARGS__); fprintf(stderr, __VA_ARGS__); } -#define PERSISTENT_PROPERTY_DIR "/data/property" - -static int verbose = 0; +int prop_verbose = 0; static int check_legal_property_name(const char *name) { int namelen = strlen(name); @@ -83,6 +79,49 @@ static int usage(char* arg0) { return 1; } +// The callback passes to __system_property_read_callback2, actually runs the callback in read_cb +static void callback_wrapper(void *read_cb, const char *name, const char *value, uint32_t serial) { + ((struct read_cb_t *) read_cb)->func(name, value, ((struct read_cb_t *) read_cb)->cookie); +} + +/* ********************************** + * Callback functions for read_cb_t + * **********************************/ + +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) { + struct vector *v = prop_list; + struct prop_t *p; + bool uniq = true; + vec_for_each(v, p) { + if (strcmp(name, p->name) == 0) { + uniq = 0; + break; + } + } + 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_callback2(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() { if (__system_properties_init2()) { PRINT_E("resetprop: Initialize error\n"); @@ -91,16 +130,36 @@ static int init_resetprop() { return 0; } +static void print_props(int persist) { + struct prop_t *p; + struct vector prop_list; + vec_init(&prop_list); + getprop_all(collect_props, &prop_list); + if (persist) { + struct read_cb_t read_cb = { + .func = collect_unique_props, + .cookie = &prop_list + }; + persist_getprop_all(&read_cb); + } + vec_sort(&prop_list, prop_cmp); + vec_for_each(&prop_list, p) { + printf("[%s]: [%s]\n", p->name, p->value); + free(p->name); + free(p); + } + vec_destroy(&prop_list); +} + +/* ************************************************** + * Implementations of functions in resetprop.h (APIs) + * **************************************************/ + int prop_exist(const char *name) { if (init_resetprop()) return 0; return __system_property_find2(name) != NULL; } -static void read_prop_info(void* cookie, const char *name, const char *value, uint32_t serial) { - strcpy((char *) cookie, value); -} - - char *getprop(const char *name) { return getprop2(name, 0); } @@ -109,103 +168,35 @@ char *getprop(const char *name) { char *getprop2(const char *name, int persist) { if (check_legal_property_name(name)) return NULL; - char value[PROP_VALUE_MAX]; if (init_resetprop()) return NULL; const prop_info *pi = __system_property_find2(name); if (pi == NULL) { if (persist && strncmp(name, "persist.", 8) == 0) { - // Try to read from file - char path[PATH_MAX]; - snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); - int fd = open(path, O_RDONLY | O_CLOEXEC); - if (fd < 0) goto no_prop; - PRINT_D("resetprop: read prop from [%s]\n", path); - size_t len = read(fd, value, sizeof(value)); - value[len] = '\0'; // Null terminate the read value - } else { -no_prop: + char *value = persist_getprop(name); + if (value) + return value; + } PRINT_D("resetprop: prop [%s] does not exist\n", name); return NULL; - } } else { - __system_property_read_callback2(pi, read_prop_info, value); + char value[PROP_VALUE_MAX]; + struct read_cb_t read_cb = { + .func = store_prop_value, + .cookie = value + }; + __system_property_read_callback2(pi, callback_wrapper, &read_cb); + PRINT_D("resetprop: getprop [%s]: [%s]\n", name, value); + return strdup(value); } - PRINT_D("resetprop: getprop [%s]: [%s]\n", name, value); - return strdup(value); } -struct wrapper { - void (*func)(const char *, const char *); -}; - -static void cb_wrapper(void* cookie, const char *name, const char *value, uint32_t serial) { - ((wrapper *) cookie)->func(name, value); -} - -static void prop_foreach_cb(const prop_info* pi, void* cookie) { - __system_property_read_callback2(pi, cb_wrapper, cookie); -} - -class property { -public: - property(const char *n, const char *v) { - name = strdup(n); - value = strdup(v); - } - ~property() { - free((void *)name); - free((void *)value); - } - const char *name; - const char *value; -}; - -vector prop_list; - -static int prop_cmp(const void *p1, const void *p2) { - return strcmp(((property *) p1)->name, ((property *) p2)->name); -} - -static void print_all_props_cb(const char *name, const char *value) { - vec_push_back(&prop_list, new property(name, value)); -} - -static void print_all_props(int persist) { - void *p; - vec_init(&prop_list); - getprop_all(print_all_props_cb); - if (persist) { - // Check all persist props in data - DIR *dir = opendir(PERSISTENT_PROPERTY_DIR); - struct dirent *entry; - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 ) - continue; - int found = 0; - vec_for_each(&prop_list, p) { - if (strcmp(((property *) p)->name, entry->d_name) == 0) { - found = 1; - break; - } - } - if (!found) - vec_push_back(&prop_list, new property(entry->d_name, getprop2(entry->d_name, 1))); - } - } - vec_sort(&prop_list, prop_cmp); - vec_for_each(&prop_list, p) { - printf("[%s]: [%s]\n", ((property *) p)->name, ((property *) p)->value); - delete((property *) p); - } - vec_destroy(&prop_list); -} - -void getprop_all(void (*callback)(const char*, const char*)) { +void getprop_all(void (*callback)(const char *, const char *, void *), void *cookie) { if (init_resetprop()) return; - struct wrapper wrap = { - .func = callback + struct read_cb_t read_cb = { + .func = callback, + .cookie = cookie }; - __system_property_foreach2(prop_foreach_cb, &wrap); + __system_property_foreach2(prop_foreach_cb, &read_cb); } int setprop(const char *name, const char *value) { @@ -248,7 +239,7 @@ int deleteprop(const char *name) { return deleteprop2(name, 1); } -int deleteprop2(const char *name, const int persist) { +int deleteprop2(const char *name, int persist) { if (check_legal_property_name(name)) return 1; if (init_resetprop()) return -1; @@ -256,8 +247,8 @@ int deleteprop2(const char *name, const int persist) { path[0] = '\0'; PRINT_D("resetprop: deleteprop [%s]\n", name); if (persist && strncmp(name, "persist.", 8) == 0) - snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); - return __system_property_del(name) && unlink(path); + persist = persist_deleteprop(name); + return __system_property_del(name) && !(persist && strncmp(name, "persist.", 8) == 0); } int read_prop_file(const char* filename, const int trigger) { @@ -290,7 +281,7 @@ int read_prop_file(const char* filename, const int trigger) { } if (comment) continue; pch = strchr(line, '='); - // Ignore ivalid formats + // Ignore invalid formats if ( ((pch == NULL) || (i >= (pch - line))) || (pch >= line + read - 1) ) continue; // Separate the string *pch = '\0'; @@ -321,7 +312,7 @@ int resetprop_main(int argc, char *argv[]) { goto usage; } case 'v': - verbose = 1; + prop_verbose = 1; continue; case 'p': persist = 1; @@ -344,7 +335,7 @@ int resetprop_main(int argc, char *argv[]) { switch (argc) { case 0: - print_all_props(persist); + print_props(persist); return 0; case 1: prop = getprop2(argv[0], persist);