Stop using PathBuf in package.rs

This commit is contained in:
topjohnwu 2025-04-24 16:47:55 -07:00 committed by John Wu
parent 4ad26d3dfb
commit c7d1af9805
2 changed files with 34 additions and 35 deletions

View File

@ -192,6 +192,12 @@ impl From<String> for Utf8CString {
} }
} }
impl From<&str> for Utf8CString {
fn from(value: &str) -> Self {
value.to_string().into()
}
}
impl Borrow<Utf8CStr> for Utf8CString { impl Borrow<Utf8CStr> for Utf8CString {
fn borrow(&self) -> &Utf8CStr { fn borrow(&self) -> &Utf8CStr {
self.deref() self.deref()

View File

@ -4,8 +4,8 @@ use crate::ffi::{DbEntryKey, get_magisk_tmp, install_apk, uninstall_pkg};
use base::WalkResult::{Abort, Continue, Skip}; use base::WalkResult::{Abort, Continue, Skip};
use base::libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_TRUNC, O_WRONLY}; use base::libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_TRUNC, O_WRONLY};
use base::{ use base::{
BufReadExt, Directory, FsPathBuilder, LoggedResult, ReadExt, ResultExt, Utf8CStrBuf, cstr, BufReadExt, Directory, FsPathBuilder, LoggedResult, ReadExt, ResultExt, Utf8CStrBuf,
error, fd_get_attr, warn, Utf8CString, cstr, error, fd_get_attr, warn,
}; };
use bit_set::BitSet; use bit_set::BitSet;
use cxx::CxxString; use cxx::CxxString;
@ -14,14 +14,13 @@ use std::fs::File;
use std::io; use std::io;
use std::io::{Cursor, Read, Seek, SeekFrom}; use std::io::{Cursor, Read, Seek, SeekFrom};
use std::os::fd::AsRawFd; use std::os::fd::AsRawFd;
use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};
use std::pin::Pin; use std::pin::Pin;
use std::time::Duration; use std::time::Duration;
const EOCD_MAGIC: u32 = 0x06054B50; const EOCD_MAGIC: u32 = 0x06054B50;
const APK_SIGNING_BLOCK_MAGIC: [u8; 16] = *b"APK Sig Block 42"; const APK_SIGNING_BLOCK_MAGIC: [u8; 16] = *b"APK Sig Block 42";
const SIGNATURE_SCHEME_V2_MAGIC: u32 = 0x7109871A; const SIGNATURE_SCHEME_V2_MAGIC: u32 = 0x7109871A;
const PACKAGES_XML: &str = "/data/system/packages.xml";
macro_rules! bad_apk { macro_rules! bad_apk {
($msg:literal) => { ($msg:literal) => {
@ -152,7 +151,8 @@ fn read_certificate(apk: &mut File, version: i32) -> Vec<u8> {
res.log().unwrap_or(vec![]) res.log().unwrap_or(vec![])
} }
fn find_apk_path(pkg: &str, buf: &mut dyn Utf8CStrBuf) -> LoggedResult<()> { fn find_apk_path(pkg: &str) -> LoggedResult<Utf8CString> {
let mut buf = cstr::buf::default();
Directory::open(cstr!("/data/app"))?.pre_order_walk(|e| { Directory::open(cstr!("/data/app"))?.pre_order_walk(|e| {
if !e.is_dir() { if !e.is_dir() {
return Ok(Skip); return Ok(Skip);
@ -160,7 +160,7 @@ fn find_apk_path(pkg: &str, buf: &mut dyn Utf8CStrBuf) -> LoggedResult<()> {
let name_bytes = e.name().as_bytes(); let name_bytes = e.name().as_bytes();
if name_bytes.starts_with(pkg.as_bytes()) && name_bytes[pkg.len()] == b'-' { if name_bytes.starts_with(pkg.as_bytes()) && name_bytes[pkg.len()] == b'-' {
// Found the APK path, we can abort now // Found the APK path, we can abort now
e.resolve_path(buf)?; e.resolve_path(&mut buf)?;
return Ok(Abort); return Ok(Abort);
} }
if name_bytes.starts_with(b"~~") { if name_bytes.starts_with(b"~~") {
@ -171,7 +171,7 @@ fn find_apk_path(pkg: &str, buf: &mut dyn Utf8CStrBuf) -> LoggedResult<()> {
if !buf.is_empty() { if !buf.is_empty() {
buf.push_str("/base.apk"); buf.push_str("/base.apk");
} }
Ok(()) Ok(buf.to_owned())
} }
enum Status { enum Status {
@ -204,35 +204,29 @@ impl Default for ManagerInfo {
#[derive(Default)] #[derive(Default)]
struct TrackedFile { struct TrackedFile {
path: PathBuf, path: Utf8CString,
timestamp: Duration, timestamp: Duration,
} }
impl TrackedFile { impl TrackedFile {
fn new<T: AsRef<Path>>(path: T) -> TrackedFile { fn new(path: Utf8CString) -> TrackedFile {
fn inner(path: &Path) -> TrackedFile { let attr = match path.get_attr() {
let meta = match path.metadata() { Ok(attr) => attr,
Ok(meta) => meta, Err(_) => return TrackedFile::default(),
Err(_) => return TrackedFile::default(), };
}; let timestamp = Duration::new(attr.st.st_ctime as u64, attr.st.st_ctime_nsec as u32);
let timestamp = Duration::new(meta.ctime() as u64, meta.ctime_nsec() as u32); TrackedFile { path, timestamp }
TrackedFile {
path: PathBuf::from(path),
timestamp,
}
}
inner(path.as_ref())
} }
fn is_same(&self) -> bool { fn is_same(&self) -> bool {
if self.path.as_os_str().is_empty() { if self.path.is_empty() {
return false; return false;
} }
let meta = match self.path.metadata() { let attr = match self.path.get_attr() {
Ok(meta) => meta, Ok(attr) => attr,
Err(_) => return false, Err(_) => return false,
}; };
let timestamp = Duration::new(meta.ctime() as u64, meta.ctime_nsec() as u32); let timestamp = Duration::new(attr.st.st_ctime as u64, attr.st.st_ctime_nsec as u32);
timestamp == self.timestamp timestamp == self.timestamp
} }
} }
@ -268,15 +262,15 @@ impl ManagerInfo {
} }
self.repackaged_app_id = to_app_id(uid); self.repackaged_app_id = to_app_id(uid);
self.tracked_files.insert(user, TrackedFile::new(apk)); self.tracked_files
.insert(user, TrackedFile::new(apk.to_owned()));
Status::Installed Status::Installed
} }
fn check_stub(&mut self, user: i32, pkg: &str) -> Status { fn check_stub(&mut self, user: i32, pkg: &str) -> Status {
let mut apk = cstr::buf::default(); let Ok(apk) = find_apk_path(pkg) else {
if find_apk_path(pkg, &mut apk).is_err() {
return Status::NotInstalled; return Status::NotInstalled;
} };
let cert = match apk.open(O_RDONLY | O_CLOEXEC) { let cert = match apk.open(O_RDONLY | O_CLOEXEC) {
Ok(mut fd) => read_certificate(&mut fd, -1), Ok(mut fd) => read_certificate(&mut fd, -1),
@ -297,10 +291,9 @@ impl ManagerInfo {
} }
fn check_orig(&mut self, user: i32) -> Status { fn check_orig(&mut self, user: i32) -> Status {
let mut apk = cstr::buf::default(); let Ok(apk) = find_apk_path(APP_PACKAGE_NAME) else {
if find_apk_path(APP_PACKAGE_NAME, &mut apk).is_err() {
return Status::NotInstalled; return Status::NotInstalled;
} };
let cert = match apk.open(O_RDONLY | O_CLOEXEC) { let cert = match apk.open(O_RDONLY | O_CLOEXEC) {
Ok(mut fd) => read_certificate(&mut fd, MAGISK_VER_CODE), Ok(mut fd) => read_certificate(&mut fd, MAGISK_VER_CODE),
@ -351,14 +344,14 @@ impl ManagerInfo {
&& file.is_same() && file.is_same()
{ {
// no APK // no APK
if file.path == Path::new("/data/system/packages.xml") { if &file.path == PACKAGES_XML {
if install && !daemon.is_emulator { if install && !daemon.is_emulator {
self.install_stub(); self.install_stub();
} }
return (-1, ""); return (-1, "");
} }
// dyn APK is still the same // dyn APK is still the same
if file.path.starts_with(daemon.app_data_dir()) { if file.path.starts_with(daemon.app_data_dir().as_str()) {
return ( return (
user * AID_USER_OFFSET + self.repackaged_app_id, user * AID_USER_OFFSET + self.repackaged_app_id,
&self.repackaged_pkg, &self.repackaged_pkg,
@ -427,7 +420,7 @@ impl ManagerInfo {
// If we cannot find any manager, track packages.xml for new package installs // If we cannot find any manager, track packages.xml for new package installs
self.tracked_files self.tracked_files
.insert(user, TrackedFile::new("/data/system/packages.xml")); .insert(user, TrackedFile::new(PACKAGES_XML.into()));
if install && !daemon.is_emulator { if install && !daemon.is_emulator {
self.install_stub(); self.install_stub();