mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 07:57:39 +00:00
Fix proto read and write
This commit is contained in:
parent
35b3c8ba5c
commit
4fff2aa7d8
@ -97,8 +97,8 @@ macro_rules! cstr {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! raw_cstr {
|
macro_rules! raw_cstr {
|
||||||
($s:literal) => {{
|
($($str:tt)*) => {{
|
||||||
cstr!($s).as_ptr()
|
cstr!($($str)*).as_ptr()
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
use core::ffi::c_char;
|
use core::ffi::c_char;
|
||||||
use std::pin::Pin;
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::{read_to_string, remove_file, rename, File},
|
fs::{read_to_string, remove_file, rename, File},
|
||||||
io::{BufWriter, Write},
|
io::{BufWriter, Write},
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
os::fd::FromRawFd,
|
os::fd::FromRawFd,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
pin::Pin,
|
||||||
};
|
};
|
||||||
|
|
||||||
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
||||||
|
|
||||||
use base::{
|
use base::{
|
||||||
cstr, debug, libc::mkstemp, Directory, LoggedResult, MappedFile, StringExt, Utf8CStr,
|
cstr, debug, libc::mkstemp, raw_cstr, Directory, LoggedError, LoggedResult, MappedFile,
|
||||||
WalkResult,
|
StringExt, Utf8CStr, WalkResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ffi::{clone_attr, prop_cb_exec, PropCb};
|
use crate::ffi::{clone_attr, prop_cb_exec, PropCb};
|
||||||
@ -31,17 +32,6 @@ macro_rules! PERSIST_PROP {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MatchNameCb<'a> {
|
|
||||||
cb: Pin<&'a mut PropCb>,
|
|
||||||
name: &'a Utf8CStr,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PropCollectCb<'a> {
|
|
||||||
props: &'a mut PersistentProperties,
|
|
||||||
replace_name: Option<&'a Utf8CStr>,
|
|
||||||
replace_value: Option<&'a Utf8CStr>,
|
|
||||||
}
|
|
||||||
|
|
||||||
trait PropCbExec {
|
trait PropCbExec {
|
||||||
fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr);
|
fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr);
|
||||||
}
|
}
|
||||||
@ -52,54 +42,43 @@ impl PropCbExec for Pin<&mut PropCb> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropCbExec for MatchNameCb<'_> {
|
impl Deref for PersistentProperties {
|
||||||
fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr) {
|
type Target = Vec<PersistentPropertyRecord>;
|
||||||
if name == self.name {
|
|
||||||
self.cb.exec(name, value);
|
fn deref(&self) -> &Self::Target {
|
||||||
debug!("resetprop: found prop [{}] = [{}]", name, value);
|
&self.properties
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for PersistentProperties {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.properties
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PropExt {
|
||||||
|
fn find_index(&self, name: &Utf8CStr) -> Result<usize, usize>;
|
||||||
|
fn find(&mut self, name: &Utf8CStr) -> LoggedResult<&mut PersistentPropertyRecord>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PropExt for PersistentProperties {
|
||||||
|
fn find_index(&self, name: &Utf8CStr) -> Result<usize, usize> {
|
||||||
|
self.binary_search_by(|p| p.name.as_deref().cmp(&Some(name.deref())))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find(&mut self, name: &Utf8CStr) -> LoggedResult<&mut PersistentPropertyRecord> {
|
||||||
|
if let Ok(idx) = self.find_index(name) {
|
||||||
|
Ok(&mut self[idx])
|
||||||
|
} else {
|
||||||
|
Err(LoggedError::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropCbExec for PropCollectCb<'_> {
|
fn check_proto() -> bool {
|
||||||
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()
|
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<String> {
|
fn file_get_prop(name: &Utf8CStr) -> LoggedResult<String> {
|
||||||
let path = PathBuf::new().join(PERSIST_PROP_DIR!()).join(name);
|
let path = PathBuf::new().join(PERSIST_PROP_DIR!()).join(name);
|
||||||
let path = path.as_path();
|
let path = path.as_path();
|
||||||
@ -107,27 +86,6 @@ fn file_get_prop(name: &Utf8CStr) -> LoggedResult<String> {
|
|||||||
Ok(read_to_string(path)?)
|
Ok(read_to_string(path)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pb_write_props(props: &PersistentProperties) -> LoggedResult<()> {
|
|
||||||
let mut tmp = String::from(concat!(PERSIST_PROP!(), ".XXXXXX"));
|
|
||||||
tmp.nul_terminate();
|
|
||||||
{
|
|
||||||
let f = unsafe {
|
|
||||||
let fd = mkstemp(tmp.as_mut_ptr().cast());
|
|
||||||
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().cast());
|
|
||||||
}
|
|
||||||
rename(tmp, PERSIST_PROP!())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn file_set_prop(name: &Utf8CStr, value: Option<&Utf8CStr>) -> LoggedResult<()> {
|
fn file_set_prop(name: &Utf8CStr, value: Option<&Utf8CStr>) -> LoggedResult<()> {
|
||||||
let path = PathBuf::new().join(PERSIST_PROP_DIR!()).join(name);
|
let path = PathBuf::new().join(PERSIST_PROP_DIR!()).join(name);
|
||||||
let path = path.as_path();
|
let path = path.as_path();
|
||||||
@ -152,25 +110,73 @@ fn file_set_prop(name: &Utf8CStr, value: Option<&Utf8CStr>) -> LoggedResult<()>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn proto_read_props() -> LoggedResult<PersistentProperties> {
|
||||||
|
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 props = PersistentProperties::from_reader(&mut r, m)?;
|
||||||
|
// Keep the list sorted for binary search
|
||||||
|
props.sort_unstable_by(|a, b| a.name.cmp(&b.name));
|
||||||
|
Ok(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> {
|
||||||
|
let mut tmp = String::from(concat!(PERSIST_PROP!(), ".XXXXXX"));
|
||||||
|
tmp.nul_terminate();
|
||||||
|
{
|
||||||
|
let f = unsafe {
|
||||||
|
let fd = mkstemp(tmp.as_mut_ptr().cast());
|
||||||
|
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(raw_cstr!(PERSIST_PROP!()), tmp.as_ptr().cast());
|
||||||
|
}
|
||||||
|
rename(tmp, PERSIST_PROP!())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn persist_get_prop(name: *const c_char, prop_cb: Pin<&mut PropCb>) {
|
pub unsafe fn persist_get_prop(name: *const c_char, prop_cb: Pin<&mut PropCb>) {
|
||||||
unsafe fn inner(name: *const c_char, mut prop_cb: Pin<&mut PropCb>) -> LoggedResult<()> {
|
fn inner(name: *const c_char, mut prop_cb: Pin<&mut PropCb>) -> LoggedResult<()> {
|
||||||
let name = Utf8CStr::from_ptr(name)?;
|
let name = unsafe { Utf8CStr::from_ptr(name)? };
|
||||||
if check_pb() {
|
if check_proto() {
|
||||||
pb_get_prop(&mut MatchNameCb { cb: prop_cb, name })
|
let mut props = proto_read_props()?;
|
||||||
|
if let Ok(PersistentPropertyRecord {
|
||||||
|
name: Some(ref mut n),
|
||||||
|
value: Some(ref mut v),
|
||||||
|
}) = props.find(name)
|
||||||
|
{
|
||||||
|
prop_cb.exec(Utf8CStr::from_string(n), Utf8CStr::from_string(v));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut value = file_get_prop(name)?;
|
let mut value = file_get_prop(name)?;
|
||||||
prop_cb.exec(name, Utf8CStr::from_string(&mut value));
|
prop_cb.exec(name, Utf8CStr::from_string(&mut value));
|
||||||
debug!("resetprop: found prop [{}] = [{}]", name, value);
|
debug!("resetprop: found prop [{}] = [{}]", name, value);
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
inner(name, prop_cb).ok();
|
inner(name, prop_cb).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>) {
|
pub unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>) {
|
||||||
fn inner(mut prop_cb: Pin<&mut PropCb>) -> LoggedResult<()> {
|
fn inner(mut prop_cb: Pin<&mut PropCb>) -> LoggedResult<()> {
|
||||||
if check_pb() {
|
if check_proto() {
|
||||||
pb_get_prop(&mut prop_cb)
|
let mut props = proto_read_props()?;
|
||||||
|
props.iter_mut().for_each(|p| {
|
||||||
|
if let PersistentPropertyRecord {
|
||||||
|
name: Some(ref mut n),
|
||||||
|
value: Some(ref mut v),
|
||||||
|
} = p
|
||||||
|
{
|
||||||
|
prop_cb.exec(Utf8CStr::from_string(n), Utf8CStr::from_string(v));
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
let mut dir = Directory::open(cstr!(PERSIST_PROP_DIR!()))?;
|
let mut dir = Directory::open(cstr!(PERSIST_PROP_DIR!()))?;
|
||||||
dir.for_all_file(|f| {
|
dir.for_all_file(|f| {
|
||||||
@ -181,23 +187,23 @@ pub unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>) {
|
|||||||
}
|
}
|
||||||
Ok(WalkResult::Continue)
|
Ok(WalkResult::Continue)
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
inner(prop_cb).ok();
|
inner(prop_cb).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn persist_delete_prop(name: *const c_char) -> bool {
|
pub unsafe fn persist_delete_prop(name: *const c_char) -> bool {
|
||||||
unsafe fn inner(name: *const c_char) -> LoggedResult<()> {
|
fn inner(name: *const c_char) -> LoggedResult<()> {
|
||||||
let name = Utf8CStr::from_ptr(name)?;
|
let name = unsafe { Utf8CStr::from_ptr(name)? };
|
||||||
if check_pb() {
|
if check_proto() {
|
||||||
let mut pp = PersistentProperties { properties: vec![] };
|
let mut props = proto_read_props()?;
|
||||||
pb_get_prop(&mut PropCollectCb {
|
if let Ok(idx) = props.find_index(name) {
|
||||||
props: &mut pp,
|
props.remove(idx);
|
||||||
replace_name: Some(name),
|
proto_write_props(&props)
|
||||||
replace_value: None,
|
} else {
|
||||||
})?;
|
Err(LoggedError::default())
|
||||||
pb_write_props(&pp)
|
}
|
||||||
} else {
|
} else {
|
||||||
file_set_prop(name, None)
|
file_set_prop(name, None)
|
||||||
}
|
}
|
||||||
@ -208,14 +214,19 @@ pub unsafe fn persist_set_prop(name: *const c_char, value: *const c_char) -> boo
|
|||||||
unsafe fn inner(name: *const c_char, value: *const c_char) -> LoggedResult<()> {
|
unsafe fn inner(name: *const c_char, value: *const c_char) -> LoggedResult<()> {
|
||||||
let name = Utf8CStr::from_ptr(name)?;
|
let name = Utf8CStr::from_ptr(name)?;
|
||||||
let value = Utf8CStr::from_ptr(value)?;
|
let value = Utf8CStr::from_ptr(value)?;
|
||||||
if check_pb() {
|
if check_proto() {
|
||||||
let mut pp = PersistentProperties { properties: vec![] };
|
let mut props = proto_read_props()?;
|
||||||
pb_get_prop(&mut PropCollectCb {
|
match props.find_index(name) {
|
||||||
props: &mut pp,
|
Ok(idx) => props[idx].value = Some(value.to_string()),
|
||||||
replace_name: Some(name),
|
Err(idx) => props.insert(
|
||||||
replace_value: Some(value),
|
idx,
|
||||||
})?;
|
PersistentPropertyRecord {
|
||||||
pb_write_props(&pp)
|
name: Some(name.to_string()),
|
||||||
|
value: Some(value.to_string()),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
proto_write_props(&props)
|
||||||
} else {
|
} else {
|
||||||
file_set_prop(name, Some(value))
|
file_set_prop(name, Some(value))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user