From 8d81bd0e33a5ff25bb85b73b9198b7259213e7bb Mon Sep 17 00:00:00 2001 From: LoveSy Date: Fri, 23 Jun 2023 20:37:06 +0800 Subject: [PATCH] resetprop: replace nanopb with quick-protobuf for persist --- .gitmodules | 3 - native/src/Android.mk | 5 +- native/src/Cargo.lock | 2 + native/src/base/files.rs | 21 ++ native/src/base/misc.rs | 6 +- native/src/boot/payload.rs | 2 +- native/src/core/Cargo.toml | 2 + native/src/core/build.rs | 19 ++ native/src/core/lib.rs | 14 +- native/src/core/resetprop/.gitignore | 2 + native/src/core/resetprop/mod.rs | 2 + native/src/core/resetprop/persist.cpp | 277 ------------------ native/src/core/resetprop/persist.rs | 232 +++++++++++++++ .../proto/persistent_properties.proto | 24 ++ native/src/core/resetprop/resetprop.hpp | 12 +- native/src/external/Android.mk | 11 - native/src/external/nanopb | 1 - 17 files changed, 330 insertions(+), 305 deletions(-) create mode 100644 native/src/core/resetprop/.gitignore create mode 100644 native/src/core/resetprop/mod.rs delete mode 100644 native/src/core/resetprop/persist.cpp create mode 100644 native/src/core/resetprop/persist.rs create mode 100644 native/src/core/resetprop/proto/persistent_properties.proto delete mode 160000 native/src/external/nanopb diff --git a/.gitmodules b/.gitmodules index e514a7f6d..209276091 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,9 +16,6 @@ [submodule "xz"] path = native/src/external/xz url = https://github.com/xz-mirror/xz.git -[submodule "nanopb"] - path = native/src/external/nanopb - url = https://github.com/nanopb/nanopb.git [submodule "pcre"] path = native/src/external/pcre url = https://android.googlesource.com/platform/external/pcre diff --git a/native/src/Android.mk b/native/src/Android.mk index 13d675335..9f49efd88 100644 --- a/native/src/Android.mk +++ b/native/src/Android.mk @@ -10,7 +10,6 @@ include $(CLEAR_VARS) LOCAL_MODULE := magisk LOCAL_STATIC_LIBRARIES := \ libbase \ - libnanopb \ libsystemproperties \ libphmap \ liblsplt \ @@ -28,7 +27,6 @@ LOCAL_SRC_FILES := \ core/restorecon.cpp \ core/module.cpp \ core/thread.cpp \ - core/resetprop/persist.cpp \ core/resetprop/resetprop.cpp \ core/core-rs.cpp \ core/su/su.cpp \ @@ -139,14 +137,13 @@ include $(CLEAR_VARS) LOCAL_MODULE := resetprop LOCAL_STATIC_LIBRARIES := \ libbase \ - libnanopb \ libsystemproperties \ libmagisk-rs LOCAL_SRC_FILES := \ core/applet_stub.cpp \ core/resetprop/resetprop.cpp \ - core/resetprop/persist.cpp + core/core-rs.cpp LOCAL_CFLAGS := -DAPPLET_STUB_MAIN=resetprop_main include $(BUILD_EXECUTABLE) diff --git a/native/src/Cargo.lock b/native/src/Cargo.lock index 88c1bb74d..36c7ec9d7 100644 --- a/native/src/Cargo.lock +++ b/native/src/Cargo.lock @@ -424,6 +424,8 @@ dependencies = [ "cxx-gen", "num-derive", "num-traits", + "pb-rs", + "quick-protobuf", ] [[package]] diff --git a/native/src/base/files.rs b/native/src/base/files.rs index f107c3432..273546828 100644 --- a/native/src/base/files.rs +++ b/native/src/base/files.rs @@ -345,6 +345,27 @@ impl Directory { })?; Ok(()) } + + pub fn for_all_file io::Result>( + &mut self, + mut f: F, + ) -> io::Result { + use WalkResult::*; + loop { + match self.read()? { + None => return Ok(Continue), + Some(ref e) => { + if e.is_dir() { + return Ok(Continue); + } + match f(e)? { + Abort | Skip => return Ok(Continue), + Continue => {} + } + } + } + } + } } impl Directory { diff --git a/native/src/base/misc.rs b/native/src/base/misc.rs index a1034cab3..534b21078 100644 --- a/native/src/base/misc.rs +++ b/native/src/base/misc.rs @@ -83,14 +83,14 @@ macro_rules! bfmt_cstr { #[macro_export] macro_rules! cstr { - ($str:literal) => {{ + ($($str:tt)*) => {{ assert!( - !$str.bytes().any(|b| b == b'\0'), + !($($str)*).bytes().any(|b| b == b'\0'), "cstr argument contains embedded NUL bytes", ); #[allow(unused_unsafe)] unsafe { - $crate::Utf8CStr::from_bytes_unchecked(concat!($str, "\0").as_bytes()) + $crate::Utf8CStr::from_bytes_unchecked(concat!($($str)*, "\0").as_bytes()) } }}; } diff --git a/native/src/boot/payload.rs b/native/src/boot/payload.rs index dab86d848..e10d3044e 100644 --- a/native/src/boot/payload.rs +++ b/native/src/boot/payload.rs @@ -171,7 +171,7 @@ fn do_extract_boot_from_payload( if !ffi::decompress(data, out_file.as_raw_fd()) { return Err(bad_payload!("decompression failed")); } - } + }, _ => return Err(bad_payload!("unsupported operation type")), }; } diff --git a/native/src/core/Cargo.toml b/native/src/core/Cargo.toml index f2e2b2fec..15cfc1d3f 100644 --- a/native/src/core/Cargo.toml +++ b/native/src/core/Cargo.toml @@ -9,9 +9,11 @@ path = "lib.rs" [build-dependencies] cxx-gen = { workspace = true } +pb-rs = { workspace = true } [dependencies] base = { path = "../base" } cxx = { workspace = true } num-traits = { workspace = true } num-derive = { workspace = true } +quick-protobuf = { workspace = true } diff --git a/native/src/core/build.rs b/native/src/core/build.rs index f80a90e0b..bdd3c8139 100644 --- a/native/src/core/build.rs +++ b/native/src/core/build.rs @@ -1,8 +1,27 @@ +use pb_rs::{types::FileDescriptor, ConfigBuilder}; + use crate::gen::gen_cxx_binding; #[path = "../include/gen.rs"] mod gen; fn main() { + println!("cargo:rerun-if-changed=resetprop/proto/persistent_properties.proto"); + gen_cxx_binding("core-rs"); + + let cb = ConfigBuilder::new( + &["resetprop/proto/persistent_properties.proto"], + None, + Some(&"resetprop/proto"), + &["."], + ) + .unwrap(); + FileDescriptor::run( + &cb.single_module(true) + .dont_use_cow(true) + .generate_getters(true) + .build(), + ) + .unwrap(); } diff --git a/native/src/core/lib.rs b/native/src/core/lib.rs index 1431e08d9..e523f32e0 100644 --- a/native/src/core/lib.rs +++ b/native/src/core/lib.rs @@ -5,18 +5,26 @@ use base::Utf8CStr; use cert::read_certificate; use daemon::{daemon_entry, find_apk_path, get_magiskd, zygisk_entry, MagiskD}; use logging::{android_logging, magisk_logging, zygisk_logging}; +use resetprop::persist::{ + persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop, +}; mod cert; #[path = "../include/consts.rs"] mod consts; mod daemon; mod logging; +mod resetprop; #[cxx::bridge] pub mod ffi { extern "C++" { + pub type prop_cb; include!("resetprop/resetprop.hpp"); - unsafe fn get_prop_rs(name: *const c_char, persist: bool) -> String; + include!("../base/files.hpp"); + pub unsafe fn get_prop_rs(name: *const c_char, persist: bool) -> String; + pub unsafe fn prop_cb_exec(cb: *mut prop_cb, name: *const c_char, value: *const c_char); + pub unsafe fn clone_attr(src: *const c_char, dst: *const c_char); } extern "Rust" { @@ -26,6 +34,10 @@ pub mod ffi { fn zygisk_logging(); fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize; fn read_certificate(fd: i32, version: i32) -> Vec; + unsafe fn persist_get_prop(name: *const c_char, prop_cb: *mut prop_cb); + unsafe fn persist_get_props(prop_cb: *mut prop_cb); + unsafe fn persist_delete_prop(name: *const c_char) -> bool; + unsafe fn persist_set_prop(name: *const c_char, value: *const c_char) -> bool; } #[namespace = "rust"] diff --git a/native/src/core/resetprop/.gitignore b/native/src/core/resetprop/.gitignore new file mode 100644 index 000000000..0453dd0e4 --- /dev/null +++ b/native/src/core/resetprop/.gitignore @@ -0,0 +1,2 @@ +proto/mod.rs +proto/persistent_properties.rs diff --git a/native/src/core/resetprop/mod.rs b/native/src/core/resetprop/mod.rs new file mode 100644 index 000000000..6ab80a2cf --- /dev/null +++ b/native/src/core/resetprop/mod.rs @@ -0,0 +1,2 @@ +pub mod persist; +pub mod proto; diff --git a/native/src/core/resetprop/persist.cpp b/native/src/core/resetprop/persist.cpp deleted file mode 100644 index e50fe99fd..000000000 --- a/native/src/core/resetprop/persist.cpp +++ /dev/null @@ -1,277 +0,0 @@ -#include -#include -#include - -#include - -#include "resetprop.hpp" - -using namespace std; - -/* *********************************************************************** - * Auto generated header and field definitions compiled from - * https://android.googlesource.com/platform/system/core/+/master/init/persistent_properties.proto - * Generated with Nanopb: https://github.com/nanopb/nanopb - * ***********************************************************************/ - -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.3 */ - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Struct definitions */ -struct PersistentProperties { - pb_callback_t properties; -}; - -struct PersistentProperties_PersistentPropertyRecord { - pb_callback_t name; - bool has_value; - char value[92]; -}; - -/* 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 - -/* Struct field encoding specification for nanopb */ -#define PersistentProperties_FIELDLIST(X, a) \ -X(a, CALLBACK, REPEATED, MESSAGE, properties, 1) -#define PersistentProperties_CALLBACK pb_default_field_callback -#define PersistentProperties_DEFAULT NULL -#define PersistentProperties_properties_MSGTYPE PersistentProperties_PersistentPropertyRecord - -#define PersistentProperties_PersistentPropertyRecord_FIELDLIST(X, a) \ -X(a, CALLBACK, OPTIONAL, STRING, name, 1) \ -X(a, STATIC, OPTIONAL, STRING, value, 2) -#define PersistentProperties_PersistentPropertyRecord_CALLBACK pb_default_field_callback -#define PersistentProperties_PersistentPropertyRecord_DEFAULT NULL - -extern const pb_msgdesc_t PersistentProperties_msg; -extern const pb_msgdesc_t PersistentProperties_PersistentPropertyRecord_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define PersistentProperties_fields &PersistentProperties_msg -#define PersistentProperties_PersistentPropertyRecord_fields &PersistentProperties_PersistentPropertyRecord_msg - -/* Maximum encoded size of messages (where known) */ -/* PersistentProperties_size depends on runtime parameters */ -/* PersistentProperties_PersistentPropertyRecord_size depends on runtime parameters */ - -PB_BIND(PersistentProperties, PersistentProperties, AUTO) - -PB_BIND(PersistentProperties_PersistentPropertyRecord, PersistentProperties_PersistentPropertyRecord, AUTO) - -/* *************************** - * 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) { - string &name = *static_cast(*arg); - name.resize(stream->bytes_left); - return pb_read(stream, (pb_byte_t *)(name.data()), stream->bytes_left); -} - -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, (const pb_byte_t *) *arg, strlen((const char *) *arg)); -} - -static bool prop_decode(pb_istream_t *stream, const pb_field_t *, void **arg) { - PersistentProperties_PersistentPropertyRecord prop{}; - string name; - prop.name.funcs.decode = name_decode; - prop.name.arg = &name; - if (!pb_decode(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop)) - return false; - auto cb = static_cast(*arg); - cb->exec(name.data(), prop.value); - 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; - prop_list &list = *static_cast(*arg); - for (auto &p : list) { - if (!pb_encode_tag_for_field(stream, field)) - return false; - prop.name.arg = (void *) p.first.data(); - strscpy(prop.value, p.second.data(), sizeof(prop.value)); - if (!pb_encode_submessage(stream, &PersistentProperties_PersistentPropertyRecord_msg, &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(int fd) { - pb_ostream_t o = { - .callback = write_callback, - .state = (void*)(intptr_t)fd, - .max_size = SIZE_MAX, - .bytes_written = 0, - }; - return o; -} - -static void pb_get_prop(prop_cb *prop_cb) { - LOGD("resetprop: decode with protobuf [" PERSIST_PROP "]\n"); - PersistentProperties props{}; - props.properties.funcs.decode = prop_decode; - props.properties.arg = prop_cb; - mmap_data m(PERSIST_PROP); - pb_istream_t stream = pb_istream_from_buffer(m.buf(), m.sz()); - pb_decode(&stream, &PersistentProperties_msg, &props); -} - -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]; - ssprintf(path, sizeof(path), PERSIST_PROP_DIR "/%s", name); - int fd = open(path, O_RDONLY | O_CLOEXEC); - if (fd < 0) - return false; - LOGD("resetprop: read prop from [%s]\n", path); - value[read(fd, value, PROP_VALUE_MAX - 1)] = '\0'; // Null terminate the read value - close(fd); - 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 use_pb = access(PERSIST_PROP, R_OK) == 0; - return use_pb; -} - -void persist_get_props(prop_cb *prop_cb) { - if (check_pb()) { - pb_get_prop(prop_cb); - } else { - auto dir = open_dir(PERSIST_PROP_DIR); - if (!dir) return; - char value[PROP_VALUE_MAX]; - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (file_get_prop(entry->d_name, value)) - prop_cb->exec(entry->d_name, value); - } - } -} - -struct match_prop_name : prop_cb { - explicit match_prop_name(const char *name) : _name(name) { value[0] = '\0'; } - void exec(const char *name, const char *val) override { - if (value[0] == '\0' && _name == name) - strscpy(value, val, sizeof(value)); - } - char value[PROP_VALUE_MAX]; -private: - string_view _name; -}; - -void persist_get_prop(const char *name, prop_cb *prop_cb) { - if (check_pb()) { - match_prop_name cb(name); - pb_get_prop(&cb); - if (cb.value[0]) { - LOGD("resetprop: get prop (persist) [%s]: [%s]\n", name, cb.value); - prop_cb->exec(name, cb.value); - } - } else { - // Try to read from file - char value[PROP_VALUE_MAX]; - if (file_get_prop(name, value)) { - LOGD("resetprop: get prop (persist) [%s]: [%s]\n", name, value); - prop_cb->exec(name, value); - } - } -} - -bool persist_delete_prop(const char *name) { - if (check_pb()) { - prop_list list; - prop_collector collector(list); - pb_get_prop(&collector); - - auto it = list.find(name); - if (it != list.end()) { - list.erase(it); - return pb_write_props(list); - } - return false; - } else { - char path[4096]; - ssprintf(path, sizeof(path), PERSIST_PROP_DIR "/%s", name); - if (unlink(path) == 0) { - LOGD("resetprop: unlink [%s]\n", path); - return true; - } - } - 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); - } -} diff --git a/native/src/core/resetprop/persist.rs b/native/src/core/resetprop/persist.rs new file mode 100644 index 000000000..fab499a51 --- /dev/null +++ b/native/src/core/resetprop/persist.rs @@ -0,0 +1,232 @@ +use crate::ffi::{clone_attr, prop_cb, prop_cb_exec}; +use crate::resetprop::proto::persistent_properties::{ + mod_PersistentProperties::PersistentPropertyRecord, PersistentProperties, +}; +use base::{cstr, debug, libc::mkstemp, Directory, LoggedResult, MappedFile, Utf8CStr, WalkResult}; +use core::ffi::c_char; +use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer}; +use std::{ + fs::{read_to_string, remove_file, rename, File}, + io::{BufWriter, Write}, + os::fd::FromRawFd, + path::{Path, PathBuf}, +}; + +macro_rules! PERSIST_PROP_DIR { + () => { + "/data/property" + }; +} + +macro_rules! PERSIST_PROP { + () => { + concat!(PERSIST_PROP_DIR!(), "/persistent_properties") + }; +} + +struct PropCb { + cb: *mut prop_cb, +} + +struct MatchNameCb<'a> { + cb: PropCb, + name: &'a Utf8CStr, +} + +struct PropCollectCb<'a> { + props: &'a mut PersistentProperties, + replace_name: Option<&'a Utf8CStr>, + replace_value: Option<&'a Utf8CStr>, +} + +trait PropCbExec { + fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr); +} + +impl PropCbExec for PropCb { + fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr) { + if !self.cb.is_null() { + unsafe { prop_cb_exec(self.cb, name.as_ptr(), value.as_ptr()) } + } + } +} + +impl PropCbExec for MatchNameCb<'_> { + fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr) { + if name.as_bytes() == self.name.as_bytes() { + self.cb.exec(name, value); + debug!("resetprop: found prop [{}] = [{}]", name, value); + } + } +} + +impl PropCbExec for PropCollectCb<'_> { + fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr) { + let replace_value = self.replace_value.unwrap_or(value); + let value = self.replace_name.map_or(value, |replace_name| { + if name.as_bytes() == replace_name.as_bytes() { + replace_value + } else { + value + } + }); + self.props.properties.push(PersistentPropertyRecord { + name: Some(name.to_string()), + value: Some(value.to_string()), + }) + } +} + +fn check_pb() -> bool { + Path::new(PERSIST_PROP!()).exists() +} + +fn pb_get_prop(cb: &mut dyn PropCbExec) -> LoggedResult<()> { + debug!("resetprop: decode with protobuf [{}]", PERSIST_PROP!()); + let m = MappedFile::open(cstr!(PERSIST_PROP!()))?; + let m = m.as_ref(); + let mut r = BytesReader::from_bytes(m); + let mut pp = PersistentProperties::from_reader(&mut r, m)?; + pp.properties.iter_mut().for_each(|p| { + if let PersistentPropertyRecord { + name: Some(ref mut n), + value: Some(ref mut v), + } = p + { + cb.exec(Utf8CStr::from_string(n), Utf8CStr::from_string(v)); + } + }); + Ok(()) +} + +fn file_get_prop(name: &Utf8CStr) -> LoggedResult { + let path = PathBuf::new().join(PERSIST_PROP_DIR!()).join(name); + let path = path.as_path(); + debug!("resetprop: read prop from [{}]\n", path.display()); + Ok(read_to_string(path)?) +} + +fn pb_write_props(props: &PersistentProperties) -> LoggedResult<()> { + let mut tmp = String::from(concat!(PERSIST_PROP!(), ".XXXXXX")); + let tmp = Utf8CStr::from_string(&mut tmp); + { + let f = unsafe { + let fd = mkstemp(tmp.as_ptr() as *mut c_char); + if fd < 0 { + return Err(Default::default()); + } + File::from_raw_fd(fd) + }; + debug!("resetprop: encode with protobuf [{}]", tmp); + props.write_message(&mut Writer::new(BufWriter::new(f)))?; + } + unsafe { + clone_attr(cstr!(PERSIST_PROP!()).as_ptr(), tmp.as_ptr()); + } + rename(tmp, PERSIST_PROP!())?; + Ok(()) +} + +fn file_set_prop(name: &Utf8CStr, value: Option<&Utf8CStr>) -> LoggedResult<()> { + let path = PathBuf::new().join(PERSIST_PROP_DIR!()).join(name); + let path = path.as_path(); + if let Some(value) = value { + let mut tmp = String::from(concat!(PERSIST_PROP_DIR!(), ".prop.XXXXXX")); + { + let mut f = unsafe { + let fd = mkstemp(tmp.as_mut_ptr() as *mut c_char); + if fd < 0 { + return Err(Default::default()); + } + File::from_raw_fd(fd) + }; + f.write_all(value.as_bytes())?; + } + debug!("resetprop: write prop to [{}]\n", tmp); + rename(tmp, path)?; + } else { + debug!("resetprop: unlink [{}]\n", path.display()); + remove_file(path)?; + } + Ok(()) +} + +fn do_persist_get_prop(name: &Utf8CStr, mut prop_cb: PropCb) -> LoggedResult<()> { + if check_pb() { + pb_get_prop(&mut MatchNameCb { cb: prop_cb, name }) + } else { + let mut value = file_get_prop(name)?; + prop_cb.exec(name, Utf8CStr::from_string(&mut value)); + debug!("resetprop: found prop [{}] = [{}]", name, value); + Ok(()) + } +} + +fn do_persist_get_props(mut prop_cb: PropCb) -> LoggedResult<()> { + if check_pb() { + pb_get_prop(&mut prop_cb) + } else { + let mut dir = Directory::open(cstr!(PERSIST_PROP_DIR!()))?; + dir.for_all_file(|f| { + if let Ok(name) = Utf8CStr::from_bytes(f.d_name().to_bytes()) { + if let Ok(mut value) = file_get_prop(name) { + prop_cb.exec(name, Utf8CStr::from_string(&mut value)); + } + } + Ok(WalkResult::Continue) + })?; + Ok(()) + } +} + +fn do_persist_delete_prop(name: &Utf8CStr) -> LoggedResult<()> { + if check_pb() { + let mut pp = PersistentProperties { properties: vec![] }; + pb_get_prop(&mut PropCollectCb { + props: &mut pp, + replace_name: Some(name), + replace_value: None, + })?; + pb_write_props(&pp) + } else { + file_set_prop(name, None) + } +} + +fn do_persist_set_prop(name: &Utf8CStr, value: &Utf8CStr) -> LoggedResult<()> { + if check_pb() { + let mut pp = PersistentProperties { properties: vec![] }; + pb_get_prop(&mut PropCollectCb { + props: &mut pp, + replace_name: Some(name), + replace_value: Some(value), + })?; + pb_write_props(&pp) + } else { + file_set_prop(name, Some(value)) + } +} + +pub unsafe fn persist_get_prop(name: *const c_char, prop_cb: *mut prop_cb) { + unsafe fn inner(name: *const c_char, prop_cb: *mut prop_cb) -> LoggedResult<()> { + do_persist_get_prop(Utf8CStr::from_ptr(name)?, PropCb { cb: prop_cb }) + } + inner(name, prop_cb).ok(); +} + +pub unsafe fn persist_get_props(prop_cb: *mut prop_cb) { + do_persist_get_props(PropCb { cb: prop_cb }).ok(); +} + +pub unsafe fn persist_delete_prop(name: *const c_char) -> bool { + unsafe fn inner(name: *const c_char) -> LoggedResult<()> { + do_persist_delete_prop(Utf8CStr::from_ptr(name)?) + } + inner(name).is_ok() +} +pub unsafe fn persist_set_prop(name: *const c_char, value: *const c_char) -> bool { + unsafe fn inner(name: *const c_char, value: *const c_char) -> LoggedResult<()> { + do_persist_set_prop(Utf8CStr::from_ptr(name)?, Utf8CStr::from_ptr(value)?) + } + inner(name, value).is_ok() +} diff --git a/native/src/core/resetprop/proto/persistent_properties.proto b/native/src/core/resetprop/proto/persistent_properties.proto new file mode 100644 index 000000000..15427082f --- /dev/null +++ b/native/src/core/resetprop/proto/persistent_properties.proto @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +message PersistentProperties { + message PersistentPropertyRecord { + optional string name = 1; + optional string value = 2; + } + repeated PersistentPropertyRecord properties = 1; +} diff --git a/native/src/core/resetprop/resetprop.hpp b/native/src/core/resetprop/resetprop.hpp index f5c421485..66c88709e 100644 --- a/native/src/core/resetprop/resetprop.hpp +++ b/native/src/core/resetprop/resetprop.hpp @@ -29,7 +29,11 @@ int delete_prop(const char *name, bool persist = false); int set_prop(const char *name, const char *value, bool skip_svc = false); void load_prop_file(const char *filename, bool skip_svc = false); -void persist_get_prop(const char *name, prop_cb *prop_cb); -void persist_get_props(prop_cb *prop_cb); -bool persist_delete_prop(const char *name); -bool persist_set_prop(const char *name, const char *value); +inline void prop_cb_exec(prop_cb *cb, const char *name, const char *value) { + cb->exec(name, value); +} + +void persist_get_prop(const char *name, prop_cb *prop_cb) noexcept; +void persist_get_props(prop_cb *prop_cb) noexcept; +bool persist_delete_prop(const char *name) noexcept; +bool persist_set_prop(const char *name, const char *value) noexcept; diff --git a/native/src/external/Android.mk b/native/src/external/Android.mk index c0ea1980d..5e1fed627 100644 --- a/native/src/external/Android.mk +++ b/native/src/external/Android.mk @@ -17,17 +17,6 @@ LOCAL_SRC_FILES := \ xz-embedded/xz_dec_stream.c include $(BUILD_STATIC_LIBRARY) -# libnanopb.a -include $(CLEAR_VARS) -LOCAL_MODULE:= libnanopb -LOCAL_C_INCLUDES := $(LOCAL_PATH)/nanopb -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) -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/src/external/nanopb b/native/src/external/nanopb deleted file mode 160000 index c9124132a..000000000 --- a/native/src/external/nanopb +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c9124132a604047d0ef97a09c0e99cd9bed2c818