diff --git a/native/src/base/cstr.rs b/native/src/base/cstr.rs index 6944cb85c..9bd6bc743 100644 --- a/native/src/base/cstr.rs +++ b/native/src/base/cstr.rs @@ -449,15 +449,57 @@ impl DerefMut for FsPath { } } -pub struct FsPathBuf<'a>(&'a mut dyn Utf8CStrBuf); +enum Utf8CStrBufOwned { + Dynamic(Utf8CString), + Fixed(Utf8CStrBufArr), +} -impl<'a> FsPathBuf<'a> { - pub fn new(value: &'a mut dyn Utf8CStrBuf) -> Self { - value.clear(); - FsPathBuf(value) +impl Deref for Utf8CStrBufOwned { + type Target = dyn Utf8CStrBuf; + + fn deref(&self) -> &Self::Target { + match self { + Utf8CStrBufOwned::Dynamic(s) => s, + Utf8CStrBufOwned::Fixed(arr) => arr, + } + } +} + +impl DerefMut for Utf8CStrBufOwned { + fn deref_mut(&mut self) -> &mut Self::Target { + match self { + Utf8CStrBufOwned::Dynamic(s) => s, + Utf8CStrBufOwned::Fixed(arr) => arr, + } + } +} + +pub struct FsPathBuf(Utf8CStrBufOwned); + +impl FsPathBuf<0> { + pub fn new_dynamic(capacity: usize) -> Self { + FsPathBuf(Utf8CStrBufOwned::Dynamic(Utf8CString::with_capacity( + capacity, + ))) + } +} + +impl Default for FsPathBuf<4096> { + fn default() -> Self { + FsPathBuf(Utf8CStrBufOwned::Fixed(Utf8CStrBufArr::default())) + } +} + +impl FsPathBuf { + pub fn new() -> Self { + FsPathBuf(Utf8CStrBufOwned::Fixed(Utf8CStrBufArr::::new())) } - pub fn join>(self, path: T) -> Self { + pub fn clear(&mut self) { + self.0.clear(); + } + + pub fn join>(mut self, path: T) -> Self { fn inner(buf: &mut dyn Utf8CStrBuf, path: &str) { if path.starts_with('/') { buf.clear(); @@ -466,30 +508,30 @@ impl<'a> FsPathBuf<'a> { } buf.push_str(path); } - inner(self.0, path.as_ref()); + inner(self.0.deref_mut(), path.as_ref()); self } - pub fn join_fmt(self, name: T) -> Self { + pub fn join_fmt(mut self, name: T) -> Self { fn inner(buf: &mut dyn Utf8CStrBuf, path: Arguments) { buf.write_fmt(path).ok(); } - inner(self.0, format_args!("/{}", name)); + inner(self.0.deref_mut(), format_args!("/{}", name)); self } } -impl Deref for FsPathBuf<'_> { +impl Deref for FsPathBuf { type Target = FsPath; fn deref(&self) -> &FsPath { - FsPath::from(&self.0) + FsPath::from(self.0.deref()) } } -impl DerefMut for FsPathBuf<'_> { - fn deref_mut(&mut self) -> &mut Self::Target { - FsPath::from_mut(&mut self.0) +impl DerefMut for FsPathBuf { + fn deref_mut(&mut self) -> &mut FsPath { + FsPath::from_mut(self.0.deref_mut()) } } @@ -575,7 +617,7 @@ macro_rules! impl_str { impl_str!( (Utf8CStr,) (FsPath,) - (FsPathBuf<'_>,) + (FsPathBuf, const N: usize) (Utf8CStrBufRef<'_>,) (Utf8CStrBufArr, const N: usize) (Utf8CString,) diff --git a/native/src/base/files.rs b/native/src/base/files.rs index 3b3ce1bde..2b767d3b2 100644 --- a/native/src/base/files.rs +++ b/native/src/base/files.rs @@ -38,8 +38,7 @@ macro_rules! open_fd { } pub fn fd_path(fd: RawFd, buf: &mut dyn Utf8CStrBuf) -> io::Result<()> { - let mut arr = Utf8CStrBufArr::<40>::new(); - let path = FsPathBuf::new(&mut arr).join("/proc/self/fd").join_fmt(fd); + let path = FsPathBuf::default().join("/proc/self/fd").join_fmt(fd); path.read_link(buf) } diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index 0cf92f8a3..21eb36ffb 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -11,8 +11,7 @@ use crate::package::ManagerInfo; use crate::su::SuInfo; use base::libc::{O_CLOEXEC, O_RDONLY}; use base::{ - cstr, error, info, libc, open_fd, AtomicArc, BufReadExt, FsPath, FsPathBuf, ResultExt, - Utf8CStr, Utf8CStrBufArr, + cstr, error, info, libc, open_fd, AtomicArc, BufReadExt, FsPath, FsPathBuf, ResultExt, Utf8CStr, }; use std::fs::File; use std::io::BufReader; @@ -229,8 +228,7 @@ pub fn daemon_entry() { || get_prop(cstr!("ro.product.device"), false).contains("vsoc"); // Load config status - let mut buf = Utf8CStrBufArr::<64>::new(); - let path = FsPathBuf::new(&mut buf) + let path = FsPathBuf::<64>::new() .join(get_magisk_tmp()) .join(MAIN_CONFIG); let mut is_recovery = false; diff --git a/native/src/core/logging.rs b/native/src/core/logging.rs index 2c16d94d1..077c672f8 100644 --- a/native/src/core/logging.rs +++ b/native/src/core/logging.rs @@ -180,10 +180,7 @@ pub fn zygisk_get_logd() -> i32 { let mut fd = ZYGISK_LOGD.load(Ordering::Relaxed); if fd < 0 { android_logging(); - let mut buf = Utf8CStrBufArr::default(); - let path = FsPathBuf::new(&mut buf) - .join(get_magisk_tmp()) - .join(LOG_PIPE); + let path = FsPathBuf::default().join(get_magisk_tmp()).join(LOG_PIPE); // Open as RW as sometimes it may block fd = unsafe { libc::open(path.as_ptr(), O_RDWR | O_CLOEXEC) }; if fd >= 0 { @@ -358,10 +355,7 @@ pub fn setup_logfile() { } pub fn start_log_daemon() { - let mut buf = Utf8CStrBufArr::default(); - let path = FsPathBuf::new(&mut buf) - .join(get_magisk_tmp()) - .join(LOG_PIPE); + let path = FsPathBuf::default().join(get_magisk_tmp()).join(LOG_PIPE); unsafe { libc::mkfifo(path.as_ptr(), 0o666); diff --git a/native/src/core/mount.rs b/native/src/core/mount.rs index e4472930d..2edb1a0f4 100644 --- a/native/src/core/mount.rs +++ b/native/src/core/mount.rs @@ -20,13 +20,9 @@ pub fn setup_mounts() { info!("* Setup internal mounts"); let magisk_tmp = get_magisk_tmp(); - let mut buf = Utf8CStrBufArr::default(); // Mount preinit directory - let mut dev_buf = Utf8CStrBufArr::<64>::new(); - let dev_path = FsPathBuf::new(&mut dev_buf) - .join(magisk_tmp) - .join(PREINITDEV); + let dev_path = FsPathBuf::<64>::new().join(magisk_tmp).join(PREINITDEV); let mut linked = false; if let Ok(attr) = dev_path.get_attr() { if attr.st.st_mode & libc::S_IFMT as c_uint == libc::S_IFBLK.as_() { @@ -36,7 +32,7 @@ pub fn setup_mounts() { // What we do instead is to scan through the current mountinfo and find a pre-existing // mount point mounting our desired partition, and then bind mount the target folder. let preinit_dev = attr.st.st_rdev; - let mnt_path = FsPathBuf::new(&mut buf).join(magisk_tmp).join(PREINITMIRR); + let mnt_path = FsPathBuf::default().join(magisk_tmp).join(PREINITMIRR); for info in parse_mount_info("self") { if info.root == "/" && info.device == preinit_dev { if !info.fs_option.split(',').any(|s| s == "rw") { @@ -74,7 +70,7 @@ pub fn setup_mounts() { } // Bind remount module root to clear nosuid - let module_mnt = FsPathBuf::new(&mut buf).join(magisk_tmp).join(MODULEMNT); + let module_mnt = FsPathBuf::default().join(magisk_tmp).join(MODULEMNT); let _: LoggedResult<()> = try { module_mnt.mkdir(0o755)?; unsafe { @@ -101,16 +97,15 @@ pub fn setup_mounts() { pub fn clean_mounts() { let magisk_tmp = get_magisk_tmp(); - let mut buf = Utf8CStrBufArr::default(); - - let module_mnt = FsPathBuf::new(&mut buf).join(magisk_tmp).join(MODULEMNT); + let mut module_mnt = FsPathBuf::default().join(magisk_tmp).join(MODULEMNT); let _: LoggedResult<()> = try { unsafe { libc::umount2(module_mnt.as_ptr(), libc::MNT_DETACH).as_os_err()?; } }; - let worker_dir = FsPathBuf::new(&mut buf).join(magisk_tmp).join(WORKERDIR); + module_mnt.clear(); + let worker_dir = module_mnt.join(magisk_tmp).join(WORKERDIR); let _: LoggedResult<()> = try { unsafe { libc::mount( @@ -218,8 +213,7 @@ pub fn find_preinit_device() -> String { && let Ok(tmp) = std::env::var("MAGISKTMP") && !tmp.is_empty() { - let mut buf = Utf8CStrBufArr::default(); - let mirror_dir = FsPathBuf::new(&mut buf).join(&tmp).join(PREINITMIRR); + let mut mirror_dir = FsPathBuf::default().join(&tmp).join(PREINITMIRR); let preinit_dir = FsPath::from(Utf8CStr::from_string(&mut preinit_dir)); let _: LoggedResult<()> = try { preinit_dir.mkdirs(0o700)?; @@ -236,7 +230,8 @@ pub fn find_preinit_device() -> String { } }; if std::env::var_os("MAKEDEV").is_some() { - let dev_path = FsPathBuf::new(&mut buf).join(&tmp).join(PREINITDEV); + mirror_dir.clear(); + let dev_path = mirror_dir.join(&tmp).join(PREINITDEV); unsafe { libc::mknod( dev_path.as_ptr(), diff --git a/native/src/core/package.rs b/native/src/core/package.rs index c8ea1e69e..57b4c1851 100644 --- a/native/src/core/package.rs +++ b/native/src/core/package.rs @@ -239,8 +239,7 @@ impl TrackedFile { impl ManagerInfo { fn check_dyn(&mut self, daemon: &MagiskD, user: i32, pkg: &str) -> Status { - let mut arr = Utf8CStrBufArr::default(); - let apk = FsPathBuf::new(&mut arr) + let apk = FsPathBuf::default() .join(daemon.app_data_dir()) .join_fmt(user) .join(pkg) @@ -444,8 +443,7 @@ impl ManagerInfo { impl MagiskD { fn get_package_uid(&self, user: i32, pkg: &str) -> i32 { - let mut arr = Utf8CStrBufArr::default(); - let path = FsPathBuf::new(&mut arr) + let path = FsPathBuf::default() .join(self.app_data_dir()) .join_fmt(user) .join(pkg); @@ -457,10 +455,7 @@ impl MagiskD { pub fn preserve_stub_apk(&self) { let mut info = self.manager_info.lock().unwrap(); - let mut arr = Utf8CStrBufArr::default(); - let apk = FsPathBuf::new(&mut arr) - .join(get_magisk_tmp()) - .join("stub.apk"); + let apk = FsPathBuf::default().join(get_magisk_tmp()).join("stub.apk"); if let Ok(mut fd) = apk.open(O_RDONLY | O_CLOEXEC) { info.trusted_cert = read_certificate(&mut fd, MAGISK_VER_CODE); diff --git a/native/src/core/resetprop/persist.rs b/native/src/core/resetprop/persist.rs index 1eff1b93f..e246583d4 100644 --- a/native/src/core/resetprop/persist.rs +++ b/native/src/core/resetprop/persist.rs @@ -12,7 +12,7 @@ use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer}; use base::libc::{O_CLOEXEC, O_RDONLY}; use base::{ clone_attr, cstr, debug, libc::mkstemp, Directory, FsPath, FsPathBuf, LibcReturn, LoggedResult, - MappedFile, SilentResultExt, Utf8CStr, Utf8CStrBufArr, WalkResult, + MappedFile, SilentResultExt, Utf8CStr, WalkResult, }; use crate::ffi::{prop_cb_exec, PropCb}; @@ -77,10 +77,7 @@ fn check_proto() -> bool { } fn file_get_prop(name: &Utf8CStr) -> LoggedResult { - let mut buf = Utf8CStrBufArr::default(); - let path = FsPathBuf::new(&mut buf) - .join(PERSIST_PROP_DIR!()) - .join(name); + let path = FsPathBuf::default().join(PERSIST_PROP_DIR!()).join(name); let mut file = path.open(O_RDONLY | O_CLOEXEC).silent()?; debug!("resetprop: read prop from [{}]", path); let mut s = String::new(); @@ -89,13 +86,9 @@ fn file_get_prop(name: &Utf8CStr) -> LoggedResult { } fn file_set_prop(name: &Utf8CStr, value: Option<&Utf8CStr>) -> LoggedResult<()> { - let mut buf = Utf8CStrBufArr::default(); - let path = FsPathBuf::new(&mut buf) - .join(PERSIST_PROP_DIR!()) - .join(name); + let path = FsPathBuf::default().join(PERSIST_PROP_DIR!()).join(name); if let Some(value) = value { - let mut buf = Utf8CStrBufArr::default(); - let mut tmp = FsPathBuf::new(&mut buf) + let mut tmp = FsPathBuf::default() .join(PERSIST_PROP_DIR!()) .join("prop.XXXXXX"); { @@ -126,8 +119,7 @@ fn proto_read_props() -> LoggedResult { } fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> { - let mut buf = Utf8CStrBufArr::default(); - let mut tmp = FsPathBuf::new(&mut buf).join(concat!(PERSIST_PROP!(), ".XXXXXX")); + let mut tmp = FsPathBuf::default().join(concat!(PERSIST_PROP!(), ".XXXXXX")); { let f = unsafe { let fd = mkstemp(tmp.as_mut_ptr()).check_os_err()?; diff --git a/native/src/core/zygisk/daemon.rs b/native/src/core/zygisk/daemon.rs index 03ec9b23d..6059ec6ec 100644 --- a/native/src/core/zygisk/daemon.rs +++ b/native/src/core/zygisk/daemon.rs @@ -30,7 +30,6 @@ fn exec_zygiskd(is_64_bit: bool, remote: UnixStream) { } // Start building the exec arguments - let mut exe = Utf8CStrBufArr::<64>::new(); #[cfg(target_pointer_width = "64")] let magisk = if is_64_bit { "magisk" } else { "magisk32" }; @@ -38,7 +37,7 @@ fn exec_zygiskd(is_64_bit: bool, remote: UnixStream) { #[cfg(target_pointer_width = "32")] let magisk = "magisk"; - let exe = FsPathBuf::new(&mut exe).join(get_magisk_tmp()).join(magisk); + let exe = FsPathBuf::<64>::new().join(get_magisk_tmp()).join(magisk); let mut fd_str = Utf8CStrBufArr::<16>::new(); write!(fd_str, "{}", remote.as_raw_fd()).ok(); @@ -184,8 +183,7 @@ impl MagiskD { let failed_ids: Vec = client.read_decodable()?; if let Some(module_list) = self.module_list.get() { for id in failed_ids { - let mut buf = Utf8CStrBufArr::default(); - let path = FsPathBuf::new(&mut buf) + let path = FsPathBuf::default() .join(MODULEROOT) .join(&module_list[id as usize].name) .join("zygisk"); @@ -204,8 +202,7 @@ impl MagiskD { fn get_mod_dir(&self, mut client: UnixStream) -> LoggedResult<()> { let id: i32 = client.read_decodable()?; let module = &self.module_list.get().unwrap()[id as usize]; - let mut buf = Utf8CStrBufArr::default(); - let dir = FsPathBuf::new(&mut buf).join(MODULEROOT).join(&module.name); + let dir = FsPathBuf::default().join(MODULEROOT).join(&module.name); let fd = open_fd!(&dir, O_RDONLY | O_CLOEXEC)?; client.send_fds(&[fd.as_raw_fd()])?; Ok(())