mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-12-14 04:22:01 +00:00
Add more to the Utf8CStr family
Better C strings with path operations
This commit is contained in:
@@ -3,7 +3,7 @@ use std::fs::File;
|
||||
use std::io;
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
|
||||
use base::{copy_str, cstr, Directory, ResultExt, Utf8CStr, WalkResult};
|
||||
use base::{cstr, Directory, ResultExt, Utf8CStr, Utf8CStrBuf, Utf8CStrSlice, WalkResult};
|
||||
|
||||
use crate::logging::{magisk_logging, zygisk_logging};
|
||||
|
||||
@@ -36,8 +36,7 @@ impl MagiskD {}
|
||||
|
||||
pub fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize {
|
||||
use WalkResult::*;
|
||||
fn inner(pkg: &[u8], data: &mut [u8]) -> io::Result<usize> {
|
||||
let mut len = 0_usize;
|
||||
fn inner(pkg: &[u8], buf: &mut dyn Utf8CStrBuf) -> io::Result<usize> {
|
||||
let pkg = match Utf8CStr::from_bytes(pkg) {
|
||||
Ok(pkg) => pkg,
|
||||
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
|
||||
@@ -49,7 +48,7 @@ pub fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize {
|
||||
let d_name = e.d_name().to_bytes();
|
||||
if d_name.starts_with(pkg.as_bytes()) && d_name[pkg.len()] == b'-' {
|
||||
// Found the APK path, we can abort now
|
||||
len = e.path(data)?;
|
||||
e.path(buf)?;
|
||||
return Ok(Abort);
|
||||
}
|
||||
if d_name.starts_with(b"~~") {
|
||||
@@ -57,10 +56,12 @@ pub fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize {
|
||||
}
|
||||
Ok(Skip)
|
||||
})?;
|
||||
if len > 0 {
|
||||
len += copy_str(&mut data[len..], "/base.apk");
|
||||
if !buf.is_empty() {
|
||||
buf.append("/base.apk");
|
||||
}
|
||||
Ok(len)
|
||||
Ok(buf.len())
|
||||
}
|
||||
inner(pkg, data).log().unwrap_or(0)
|
||||
inner(pkg, &mut Utf8CStrSlice::from(data))
|
||||
.log()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::cmp::min;
|
||||
use std::ffi::{c_char, c_void};
|
||||
use std::fmt::Write as FmtWrite;
|
||||
use std::fs::File;
|
||||
use std::io::{IoSlice, Read, Write};
|
||||
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
|
||||
@@ -244,8 +245,8 @@ extern "C" fn logfile_writer(arg: *mut c_void) -> *mut c_void {
|
||||
let mut logfile: LogFile = Buffer(&mut tmp);
|
||||
|
||||
let mut meta = LogMeta::default();
|
||||
let mut buf: [u8; MAX_MSG_LEN] = [0; MAX_MSG_LEN];
|
||||
let mut aux: [u8; 64] = [0; 64];
|
||||
let mut msg_buf = [0u8; MAX_MSG_LEN];
|
||||
let mut aux = Utf8CStrArr::<64>::new();
|
||||
|
||||
loop {
|
||||
// Read request
|
||||
@@ -262,16 +263,16 @@ extern "C" fn logfile_writer(arg: *mut c_void) -> *mut c_void {
|
||||
continue;
|
||||
}
|
||||
|
||||
if meta.len < 0 || meta.len > buf.len() as i32 {
|
||||
if meta.len < 0 || meta.len > MAX_MSG_LEN as i32 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read the rest of the message
|
||||
let msg = &mut buf[..(meta.len as usize)];
|
||||
let msg = &mut msg_buf[..(meta.len as usize)];
|
||||
pipe.read_exact(msg)?;
|
||||
|
||||
// Start building the log string
|
||||
|
||||
aux.clear();
|
||||
let prio =
|
||||
ALogPriority::from_i32(meta.prio).unwrap_or(ALogPriority::ANDROID_LOG_UNKNOWN);
|
||||
let prio = match prio {
|
||||
@@ -287,7 +288,6 @@ extern "C" fn logfile_writer(arg: *mut c_void) -> *mut c_void {
|
||||
// Note: the obvious better implementation is to use the rust chrono crate, however
|
||||
// the crate cannot fetch the proper local timezone without pulling in a bunch of
|
||||
// timezone handling code. To reduce binary size, fallback to use localtime_r in libc.
|
||||
let mut aux_len: usize;
|
||||
unsafe {
|
||||
let mut ts: timespec = std::mem::zeroed();
|
||||
let mut tm: tm = std::mem::zeroed();
|
||||
@@ -296,24 +296,22 @@ extern "C" fn logfile_writer(arg: *mut c_void) -> *mut c_void {
|
||||
{
|
||||
continue;
|
||||
}
|
||||
aux_len = strftime(
|
||||
aux.as_mut_ptr().cast(),
|
||||
aux.len(),
|
||||
let len = strftime(
|
||||
aux.mut_buf().as_mut_ptr().cast(),
|
||||
aux.capacity(),
|
||||
raw_cstr!("%m-%d %T"),
|
||||
&tm,
|
||||
);
|
||||
aux.set_len(len);
|
||||
let ms = ts.tv_nsec / 1000000;
|
||||
aux_len += bfmt!(
|
||||
&mut aux[aux_len..],
|
||||
aux.write_fmt(format_args!(
|
||||
".{:03} {:5} {:5} {} : ",
|
||||
ms,
|
||||
meta.pid,
|
||||
meta.tid,
|
||||
prio
|
||||
);
|
||||
ms, meta.pid, meta.tid, prio
|
||||
))
|
||||
.ok();
|
||||
}
|
||||
|
||||
let io1 = IoSlice::new(&aux[..aux_len]);
|
||||
let io1 = IoSlice::new(aux.as_bytes_with_nul());
|
||||
let io2 = IoSlice::new(msg);
|
||||
// We don't need to care the written len because we are writing less than PIPE_BUF
|
||||
// It's guaranteed to always write the whole thing atomically
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use core::ffi::c_char;
|
||||
use std::io::Read;
|
||||
use std::{
|
||||
fs::{read_to_string, remove_file, rename, File},
|
||||
fs::File,
|
||||
io::{BufWriter, Write},
|
||||
ops::{Deref, DerefMut},
|
||||
os::fd::FromRawFd,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
};
|
||||
|
||||
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
||||
|
||||
use base::libc::{O_CLOEXEC, O_RDONLY};
|
||||
use base::{
|
||||
cstr, debug, libc::mkstemp, raw_cstr, Directory, LoggedError, LoggedResult, MappedFile,
|
||||
StringExt, Utf8CStr, WalkResult,
|
||||
cstr, debug, libc::mkstemp, raw_cstr, Directory, FsPath, FsPathBuf, LibcReturn, LoggedError,
|
||||
LoggedResult, MappedFile, Utf8CStr, Utf8CStrArr, WalkResult,
|
||||
};
|
||||
|
||||
use crate::ffi::{clone_attr, prop_cb_exec, PropCb};
|
||||
@@ -76,36 +77,41 @@ impl PropExt for PersistentProperties {
|
||||
}
|
||||
|
||||
fn check_proto() -> bool {
|
||||
Path::new(PERSIST_PROP!()).exists()
|
||||
FsPath::from(cstr!(PERSIST_PROP!())).exists()
|
||||
}
|
||||
|
||||
fn file_get_prop(name: &Utf8CStr) -> LoggedResult<String> {
|
||||
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)?)
|
||||
let mut buf = Utf8CStrArr::default();
|
||||
let path = FsPathBuf::new(&mut buf)
|
||||
.join(PERSIST_PROP_DIR!())
|
||||
.join(name);
|
||||
let mut file = path.open(O_RDONLY | O_CLOEXEC)?;
|
||||
debug!("resetprop: read prop from [{}]\n", path);
|
||||
let mut s = String::new();
|
||||
file.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
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();
|
||||
let mut buf = Utf8CStrArr::default();
|
||||
let path = FsPathBuf::new(&mut buf)
|
||||
.join(PERSIST_PROP_DIR!())
|
||||
.join(name);
|
||||
if let Some(value) = value {
|
||||
let mut tmp = String::from(concat!(PERSIST_PROP_DIR!(), ".prop.XXXXXX"));
|
||||
let mut buf = Utf8CStrArr::default();
|
||||
let mut tmp = FsPathBuf::new(&mut buf).join(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());
|
||||
}
|
||||
let fd = mkstemp(tmp.as_mut_ptr()).check_os_err()?;
|
||||
File::from_raw_fd(fd)
|
||||
};
|
||||
f.write_all(value.as_bytes())?;
|
||||
}
|
||||
debug!("resetprop: write prop to [{}]\n", tmp);
|
||||
rename(tmp, path)?;
|
||||
tmp.rename_to(path)?
|
||||
} else {
|
||||
debug!("resetprop: unlink [{}]\n", path.display());
|
||||
remove_file(path)?;
|
||||
debug!("resetprop: unlink [{}]\n", path);
|
||||
path.remove()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -122,23 +128,18 @@ fn proto_read_props() -> LoggedResult<PersistentProperties> {
|
||||
}
|
||||
|
||||
fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> {
|
||||
let mut tmp = String::from(concat!(PERSIST_PROP!(), ".XXXXXX"));
|
||||
tmp.nul_terminate();
|
||||
let mut buf = Utf8CStrArr::default();
|
||||
let mut tmp = FsPathBuf::new(&mut buf).join(concat!(PERSIST_PROP!(), ".XXXXXX"));
|
||||
{
|
||||
let f = unsafe {
|
||||
let fd = mkstemp(tmp.as_mut_ptr().cast());
|
||||
if fd < 0 {
|
||||
return Err(Default::default());
|
||||
}
|
||||
let fd = mkstemp(tmp.as_mut_ptr()).check_os_err()?;
|
||||
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!())?;
|
||||
unsafe { clone_attr(raw_cstr!(PERSIST_PROP!()), tmp.as_ptr()) };
|
||||
tmp.rename_to(cstr!(PERSIST_PROP!()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user