Magisk/native/jni/resetprop/persist_properties.cpp

266 lines
8.3 KiB
C++
Raw Normal View History

2018-04-28 12:22:42 +00:00
#include <stdbool.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
2019-01-20 04:59:37 +00:00
#include <vector>
2018-04-28 12:22:42 +00:00
#include <pb.h>
#include <pb_decode.h>
#include <pb_encode.h>
2020-03-09 08:50:30 +00:00
#include <utils.hpp>
2018-04-28 12:22:42 +00:00
2020-03-09 08:50:30 +00:00
#include "_resetprop.hpp"
2018-04-28 12:22:42 +00:00
2019-01-20 04:59:37 +00:00
using namespace std;
2018-04-28 12:22:42 +00:00
/* ***********************************************************************
* 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
* ***************************/
bool use_pb = false;
2020-05-07 13:08:30 +00:00
#ifdef APPLET_STUB_MAIN
struct {
void push_back(...){};
} allocs;
void persist_cleanup(){}
#else
static thread_local vector<void *> allocs;
void persist_cleanup() {
std::for_each(allocs.begin(), allocs.end(), [](auto p){ free(p); });
allocs.clear();
}
#endif
2018-04-28 12:22:42 +00:00
static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
2020-05-07 13:08:30 +00:00
auto name = (pb_byte_t *) malloc(stream->bytes_left + 1);
allocs.push_back(name); /* Record all mallocs to cleanup */
2018-04-28 12:22:42 +00:00
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) {
2018-11-03 03:56:15 +00:00
return pb_encode_tag_for_field(stream, field) &&
pb_encode_string(stream, (const pb_byte_t *) *arg, strlen((const char *) *arg));
2018-04-28 12:22:42 +00:00
}
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;
2020-05-07 13:08:30 +00:00
reinterpret_cast<prop_cb*>(*arg)->exec((const char *) prop.name.arg, prop.value);
2018-04-28 12:22:42 +00:00
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;
2020-05-07 13:08:30 +00:00
auto &list = *(prop_list *) *arg;
for (auto &p : list) {
2018-04-28 12:22:42 +00:00
if (!pb_encode_tag_for_field(stream, field))
return false;
2020-05-07 13:08:30 +00:00
prop.name.arg = (void *) p.first.data();
strcpy(prop.value, p.second.data());
2018-04-28 12:22:42 +00:00
if (!pb_encode_submessage(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop))
return false;
}
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);
2018-11-03 03:56:15 +00:00
pb_ostream_t o = {
.callback = write_callback,
.state = (void*)(intptr_t)fd,
.max_size = SIZE_MAX,
.bytes_written = 0,
};
2018-04-28 12:22:42 +00:00
return o;
}
2020-05-07 13:08:30 +00:00
static void pb_getprop(prop_cb *prop_cb) {
2018-11-03 03:56:15 +00:00
LOGD("resetprop: decode with protobuf [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n");
PersistentProperties props = {};
props.properties.funcs.decode = prop_decode;
2020-05-07 13:08:30 +00:00
props.properties.arg = prop_cb;
2018-11-05 19:37:47 +00:00
pb_byte_t *buf;
2018-11-03 03:56:15 +00:00
size_t size;
2019-02-25 04:09:34 +00:00
mmap_ro(PERSISTENT_PROPERTY_DIR "/persistent_properties", buf, size);
2018-11-03 03:56:15 +00:00
pb_istream_t stream = pb_istream_from_buffer(buf, size);
pb_decode(&stream, PersistentProperties_fields, &props);
munmap(buf, size);
}
2019-01-20 04:59:37 +00:00
static bool file_getprop(const char *name, char *value) {
2018-11-03 03:56:15 +00:00
char path[PATH_MAX];
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0)
2019-01-20 04:59:37 +00:00
return false;
2018-11-03 03:56:15 +00:00
LOGD("resetprop: read prop from [%s]\n", path);
2019-01-20 04:59:37 +00:00
value[read(fd, value, PROP_VALUE_MAX)] = '\0'; // Null terminate the read value
2018-11-03 03:56:15 +00:00
close(fd);
2019-01-20 04:59:37 +00:00
return value[0] != '\0';
2018-11-03 03:56:15 +00:00
}
2020-05-07 13:08:30 +00:00
void persist_getprops(prop_cb *prop_cb) {
2018-11-03 03:56:15 +00:00
if (use_pb) {
2020-05-07 13:08:30 +00:00
pb_getprop(prop_cb);
2018-04-28 12:22:42 +00:00
} 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;
2018-11-03 03:56:15 +00:00
char value[PROP_VALUE_MAX];
2019-01-20 04:59:37 +00:00
if (file_getprop(entry->d_name, value))
2020-05-07 13:08:30 +00:00
prop_cb->exec(entry->d_name, value);
2018-04-28 12:22:42 +00:00
}
}
}
2019-01-20 04:59:37 +00:00
string persist_getprop(const char *name) {
2018-11-03 03:56:15 +00:00
if (use_pb) {
2020-05-07 13:08:30 +00:00
run_finally f([]{ persist_cleanup(); });
struct {
const char *name;
char value[PROP_VALUE_MAX];
} prop;
prop.name = name;
prop.value[0] = '\0';
auto reader = make_prop_cb(prop, [](auto name, auto value, auto prop) {
if (strcmp(name, prop.name) == 0)
strcpy(prop.value, value);
});
pb_getprop(&reader);
2018-11-05 19:37:47 +00:00
if (prop.value[0])
2018-11-07 07:10:38 +00:00
return prop.value;
2018-04-28 12:22:42 +00:00
} else {
// Try to read from file
2018-11-03 03:56:15 +00:00
char value[PROP_VALUE_MAX];
2019-01-20 04:59:37 +00:00
if (file_getprop(name, value))
2018-11-07 07:10:38 +00:00
return value;
2018-04-28 12:22:42 +00:00
}
2019-01-20 04:59:37 +00:00
return string();
2018-04-28 12:22:42 +00:00
}
bool persist_deleteprop(const char *name) {
2018-11-03 03:56:15 +00:00
if (use_pb) {
2020-05-07 13:08:30 +00:00
run_finally f([]{ persist_cleanup(); });
prop_list list;
prop_collector collector(list);
persist_getprops(&collector);
for (auto it = list.begin(); it != list.end(); ++it) {
if (it->first == name) {
list.erase(it);
2018-11-03 03:56:15 +00:00
// 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;
2020-05-07 13:08:30 +00:00
props.properties.arg = &list;
2018-11-03 03:56:15 +00:00
LOGD("resetprop: encode with protobuf [" 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");
return true;
}
2018-04-28 12:22:42 +00:00
}
2018-11-03 03:56:15 +00:00
return false;
2018-04-28 12:22:42 +00:00
} else {
char path[PATH_MAX];
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
if (unlink(path) == 0) {
2018-09-27 07:11:10 +00:00
LOGD("resetprop: unlink [%s]\n", path);
2018-04-28 12:22:42 +00:00
return true;
}
}
return false;
}