diff --git a/native/src/base/cstr.rs b/native/src/base/cstr.rs index 73c002765..e3025335d 100644 --- a/native/src/base/cstr.rs +++ b/native/src/base/cstr.rs @@ -41,7 +41,7 @@ pub mod cstr_buf { use super::{Utf8CStrBufArr, Utf8CStrBufRef, Utf8CString}; #[inline(always)] - pub fn with_capacity(capacity: usize) -> Utf8CString { + pub fn dynamic(capacity: usize) -> Utf8CString { Utf8CString::with_capacity(capacity) } @@ -66,6 +66,63 @@ pub mod cstr_buf { } } +// Union type for storing a Utf8CStrBuf value + +pub enum Utf8CStrBuffer<'a, const N: usize> { + Array(Utf8CStrBufArr), + Reference(Utf8CStrBufRef<'a>), + Dynamic(Utf8CString), + Wrap(&'a mut dyn Utf8CStrBuf), +} + +impl<'a, const N: usize> Deref for Utf8CStrBuffer<'a, N> { + type Target = dyn Utf8CStrBuf + 'a; + + fn deref(&self) -> &Self::Target { + match self { + Utf8CStrBuffer::Array(s) => s, + Utf8CStrBuffer::Reference(s) => s, + Utf8CStrBuffer::Dynamic(s) => s, + Utf8CStrBuffer::Wrap(s) => *s, + } + } +} + +impl DerefMut for Utf8CStrBuffer<'_, N> { + fn deref_mut(&mut self) -> &mut Self::Target { + match self { + Utf8CStrBuffer::Array(s) => s, + Utf8CStrBuffer::Reference(s) => s, + Utf8CStrBuffer::Dynamic(s) => s, + Utf8CStrBuffer::Wrap(s) => *s, + } + } +} + +impl From for Utf8CStrBuffer<'static, 0> { + fn from(value: Utf8CString) -> Self { + Utf8CStrBuffer::Dynamic(value) + } +} + +impl From> for Utf8CStrBuffer<'static, N> { + fn from(value: Utf8CStrBufArr) -> Self { + Utf8CStrBuffer::Array(value) + } +} + +impl<'a> From<&'a mut dyn Utf8CStrBuf> for Utf8CStrBuffer<'a, 0> { + fn from(value: &'a mut dyn Utf8CStrBuf) -> Self { + Utf8CStrBuffer::Wrap(value) + } +} + +impl Default for Utf8CStrBuffer<'static, 4096> { + fn default() -> Self { + Utf8CStrBuffer::Array(cstr_buf::default()) + } +} + // Trait definitions pub trait Utf8CStrBuf: @@ -125,7 +182,7 @@ impl AsUtf8CStr for T { // Implementation for Utf8CString -fn utf8_cstr_buf_append(buf: &mut dyn Utf8CStrBufWithSlice, s: &[u8]) -> usize { +fn utf8_cstr_append(buf: &mut dyn Utf8CStrBufWithSlice, s: &[u8]) -> usize { let mut used = buf.len(); if used >= buf.capacity() - 1 { // Truncate @@ -480,7 +537,7 @@ impl FsPath { } #[inline(always)] - pub const fn from_utfcstr(value: &Utf8CStr) -> &FsPath { + pub const fn __from_utfcstr(value: &Utf8CStr) -> &FsPath { unsafe { mem::transmute(value) } } @@ -525,52 +582,33 @@ impl DerefMut for FsPathFollow { } } -enum Utf8CStrBufOwned { - Dynamic(Utf8CString), - Fixed(Utf8CStrBufArr), -} +pub struct FsPathBuf<'a, const N: usize>(pub Utf8CStrBuffer<'a, N>); -impl Deref for Utf8CStrBufOwned { - type Target = dyn Utf8CStrBuf; - - fn deref(&self) -> &Self::Target { - match self { - Utf8CStrBufOwned::Dynamic(s) => s, - Utf8CStrBufOwned::Fixed(arr) => arr, - } +impl From for FsPathBuf<'static, 0> { + fn from(value: Utf8CString) -> Self { + FsPathBuf(From::from(value)) } } -impl DerefMut for Utf8CStrBufOwned { - fn deref_mut(&mut self) -> &mut Self::Target { - match self { - Utf8CStrBufOwned::Dynamic(s) => s, - Utf8CStrBufOwned::Fixed(arr) => arr, - } +impl From> for FsPathBuf<'static, N> { + fn from(value: Utf8CStrBufArr) -> Self { + FsPathBuf(From::from(value)) } } -pub struct FsPathBuf(Utf8CStrBufOwned); - -impl FsPathBuf<0> { - pub fn new_dynamic(capacity: usize) -> Self { - FsPathBuf(Utf8CStrBufOwned::Dynamic(Utf8CString::with_capacity( - capacity, - ))) +impl<'a> From<&'a mut dyn Utf8CStrBuf> for FsPathBuf<'a, 0> { + fn from(value: &'a mut dyn Utf8CStrBuf) -> Self { + FsPathBuf(From::from(value)) } } -impl Default for FsPathBuf<4096> { +impl Default for FsPathBuf<'static, 4096> { fn default() -> Self { - FsPathBuf(Utf8CStrBufOwned::Fixed(cstr_buf::default())) + FsPathBuf(Default::default()) } } -impl FsPathBuf { - pub fn new() -> Self { - FsPathBuf(Utf8CStrBufOwned::Fixed(cstr_buf::new::())) - } - +impl FsPathBuf<'_, N> { pub fn clear(&mut self) { self.0.clear(); } @@ -595,7 +633,7 @@ impl FsPathBuf { } } -impl Deref for FsPathBuf { +impl Deref for FsPathBuf<'_, N> { type Target = FsPath; fn deref(&self) -> &FsPath { @@ -603,7 +641,7 @@ impl Deref for FsPathBuf { } } -impl DerefMut for FsPathBuf { +impl DerefMut for FsPathBuf<'_, N> { fn deref_mut(&mut self) -> &mut FsPath { FsPath::from_mut(self.0.deref_mut()) } @@ -692,7 +730,7 @@ impl_str!( (Utf8CStr,) (FsPath,) (FsPathFollow,) - (FsPathBuf, const N: usize) + (FsPathBuf<'_, N>, const N: usize) (Utf8CStrBufRef<'_>,) (Utf8CStrBufArr, const N: usize) (Utf8CString,) @@ -749,7 +787,7 @@ macro_rules! impl_str_buf_with_slice { } #[inline(always)] fn push_str(&mut self, s: &str) -> usize { - utf8_cstr_buf_append(self, s.as_bytes()) + utf8_cstr_append(self, s.as_bytes()) } #[inline(always)] fn push_lossy(&mut self, s: &[u8]) -> usize { @@ -791,5 +829,5 @@ macro_rules! raw_cstr { #[macro_export] macro_rules! path { - ($str:expr) => {{ $crate::FsPath::from_utfcstr($crate::cstr!($str)) }}; + ($str:expr) => {{ $crate::FsPath::__from_utfcstr($crate::cstr!($str)) }}; } diff --git a/native/src/base/dir.rs b/native/src/base/dir.rs index b356704ed..c80bd4c55 100644 --- a/native/src/base/dir.rs +++ b/native/src/base/dir.rs @@ -1,7 +1,7 @@ use crate::cxx_extern::readlinkat; use crate::{ - FileAttr, FsPath, LibcReturn, OsError, OsResult, OsResultStatic, Utf8CStr, Utf8CStrBuf, cstr, - cstr_buf, errno, fd_path, fd_set_attr, + FileAttr, FsPath, FsPathBuf, LibcReturn, OsError, OsResult, OsResultStatic, Utf8CStr, + Utf8CStrBuf, cstr, cstr_buf, errno, fd_path, fd_set_attr, }; use libc::{EEXIST, O_CLOEXEC, O_CREAT, O_RDONLY, O_TRUNC, O_WRONLY, dirent, mode_t}; use std::ffi::CStr; @@ -39,8 +39,12 @@ impl DirEntry<'_> { pub fn path(&self, buf: &mut dyn Utf8CStrBuf) -> OsResult<'static, ()> { self.dir.path(buf)?; - buf.push_str("/"); - buf.push_lossy(self.name().to_bytes()); + if let Ok(s) = self.name().to_str() { + FsPathBuf::from(buf).join(s); + } else { + buf.push_str("/"); + buf.push_lossy(self.name().to_bytes()); + } Ok(()) } diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index d0f86d214..eddec0098 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -11,7 +11,8 @@ use crate::package::ManagerInfo; use crate::su::SuInfo; use base::libc::{O_CLOEXEC, O_RDONLY}; use base::{ - AtomicArc, BufReadExt, FsPathBuf, ResultExt, Utf8CStr, cstr, error, info, libc, open_fd, path, + AtomicArc, BufReadExt, FsPathBuf, ResultExt, Utf8CStr, cstr, cstr_buf, error, info, libc, + open_fd, path, }; use std::fs::File; use std::io::BufReader; @@ -228,7 +229,7 @@ pub fn daemon_entry() { || get_prop(cstr!("ro.product.device"), false).contains("vsoc"); // Load config status - let path = FsPathBuf::<64>::new() + let path = FsPathBuf::from(cstr_buf::new::<64>()) .join(get_magisk_tmp()) .join(MAIN_CONFIG); let mut is_recovery = false; diff --git a/native/src/core/mount.rs b/native/src/core/mount.rs index af0824253..75ad73d50 100644 --- a/native/src/core/mount.rs +++ b/native/src/core/mount.rs @@ -7,8 +7,8 @@ use num_traits::AsPrimitive; use base::libc::{c_uint, dev_t}; use base::{ - FsPath, FsPathBuf, LibcReturn, LoggedResult, MountInfo, ResultExt, Utf8CStr, cstr, debug, info, - libc, parse_mount_info, path, warn, + FsPath, FsPathBuf, LibcReturn, LoggedResult, MountInfo, ResultExt, Utf8CStr, cstr, cstr_buf, + debug, info, libc, parse_mount_info, path, warn, }; use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR}; @@ -21,7 +21,9 @@ pub fn setup_mounts() { let magisk_tmp = get_magisk_tmp(); // Mount preinit directory - let dev_path = FsPathBuf::<64>::new().join(magisk_tmp).join(PREINITDEV); + let dev_path = FsPathBuf::from(cstr_buf::new::<64>()) + .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_() { diff --git a/native/src/core/zygisk/daemon.rs b/native/src/core/zygisk/daemon.rs index b5a48f954..3cbac1c0b 100644 --- a/native/src/core/zygisk/daemon.rs +++ b/native/src/core/zygisk/daemon.rs @@ -37,7 +37,9 @@ fn exec_zygiskd(is_64_bit: bool, remote: UnixStream) { #[cfg(target_pointer_width = "32")] let magisk = "magisk"; - let exe = FsPathBuf::<64>::new().join(get_magisk_tmp()).join(magisk); + let exe = FsPathBuf::from(cstr_buf::new::<64>()) + .join(get_magisk_tmp()) + .join(magisk); let mut fd_str = cstr_buf::new::<16>(); write!(fd_str, "{}", remote.as_raw_fd()).ok(); diff --git a/native/src/init/rootdir.rs b/native/src/init/rootdir.rs index ef6b0e323..796fc5697 100644 --- a/native/src/init/rootdir.rs +++ b/native/src/init/rootdir.rs @@ -2,8 +2,8 @@ use crate::consts::{ROOTMNT, ROOTOVL}; use crate::ffi::MagiskInit; use base::libc::{O_CREAT, O_RDONLY, O_WRONLY}; use base::{ - BufReadExt, Directory, FsPath, FsPathBuf, LoggedResult, ResultExt, Utf8CStr, Utf8CString, - clone_attr, cstr, cstr_buf, debug, path, + BufReadExt, Directory, FsPath, FsPathBuf, LoggedResult, ResultExt, Utf8CStr, + Utf8CString, clone_attr, cstr, cstr_buf, debug, path, }; use std::io::BufReader; use std::{ @@ -72,8 +72,12 @@ impl MagiskInit { None => return Ok(()), Some(e) => { let name = e.name().to_str()?; - let src = FsPathBuf::new_dynamic(256).join(src_dir).join(name); - let dest = FsPathBuf::new_dynamic(256).join(dest_dir).join(name); + let src = FsPathBuf::from(cstr_buf::dynamic(256)) + .join(src_dir) + .join(name); + let dest = FsPathBuf::from(cstr_buf::dynamic(256)) + .join(dest_dir) + .join(name); if dest.exists() { if e.is_dir() { // Recursive