mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-29 22:14:27 +02:00
Make FsPath a trait
This commit is contained in:
parent
c34c7838bb
commit
f3fef7bfe4
@ -11,8 +11,7 @@ use std::str::Utf8Error;
|
||||
use std::{fmt, mem, slice, str};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::slice_from_ptr_mut;
|
||||
|
||||
use crate::{FsPath, FsPathMnt, slice_from_ptr_mut};
|
||||
// Utf8CStr types are UTF-8 validated and null terminated strings.
|
||||
//
|
||||
// Several Utf8CStr types:
|
||||
@ -415,32 +414,6 @@ const_assert_eq!(align_of::<&Utf8CStr>(), align_of::<[usize; 2]>());
|
||||
|
||||
// File system path extensions types
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct FsPath(Utf8CStr);
|
||||
|
||||
impl FsPath {
|
||||
#[inline(always)]
|
||||
pub fn from<T: AsRef<Utf8CStr> + ?Sized>(value: &T) -> &FsPath {
|
||||
unsafe { mem::transmute(value.as_ref()) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub const fn __from_utfcstr(value: &Utf8CStr) -> &FsPath {
|
||||
unsafe { mem::transmute(value) }
|
||||
}
|
||||
|
||||
pub fn follow_link(&self) -> &FsPathFollow {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsUtf8CStr for FsPath {
|
||||
#[inline(always)]
|
||||
fn as_utf8_cstr(&self) -> &Utf8CStr {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct FsPathFollow(Utf8CStr);
|
||||
|
||||
@ -502,11 +475,10 @@ impl<const N: usize> FsPathBuf<'_, N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Deref for FsPathBuf<'_, N> {
|
||||
type Target = FsPath;
|
||||
|
||||
fn deref(&self) -> &FsPath {
|
||||
FsPath::from(self.0.deref())
|
||||
impl<const N: usize> AsUtf8CStr for FsPathBuf<'_, N> {
|
||||
#[inline(always)]
|
||||
fn as_utf8_cstr(&self) -> &Utf8CStr {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
@ -525,11 +497,11 @@ macro_rules! impl_cstr_deref {
|
||||
}
|
||||
|
||||
impl_cstr_deref!(
|
||||
(FsPath,)
|
||||
(FsPathFollow,)
|
||||
(Utf8CStrBufRef<'_>,)
|
||||
(Utf8CStrBufArr<N>, const N: usize)
|
||||
(Utf8CString,)
|
||||
(FsPathFollow,)
|
||||
(FsPathBuf<'_, N>, const N: usize)
|
||||
);
|
||||
|
||||
// impl<T: Deref<Target = Utf8CStr>> BoilerPlate for T { ... }
|
||||
@ -612,12 +584,11 @@ macro_rules! impl_cstr_misc {
|
||||
|
||||
impl_cstr_misc!(
|
||||
(Utf8CStr,)
|
||||
(FsPath,)
|
||||
(FsPathFollow,)
|
||||
(FsPathBuf<'_, N>, const N: usize)
|
||||
(Utf8CStrBufRef<'_>,)
|
||||
(Utf8CStrBufArr<N>, const N: usize)
|
||||
(Utf8CString,)
|
||||
(FsPathFollow,)
|
||||
(FsPathBuf<'_, N>, const N: usize)
|
||||
);
|
||||
|
||||
fn copy_cstr_truncate(dest: &mut [u8], src: &[u8]) -> usize {
|
||||
@ -703,6 +674,23 @@ impl_cstr_buf_write!(
|
||||
(Utf8CString,)
|
||||
);
|
||||
|
||||
// impl<T: Deref<Target = Utf8CStr>> FsPath for T {}
|
||||
// impl<T: Deref<Target = Utf8CStr>> FsPathMnt for T {}
|
||||
macro_rules! impl_fs_path {
|
||||
($( ($t:ty, $($g:tt)*) )*) => {$(
|
||||
impl<$($g)*> FsPath for $t {}
|
||||
impl<$($g)*> FsPathMnt for $t {}
|
||||
)*}
|
||||
}
|
||||
|
||||
impl_fs_path!(
|
||||
(&Utf8CStr,)
|
||||
(Utf8CStrBufRef<'_>,)
|
||||
(Utf8CStrBufArr<N>, const N: usize)
|
||||
(Utf8CString,)
|
||||
(FsPathBuf<'_, N>, const N: usize)
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! cstr {
|
||||
($str:expr) => {{
|
||||
@ -718,8 +706,3 @@ macro_rules! cstr {
|
||||
macro_rules! raw_cstr {
|
||||
($str:expr) => {{ $crate::cstr!($str).as_ptr() }};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! path {
|
||||
($str:expr) => {{ $crate::FsPath::__from_utfcstr($crate::cstr!($str)) }};
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ pub(crate) fn fd_path_for_cxx(fd: RawFd, buf: &mut [u8]) -> isize {
|
||||
unsafe extern "C" fn canonical_path(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
|
||||
unsafe {
|
||||
match Utf8CStr::from_ptr(path) {
|
||||
Ok(p) => {
|
||||
Ok(path) => {
|
||||
let mut buf = cstr_buf::wrap_ptr(buf, bufsz);
|
||||
FsPath::from(p)
|
||||
.realpath(&mut buf)
|
||||
.map_or(-1, |_| buf.len() as isize)
|
||||
path.realpath(&mut buf)
|
||||
.log_cxx()
|
||||
.map_or(-1_isize, |_| buf.len() as isize)
|
||||
}
|
||||
Err(_) => -1,
|
||||
}
|
||||
@ -38,7 +38,7 @@ unsafe extern "C" fn canonical_path(path: *const c_char, buf: *mut u8, bufsz: us
|
||||
unsafe extern "C" fn mkdirs_for_cxx(path: *const c_char, mode: mode_t) -> i32 {
|
||||
unsafe {
|
||||
match Utf8CStr::from_ptr(path) {
|
||||
Ok(p) => FsPath::from(p).mkdirs(mode).map_or(-1, |_| 0),
|
||||
Ok(path) => path.mkdirs(mode).map_or(-1, |_| 0),
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
@ -48,7 +48,7 @@ unsafe extern "C" fn mkdirs_for_cxx(path: *const c_char, mode: mode_t) -> i32 {
|
||||
unsafe extern "C" fn rm_rf_for_cxx(path: *const c_char) -> bool {
|
||||
unsafe {
|
||||
match Utf8CStr::from_ptr(path) {
|
||||
Ok(p) => FsPath::from(p).remove_all().is_ok(),
|
||||
Ok(path) => path.remove_all().is_ok(),
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
@ -114,8 +114,6 @@ unsafe extern "C" fn cp_afc_for_cxx(src: *const c_char, dest: *const c_char) ->
|
||||
unsafe {
|
||||
if let Ok(src) = Utf8CStr::from_ptr(src) {
|
||||
if let Ok(dest) = Utf8CStr::from_ptr(dest) {
|
||||
let src = FsPath::from(src);
|
||||
let dest = FsPath::from(dest);
|
||||
return src.copy_to(dest).log_cxx().is_ok();
|
||||
}
|
||||
}
|
||||
@ -128,8 +126,6 @@ unsafe extern "C" fn mv_path_for_cxx(src: *const c_char, dest: *const c_char) ->
|
||||
unsafe {
|
||||
if let Ok(src) = Utf8CStr::from_ptr(src) {
|
||||
if let Ok(dest) = Utf8CStr::from_ptr(dest) {
|
||||
let src = FsPath::from(src);
|
||||
let dest = FsPath::from(dest);
|
||||
return src.move_to(dest).log_cxx().is_ok();
|
||||
}
|
||||
}
|
||||
@ -142,8 +138,6 @@ unsafe extern "C" fn link_path_for_cxx(src: *const c_char, dest: *const c_char)
|
||||
unsafe {
|
||||
if let Ok(src) = Utf8CStr::from_ptr(src) {
|
||||
if let Ok(dest) = Utf8CStr::from_ptr(dest) {
|
||||
let src = FsPath::from(src);
|
||||
let dest = FsPath::from(dest);
|
||||
return src.link_to(dest).log_cxx().is_ok();
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,6 @@ unsafe extern "C" fn clone_attr_for_cxx(src: *const c_char, dest: *const c_char)
|
||||
unsafe {
|
||||
if let Ok(src) = Utf8CStr::from_ptr(src) {
|
||||
if let Ok(dest) = Utf8CStr::from_ptr(dest) {
|
||||
let src = FsPath::from(src);
|
||||
let dest = FsPath::from(dest);
|
||||
return clone_attr(src, dest).log_cxx().is_ok();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::cxx_extern::readlinkat;
|
||||
use crate::{
|
||||
FileAttr, FsPathBuf, LibcReturn, OsError, OsResult, OsResultStatic, Utf8CStr, Utf8CStrBuf,
|
||||
cstr_buf, errno, fd_path, fd_set_attr,
|
||||
FileAttr, FsPath, FsPathBuf, LibcReturn, OsError, OsResult, OsResultStatic, Utf8CStr,
|
||||
Utf8CStrBuf, 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::fs::File;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
Directory, FsPath, FsPathBuf, FsPathFollow, LibcReturn, OsError, OsResult, OsResultStatic,
|
||||
Utf8CStr, Utf8CStrBuf, cstr_buf, errno, error,
|
||||
Directory, FsPathBuf, FsPathFollow, LibcReturn, OsError, OsResult, OsResultStatic, Utf8CStr,
|
||||
Utf8CStrBuf, cstr_buf, errno, error,
|
||||
};
|
||||
use bytemuck::{Pod, bytes_of, bytes_of_mut};
|
||||
use libc::{
|
||||
@ -13,6 +13,7 @@ use std::cmp::min;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write};
|
||||
use std::ops::Deref;
|
||||
use std::os::fd::{AsFd, BorrowedFd};
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
|
||||
@ -193,23 +194,27 @@ impl FileAttr {
|
||||
|
||||
const XATTR_NAME_SELINUX: &CStr = c"security.selinux";
|
||||
|
||||
impl FsPath {
|
||||
pub fn open(&self, flags: i32) -> OsResult<File> {
|
||||
pub trait FsPath: Deref<Target = Utf8CStr> {
|
||||
fn follow_link(&self) -> &FsPathFollow {
|
||||
unsafe { mem::transmute(self.deref()) }
|
||||
}
|
||||
|
||||
fn open(&self, flags: i32) -> OsResult<File> {
|
||||
Ok(File::from(open_fd!(self, flags)?))
|
||||
}
|
||||
|
||||
pub fn create(&self, flags: i32, mode: mode_t) -> OsResult<File> {
|
||||
fn create(&self, flags: i32, mode: mode_t) -> OsResult<File> {
|
||||
Ok(File::from(open_fd!(self, O_CREAT | flags, mode)?))
|
||||
}
|
||||
|
||||
pub fn exists(&self) -> bool {
|
||||
fn exists(&self) -> bool {
|
||||
unsafe {
|
||||
let mut st: stat = mem::zeroed();
|
||||
libc::lstat(self.as_ptr(), &mut st) == 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename_to<'a>(&'a self, name: &'a FsPath) -> OsResult<'a, ()> {
|
||||
fn rename_to<'a>(&'a self, name: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
unsafe {
|
||||
libc::rename(self.as_ptr(), name.as_ptr()).check_os_err(
|
||||
"rename",
|
||||
@ -219,11 +224,11 @@ impl FsPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&self) -> OsResult<()> {
|
||||
fn remove(&self) -> OsResult<()> {
|
||||
unsafe { libc::remove(self.as_ptr()).check_os_err("remove", Some(self), None) }
|
||||
}
|
||||
|
||||
pub fn remove_all(&self) -> OsResultStatic<()> {
|
||||
fn remove_all(&self) -> OsResultStatic<()> {
|
||||
let attr = self.get_attr()?;
|
||||
if attr.is_dir() {
|
||||
let mut dir = Directory::try_from(open_fd!(self, O_RDONLY | O_CLOEXEC)?)?;
|
||||
@ -233,7 +238,7 @@ impl FsPath {
|
||||
}
|
||||
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub fn read_link(&self, buf: &mut dyn Utf8CStrBuf) -> OsResult<()> {
|
||||
fn read_link(&self, buf: &mut dyn Utf8CStrBuf) -> OsResult<()> {
|
||||
buf.clear();
|
||||
unsafe {
|
||||
let r = libc::readlink(self.as_ptr(), buf.as_mut_ptr(), buf.capacity() - 1)
|
||||
@ -244,7 +249,7 @@ impl FsPath {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mkdir(&self, mode: mode_t) -> OsResult<()> {
|
||||
fn mkdir(&self, mode: mode_t) -> OsResult<()> {
|
||||
unsafe {
|
||||
if libc::mkdir(self.as_ptr(), mode) < 0 {
|
||||
if *errno() == EEXIST {
|
||||
@ -257,7 +262,7 @@ impl FsPath {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mkdirs(&self, mode: mode_t) -> OsResultStatic<()> {
|
||||
fn mkdirs(&self, mode: mode_t) -> OsResultStatic<()> {
|
||||
if self.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
@ -282,7 +287,7 @@ impl FsPath {
|
||||
}
|
||||
|
||||
// Inspired by https://android.googlesource.com/platform/bionic/+/master/libc/bionic/realpath.cpp
|
||||
pub fn realpath(&self, buf: &mut dyn Utf8CStrBuf) -> OsResult<()> {
|
||||
fn realpath(&self, buf: &mut dyn Utf8CStrBuf) -> OsResult<()> {
|
||||
let fd = open_fd!(self, O_PATH | O_CLOEXEC)?;
|
||||
let mut st1: libc::stat;
|
||||
let mut st2: libc::stat;
|
||||
@ -306,7 +311,7 @@ impl FsPath {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_attr(&self) -> OsResult<FileAttr> {
|
||||
fn get_attr(&self) -> OsResult<FileAttr> {
|
||||
let mut attr = FileAttr::new();
|
||||
unsafe {
|
||||
libc::lstat(self.as_ptr(), &mut attr.st).check_os_err("lstat", Some(self), None)?;
|
||||
@ -317,7 +322,7 @@ impl FsPath {
|
||||
Ok(attr)
|
||||
}
|
||||
|
||||
pub fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> {
|
||||
fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> {
|
||||
unsafe {
|
||||
if !attr.is_symlink() {
|
||||
libc::chmod(self.as_ptr(), (attr.st.st_mode & 0o777).as_()).check_os_err(
|
||||
@ -340,7 +345,7 @@ impl FsPath {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_secontext(&self, con: &mut dyn Utf8CStrBuf) -> OsResult<()> {
|
||||
fn get_secontext(&self, con: &mut dyn Utf8CStrBuf) -> OsResult<()> {
|
||||
unsafe {
|
||||
let sz = libc::lgetxattr(
|
||||
self.as_ptr(),
|
||||
@ -360,7 +365,7 @@ impl FsPath {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_secontext<'a>(&'a self, con: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
fn set_secontext<'a>(&'a self, con: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
unsafe {
|
||||
libc::lsetxattr(
|
||||
self.as_ptr(),
|
||||
@ -373,7 +378,7 @@ impl FsPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_to(&self, path: &FsPath) -> OsResultStatic<()> {
|
||||
fn copy_to(&self, path: &Utf8CStr) -> OsResultStatic<()> {
|
||||
let attr = self.get_attr()?;
|
||||
if attr.is_dir() {
|
||||
path.mkdir(0o777)?;
|
||||
@ -403,7 +408,7 @@ impl FsPath {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn move_to(&self, path: &FsPath) -> OsResultStatic<()> {
|
||||
fn move_to(&self, path: &Utf8CStr) -> OsResultStatic<()> {
|
||||
if path.exists() {
|
||||
let attr = path.get_attr()?;
|
||||
if attr.is_dir() {
|
||||
@ -418,7 +423,7 @@ impl FsPath {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn parent(&self, buf: &mut dyn Utf8CStrBuf) -> bool {
|
||||
fn parent(&self, buf: &mut dyn Utf8CStrBuf) -> bool {
|
||||
buf.clear();
|
||||
if let Some(parent) = Path::new(self.as_str()).parent() {
|
||||
let bytes = parent.as_os_str().as_bytes();
|
||||
@ -432,7 +437,7 @@ impl FsPath {
|
||||
}
|
||||
|
||||
// ln self path
|
||||
pub fn link_to(&self, path: &FsPath) -> OsResultStatic<()> {
|
||||
fn link_to(&self, path: &Utf8CStr) -> OsResultStatic<()> {
|
||||
let attr = self.get_attr()?;
|
||||
if attr.is_dir() {
|
||||
path.mkdir(0o777)?;
|
||||
@ -453,7 +458,7 @@ impl FsPath {
|
||||
}
|
||||
|
||||
// ln -s target self
|
||||
pub fn create_symlink_to<'a>(&'a self, target: &'a FsPath) -> OsResult<'a, ()> {
|
||||
fn create_symlink_to<'a>(&'a self, target: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
unsafe {
|
||||
libc::symlink(target.as_ptr(), self.as_ptr()).check_os_err(
|
||||
"symlink",
|
||||
@ -463,17 +468,21 @@ impl FsPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mkfifo(&self, mode: mode_t) -> OsResult<()> {
|
||||
fn mkfifo(&self, mode: mode_t) -> OsResult<()> {
|
||||
unsafe { libc::mkfifo(self.as_ptr(), mode).check_os_err("mkfifo", Some(self), None) }
|
||||
}
|
||||
}
|
||||
|
||||
impl FsPathFollow {
|
||||
pub fn exists(&self) -> bool {
|
||||
impl FsPath for FsPathFollow {
|
||||
fn follow_link(&self) -> &FsPathFollow {
|
||||
self
|
||||
}
|
||||
|
||||
fn exists(&self) -> bool {
|
||||
unsafe { libc::access(self.as_ptr(), F_OK) == 0 }
|
||||
}
|
||||
|
||||
pub fn get_attr(&self) -> OsResult<FileAttr> {
|
||||
fn get_attr(&self) -> OsResult<FileAttr> {
|
||||
let mut attr = FileAttr::new();
|
||||
unsafe {
|
||||
libc::stat(self.as_ptr(), &mut attr.st).check_os_err("stat", Some(self), None)?;
|
||||
@ -484,7 +493,7 @@ impl FsPathFollow {
|
||||
Ok(attr)
|
||||
}
|
||||
|
||||
pub fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> {
|
||||
fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> {
|
||||
unsafe {
|
||||
libc::chmod(self.as_ptr(), (attr.st.st_mode & 0o777).as_()).check_os_err(
|
||||
"chmod",
|
||||
@ -505,7 +514,7 @@ impl FsPathFollow {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_secontext(&self, con: &mut dyn Utf8CStrBuf) -> OsResult<()> {
|
||||
fn get_secontext(&self, con: &mut dyn Utf8CStrBuf) -> OsResult<()> {
|
||||
unsafe {
|
||||
let sz = libc::getxattr(
|
||||
self.as_ptr(),
|
||||
@ -525,7 +534,7 @@ impl FsPathFollow {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_secontext<'a>(&'a self, con: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
fn set_secontext<'a>(&'a self, con: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
unsafe {
|
||||
libc::setxattr(
|
||||
self.as_ptr(),
|
||||
@ -595,8 +604,8 @@ pub fn fd_set_secontext(fd: RawFd, con: &Utf8CStr) -> OsResult<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_attr<'a>(a: &'a FsPath, b: &'a FsPath) -> OsResult<'a, ()> {
|
||||
let attr = a.get_attr()?;
|
||||
pub fn clone_attr<'a>(a: &'a Utf8CStr, b: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
let attr = a.get_attr().map_err(|e| e.set_args(Some(a), None))?;
|
||||
b.set_attr(&attr).map_err(|e| e.set_args(Some(b), None))
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ pub use ffi::fork_dont_care;
|
||||
pub use files::*;
|
||||
pub use logging::*;
|
||||
pub use misc::*;
|
||||
pub use mount::*;
|
||||
pub use result::*;
|
||||
|
||||
mod cstr;
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::{FsPath, LibcReturn, OsResult, Utf8CStr};
|
||||
use crate::{LibcReturn, OsResult, Utf8CStr};
|
||||
use libc::c_ulong;
|
||||
use std::ops::Deref;
|
||||
use std::ptr;
|
||||
|
||||
impl FsPath {
|
||||
pub fn bind_mount_to<'a>(&'a self, path: &'a FsPath) -> OsResult<'a, ()> {
|
||||
pub trait FsPathMnt: Deref<Target = Utf8CStr> {
|
||||
fn bind_mount_to<'a>(&'a self, path: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
unsafe {
|
||||
libc::mount(
|
||||
self.as_ptr(),
|
||||
@ -16,7 +17,7 @@ impl FsPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remount_with_flags(&self, flags: c_ulong) -> OsResult<()> {
|
||||
fn remount_with_flags(&self, flags: c_ulong) -> OsResult<()> {
|
||||
unsafe {
|
||||
libc::mount(
|
||||
ptr::null(),
|
||||
@ -29,7 +30,7 @@ impl FsPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remount_with_data(&self, data: &Utf8CStr) -> OsResult<()> {
|
||||
fn remount_with_data(&self, data: &Utf8CStr) -> OsResult<()> {
|
||||
unsafe {
|
||||
libc::mount(
|
||||
ptr::null(),
|
||||
@ -42,7 +43,7 @@ impl FsPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_mount_to<'a>(&'a self, path: &'a FsPath) -> OsResult<'a, ()> {
|
||||
fn move_mount_to<'a>(&'a self, path: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||
unsafe {
|
||||
libc::mount(
|
||||
self.as_ptr(),
|
||||
@ -55,13 +56,13 @@ impl FsPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unmount(&self) -> OsResult<()> {
|
||||
fn unmount(&self) -> OsResult<()> {
|
||||
unsafe {
|
||||
libc::umount2(self.as_ptr(), libc::MNT_DETACH).check_os_err("unmount", Some(self), None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_mount_private(&self, recursive: bool) -> OsResult<()> {
|
||||
fn set_mount_private(&self, recursive: bool) -> OsResult<()> {
|
||||
let flag = if recursive { libc::MS_REC } else { 0 };
|
||||
unsafe {
|
||||
libc::mount(
|
||||
|
@ -29,10 +29,9 @@ fn ptr_to_str<'a>(ptr: *const c_char) -> Option<&'a str> {
|
||||
unsafe extern "C" fn xrealpath(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
|
||||
unsafe {
|
||||
match Utf8CStr::from_ptr(path) {
|
||||
Ok(p) => {
|
||||
Ok(path) => {
|
||||
let mut buf = cstr_buf::wrap_ptr(buf, bufsz);
|
||||
FsPath::from(p)
|
||||
.realpath(&mut buf)
|
||||
path.realpath(&mut buf)
|
||||
.log_cxx()
|
||||
.map_or(-1, |_| buf.len() as isize)
|
||||
}
|
||||
@ -45,10 +44,9 @@ unsafe extern "C" fn xrealpath(path: *const c_char, buf: *mut u8, bufsz: usize)
|
||||
unsafe extern "C" fn xreadlink(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
|
||||
unsafe {
|
||||
match Utf8CStr::from_ptr(path) {
|
||||
Ok(p) => {
|
||||
Ok(path) => {
|
||||
let mut buf = cstr_buf::wrap_ptr(buf, bufsz);
|
||||
FsPath::from(p)
|
||||
.read_link(&mut buf)
|
||||
path.read_link(&mut buf)
|
||||
.log_cxx()
|
||||
.map_or(-1, |_| buf.len() as isize)
|
||||
}
|
||||
@ -343,7 +341,7 @@ unsafe extern "C" fn xrename(oldname: *const c_char, newname: *const c_char) ->
|
||||
unsafe extern "C" fn xmkdir(path: *const c_char, mode: mode_t) -> i32 {
|
||||
unsafe {
|
||||
match Utf8CStr::from_ptr(path) {
|
||||
Ok(p) => FsPath::from(p).mkdir(mode).log_cxx().map_or(-1, |_| 0),
|
||||
Ok(path) => path.mkdir(mode).log_cxx().map_or(-1, |_| 0),
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
@ -353,7 +351,7 @@ unsafe extern "C" fn xmkdir(path: *const c_char, mode: mode_t) -> i32 {
|
||||
unsafe extern "C" fn xmkdirs(path: *const c_char, mode: mode_t) -> i32 {
|
||||
unsafe {
|
||||
match Utf8CStr::from_ptr(path) {
|
||||
Ok(p) => FsPath::from(p).mkdirs(mode).log_cxx().map_or(-1, |_| 0),
|
||||
Ok(path) => path.mkdirs(mode).log_cxx().map_or(-1, |_| 0),
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
@ -342,13 +342,12 @@ impl Cpio {
|
||||
eprintln!("Extracting entry [{}] to [{}]", path, out);
|
||||
|
||||
let out = Utf8CStr::from_string(out);
|
||||
let out = FsPath::from(out);
|
||||
|
||||
let mut buf = cstr_buf::default();
|
||||
|
||||
// Make sure its parent directories exist
|
||||
if out.parent(&mut buf) {
|
||||
FsPath::from(&buf).mkdirs(0o755)?;
|
||||
buf.mkdirs(0o755)?;
|
||||
}
|
||||
|
||||
let mode: mode_t = (entry.mode & 0o777).into();
|
||||
@ -362,7 +361,7 @@ impl Cpio {
|
||||
S_IFLNK => {
|
||||
buf.clear();
|
||||
buf.push_str(str::from_utf8(entry.data.as_slice())?);
|
||||
out.create_symlink_to(FsPath::from(&buf))?;
|
||||
out.create_symlink_to(&buf)?;
|
||||
}
|
||||
S_IFBLK | S_IFCHR => {
|
||||
let dev = makedev(entry.rdevmajor.try_into()?, entry.rdevminor.try_into()?);
|
||||
@ -399,7 +398,6 @@ impl Cpio {
|
||||
return Err(log_err!("path cannot end with / for add"));
|
||||
}
|
||||
let file = Utf8CStr::from_string(file);
|
||||
let file = FsPath::from(&file);
|
||||
let attr = file.get_attr()?;
|
||||
|
||||
let mut content = Vec::<u8>::new();
|
||||
@ -765,7 +763,7 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
|
||||
CpioCli::from_args(&["magiskboot", "cpio"], &cmds).on_early_exit(print_cpio_usage);
|
||||
|
||||
let file = Utf8CStr::from_string(&mut cli.file);
|
||||
let mut cpio = if FsPath::from(file).exists() {
|
||||
let mut cpio = if file.exists() {
|
||||
Cpio::load_from_file(file)?
|
||||
} else {
|
||||
Cpio::new()
|
||||
|
@ -11,8 +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, cstr_buf, error, info, libc,
|
||||
open_fd, path,
|
||||
AtomicArc, BufReadExt, FsPath, FsPathBuf, ResultExt, Utf8CStr, cstr, cstr_buf, error, info,
|
||||
libc, open_fd,
|
||||
};
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
@ -106,7 +106,7 @@ impl MagiskD {
|
||||
self.preserve_stub_apk();
|
||||
|
||||
// Check secure dir
|
||||
let secure_dir = path!(SECURE_DIR);
|
||||
let secure_dir = cstr!(SECURE_DIR);
|
||||
if !secure_dir.exists() {
|
||||
if self.sdk_int < 24 {
|
||||
secure_dir.mkdir(0o700).log_ok();
|
||||
@ -173,7 +173,7 @@ impl MagiskD {
|
||||
self.set_db_setting(DbEntryKey::BootloopCount, 0).log_ok();
|
||||
|
||||
// At this point it's safe to create the folder
|
||||
let secure_dir = path!(SECURE_DIR);
|
||||
let secure_dir = cstr!(SECURE_DIR);
|
||||
if !secure_dir.exists() {
|
||||
secure_dir.mkdir(0o700).log_ok();
|
||||
}
|
||||
@ -245,7 +245,7 @@ pub fn daemon_entry() {
|
||||
}
|
||||
|
||||
let mut sdk_int = -1;
|
||||
if let Ok(file) = path!("/system/build.prop").open(O_RDONLY | O_CLOEXEC) {
|
||||
if let Ok(file) = cstr!("/system/build.prop").open(O_RDONLY | O_CLOEXEC) {
|
||||
let mut file = BufReader::new(file);
|
||||
file.foreach_props(|key, val| {
|
||||
if key == "ro.build.version.sdk" {
|
||||
|
@ -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, cstr_buf,
|
||||
debug, info, libc, parse_mount_info, path, warn,
|
||||
FsPath, FsPathBuf, FsPathMnt, LibcReturn, LoggedResult, MountInfo, ResultExt, Utf8CStr, cstr,
|
||||
cstr_buf, debug, info, libc, parse_mount_info, warn,
|
||||
};
|
||||
|
||||
use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR};
|
||||
@ -44,7 +44,6 @@ pub fn setup_mounts() {
|
||||
let target = Utf8CStr::from_string(&mut target);
|
||||
let mut preinit_dir = resolve_preinit_dir(target);
|
||||
let preinit_dir = Utf8CStr::from_string(&mut preinit_dir);
|
||||
let preinit_dir = FsPath::from(preinit_dir);
|
||||
let r: LoggedResult<()> = try {
|
||||
preinit_dir.mkdir(0o700)?;
|
||||
mnt_path.mkdirs(0o755)?;
|
||||
@ -70,7 +69,7 @@ pub fn setup_mounts() {
|
||||
let module_mnt = FsPathBuf::default().join(magisk_tmp).join(MODULEMNT);
|
||||
let _: LoggedResult<()> = try {
|
||||
module_mnt.mkdir(0o755)?;
|
||||
path!(MODULEROOT).bind_mount_to(&module_mnt)?;
|
||||
cstr!(MODULEROOT).bind_mount_to(&module_mnt)?;
|
||||
module_mnt.remount_with_flags(libc::MS_RDONLY)?;
|
||||
};
|
||||
}
|
||||
@ -182,7 +181,7 @@ pub fn find_preinit_device() -> String {
|
||||
&& !tmp.is_empty()
|
||||
{
|
||||
let mut mirror_dir = FsPathBuf::default().join(&tmp).join(PREINITMIRR);
|
||||
let preinit_dir = FsPath::from(Utf8CStr::from_string(&mut preinit_dir));
|
||||
let preinit_dir = Utf8CStr::from_string(&mut preinit_dir);
|
||||
let _: LoggedResult<()> = try {
|
||||
preinit_dir.mkdirs(0o700)?;
|
||||
mirror_dir.mkdirs(0o755)?;
|
||||
|
@ -273,11 +273,10 @@ impl ManagerInfo {
|
||||
}
|
||||
|
||||
fn check_stub(&mut self, user: i32, pkg: &str) -> Status {
|
||||
let mut arr = cstr_buf::default();
|
||||
if find_apk_path(pkg, &mut arr).is_err() {
|
||||
let mut apk = cstr_buf::default();
|
||||
if find_apk_path(pkg, &mut apk).is_err() {
|
||||
return Status::NotInstalled;
|
||||
}
|
||||
let apk = FsPath::from(&arr);
|
||||
|
||||
let cert = match apk.open(O_RDONLY | O_CLOEXEC) {
|
||||
Ok(mut fd) => read_certificate(&mut fd, -1),
|
||||
@ -286,7 +285,7 @@ impl ManagerInfo {
|
||||
|
||||
if cert.is_empty() || (pkg == self.repackaged_pkg && cert != self.repackaged_cert) {
|
||||
error!("pkg: repackaged APK signature invalid: {}", apk);
|
||||
uninstall_pkg(apk);
|
||||
uninstall_pkg(&apk);
|
||||
return Status::CertMismatch;
|
||||
}
|
||||
|
||||
@ -298,11 +297,10 @@ impl ManagerInfo {
|
||||
}
|
||||
|
||||
fn check_orig(&mut self, user: i32) -> Status {
|
||||
let mut arr = cstr_buf::default();
|
||||
if find_apk_path(APP_PACKAGE_NAME, &mut arr).is_err() {
|
||||
let mut apk = cstr_buf::default();
|
||||
if find_apk_path(APP_PACKAGE_NAME, &mut apk).is_err() {
|
||||
return Status::NotInstalled;
|
||||
}
|
||||
let apk = FsPath::from(&arr);
|
||||
|
||||
let cert = match apk.open(O_RDONLY | O_CLOEXEC) {
|
||||
Ok(mut fd) => read_certificate(&mut fd, MAGISK_VER_CODE),
|
||||
|
@ -16,8 +16,8 @@ use crate::resetprop::proto::persistent_properties::{
|
||||
use base::const_format::concatcp;
|
||||
use base::libc::{O_CLOEXEC, O_RDONLY};
|
||||
use base::{
|
||||
Directory, FsPathBuf, LibcReturn, LoggedResult, MappedFile, SilentResultExt, Utf8CStr,
|
||||
WalkResult, clone_attr, cstr, debug, libc::mkstemp, path,
|
||||
Directory, FsPath, FsPathBuf, LibcReturn, LoggedResult, MappedFile, SilentResultExt, Utf8CStr,
|
||||
WalkResult, clone_attr, cstr, debug, libc::mkstemp,
|
||||
};
|
||||
|
||||
const PERSIST_PROP_DIR: &str = "/data/property";
|
||||
@ -64,7 +64,7 @@ impl PropExt for PersistentProperties {
|
||||
}
|
||||
|
||||
fn check_proto() -> bool {
|
||||
path!(PERSIST_PROP).exists()
|
||||
cstr!(PERSIST_PROP).exists()
|
||||
}
|
||||
|
||||
fn file_get_prop(name: &Utf8CStr) -> LoggedResult<String> {
|
||||
@ -121,8 +121,8 @@ fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> {
|
||||
debug!("resetprop: encode with protobuf [{}]", tmp);
|
||||
props.write_message(&mut Writer::new(BufWriter::new(f)))?;
|
||||
}
|
||||
clone_attr(path!(PERSIST_PROP), &tmp)?;
|
||||
tmp.rename_to(path!(PERSIST_PROP))?;
|
||||
clone_attr(cstr!(PERSIST_PROP), &tmp)?;
|
||||
tmp.rename_to(cstr!(PERSIST_PROP))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::ffi::{BootConfig, MagiskInit, backup_init};
|
||||
use base::{BytesExt, MappedFile, path};
|
||||
use base::{BytesExt, FsPath, MappedFile, cstr};
|
||||
|
||||
impl BootConfig {
|
||||
#[allow(unused_imports, unused_unsafe)]
|
||||
@ -37,11 +37,11 @@ impl BootConfig {
|
||||
|
||||
impl MagiskInit {
|
||||
pub(crate) fn check_two_stage(&self) -> bool {
|
||||
path!("/first_stage_ramdisk").exists() ||
|
||||
path!("/second_stage_resources").exists() ||
|
||||
path!("/system/bin/init").exists() ||
|
||||
cstr!("/first_stage_ramdisk").exists() ||
|
||||
cstr!("/second_stage_resources").exists() ||
|
||||
cstr!("/system/bin/init").exists() ||
|
||||
// Use the apex folder to determine whether 2SI (Android 10+)
|
||||
path!("/apex").exists() ||
|
||||
cstr!("/apex").exists() ||
|
||||
// If we still have no indication, parse the original init and see what's up
|
||||
MappedFile::open(backup_init())
|
||||
.map(|data| data.contains(b"selinux_setup"))
|
||||
|
@ -6,9 +6,9 @@ use crate::{
|
||||
logging::setup_klog,
|
||||
};
|
||||
use base::{
|
||||
FsPath, LibcReturn, LoggedResult, ResultExt, info,
|
||||
FsPath, FsPathMnt, LibcReturn, LoggedResult, ResultExt, cstr, info,
|
||||
libc::{basename, getpid, mount, umask},
|
||||
path, raw_cstr,
|
||||
raw_cstr,
|
||||
};
|
||||
use std::{
|
||||
ffi::{CStr, c_char},
|
||||
@ -41,7 +41,7 @@ impl MagiskInit {
|
||||
info!("First Stage Init");
|
||||
self.prepare_data();
|
||||
|
||||
if !path!("/sdcard").exists() && !path!("/first_stage_ramdisk/sdcard").exists() {
|
||||
if !cstr!("/sdcard").exists() && !cstr!("/first_stage_ramdisk/sdcard").exists() {
|
||||
self.hijack_init_with_switch_root();
|
||||
self.restore_ramdisk_init();
|
||||
} else {
|
||||
@ -54,9 +54,9 @@ impl MagiskInit {
|
||||
fn second_stage(&mut self) {
|
||||
info!("Second Stage Init");
|
||||
|
||||
path!("/init").unmount().ok();
|
||||
path!("/system/bin/init").unmount().ok(); // just in case
|
||||
path!("/data/init").remove().ok();
|
||||
cstr!("/init").unmount().ok();
|
||||
cstr!("/system/bin/init").unmount().ok(); // just in case
|
||||
cstr!("/data/init").remove().ok();
|
||||
|
||||
unsafe {
|
||||
// Make sure init dmesg logs won't get messed up
|
||||
@ -66,10 +66,10 @@ impl MagiskInit {
|
||||
// Some weird devices like meizu, uses 2SI but still have legacy rootfs
|
||||
if is_rootfs() {
|
||||
// We are still on rootfs, so make sure we will execute the init of the 2nd stage
|
||||
let init_path = path!("/init");
|
||||
let init_path = cstr!("/init");
|
||||
init_path.remove().ok();
|
||||
init_path
|
||||
.create_symlink_to(path!("/system/bin/init"))
|
||||
.create_symlink_to(cstr!("/system/bin/init"))
|
||||
.log_ok();
|
||||
self.patch_rw_root();
|
||||
} else {
|
||||
@ -98,29 +98,29 @@ impl MagiskInit {
|
||||
fn recovery(&self) {
|
||||
info!("Ramdisk is recovery, abort");
|
||||
self.restore_ramdisk_init();
|
||||
path!("/.backup").remove_all().ok();
|
||||
cstr!("/.backup").remove_all().ok();
|
||||
}
|
||||
|
||||
fn restore_ramdisk_init(&self) {
|
||||
path!("/init").remove().ok();
|
||||
cstr!("/init").remove().ok();
|
||||
|
||||
let orig_init = FsPath::from(backup_init());
|
||||
let orig_init = backup_init();
|
||||
|
||||
if orig_init.exists() {
|
||||
orig_init.rename_to(path!("/init")).log_ok();
|
||||
orig_init.rename_to(cstr!("/init")).log_ok();
|
||||
} else {
|
||||
// If the backup init is missing, this means that the boot ramdisk
|
||||
// was created from scratch, and the real init is in a separate CPIO,
|
||||
// which is guaranteed to be placed at /system/bin/init.
|
||||
path!("/init")
|
||||
.create_symlink_to(path!("/system/bin/init"))
|
||||
cstr!("/init")
|
||||
.create_symlink_to(cstr!("/system/bin/init"))
|
||||
.log_ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn start(&mut self) -> LoggedResult<()> {
|
||||
if !path!("/proc/cmdline").exists() {
|
||||
path!("/proc").mkdir(0o755)?;
|
||||
if !cstr!("/proc/cmdline").exists() {
|
||||
cstr!("/proc").mkdir(0o755)?;
|
||||
unsafe {
|
||||
mount(
|
||||
raw_cstr!("proc"),
|
||||
@ -133,8 +133,8 @@ impl MagiskInit {
|
||||
.check_io_err()?;
|
||||
self.mount_list.push("/proc".to_string());
|
||||
}
|
||||
if !path!("/sys/block").exists() {
|
||||
path!("/sys").mkdir(0o755)?;
|
||||
if !cstr!("/sys/block").exists() {
|
||||
cstr!("/sys").mkdir(0o755)?;
|
||||
unsafe {
|
||||
mount(
|
||||
raw_cstr!("sysfs"),
|
||||
@ -159,7 +159,7 @@ impl MagiskInit {
|
||||
self.legacy_system_as_root();
|
||||
} else if self.config.force_normal_boot {
|
||||
self.first_stage();
|
||||
} else if path!("/sbin/recovery").exists() || path!("/system/bin/recovery").exists() {
|
||||
} else if cstr!("/sbin/recovery").exists() || cstr!("/system/bin/recovery").exists() {
|
||||
self.recovery();
|
||||
} else if self.check_two_stage() {
|
||||
self.first_stage();
|
||||
|
@ -3,7 +3,6 @@
|
||||
#![feature(try_blocks)]
|
||||
#![allow(clippy::missing_safety_doc)]
|
||||
|
||||
use base::FsPath;
|
||||
use logging::setup_klog;
|
||||
// Has to be pub so all symbols in that crate is included
|
||||
pub use magiskpolicy;
|
||||
@ -106,18 +105,3 @@ pub mod ffi {
|
||||
unsafe fn patch_fissiond(self: &mut MagiskInit, tmp_path: *const c_char);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn preload_lib() -> &'static FsPath {
|
||||
FsPath::from(ffi::preload_lib())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn preload_policy() -> &'static FsPath {
|
||||
FsPath::from(ffi::preload_policy())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn preload_ack() -> &'static FsPath {
|
||||
FsPath::from(ffi::preload_ack())
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
use base::{
|
||||
LOGGER, LogLevel, Logger, Utf8CStr, cstr,
|
||||
FsPath, LOGGER, LogLevel, Logger, Utf8CStr, cstr,
|
||||
libc::{
|
||||
O_CLOEXEC, O_RDWR, O_WRONLY, S_IFCHR, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO, SYS_dup3,
|
||||
makedev, mknod, syscall,
|
||||
},
|
||||
open_fd, path, raw_cstr,
|
||||
open_fd, raw_cstr,
|
||||
};
|
||||
use std::{
|
||||
fs::File,
|
||||
@ -23,7 +23,7 @@ pub fn setup_klog() {
|
||||
if fd.is_err() {
|
||||
mknod(raw_cstr!("/null"), S_IFCHR | 0o666, makedev(1, 3));
|
||||
fd = open_fd!(cstr!("/null"), O_RDWR | O_CLOEXEC);
|
||||
path!("/null").remove().ok();
|
||||
cstr!("/null").remove().ok();
|
||||
}
|
||||
if let Ok(ref fd) = fd {
|
||||
syscall(SYS_dup3, fd, STDIN_FILENO, O_CLOEXEC);
|
||||
@ -36,7 +36,7 @@ pub fn setup_klog() {
|
||||
if fd.is_err() {
|
||||
mknod(raw_cstr!("/kmsg"), S_IFCHR | 0o666, makedev(1, 11));
|
||||
fd = open_fd!(cstr!("/kmsg"), O_WRONLY | O_CLOEXEC);
|
||||
path!("/kmsg").remove().ok();
|
||||
cstr!("/kmsg").remove().ok();
|
||||
}
|
||||
KMSG = fd.map(|fd| fd.into_raw_fd()).unwrap_or(-1);
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::ffi::MagiskInit;
|
||||
use base::libc::{TMPFS_MAGIC, statfs};
|
||||
use base::{
|
||||
Directory, FsPath, FsPathBuf, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, debug, libc,
|
||||
Directory, FsPath, FsPathBuf, FsPathMnt, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr,
|
||||
debug, libc,
|
||||
libc::{chdir, chroot, execve, exit, mount},
|
||||
parse_mount_info, path, raw_cstr,
|
||||
parse_mount_info, raw_cstr,
|
||||
};
|
||||
use cxx::CxxString;
|
||||
use std::ffi::c_long;
|
||||
@ -36,7 +37,7 @@ pub(crate) fn switch_root(path: &Utf8CStr) {
|
||||
}
|
||||
|
||||
let mut target = info.target.clone();
|
||||
let target = FsPath::from(Utf8CStr::from_string(&mut target));
|
||||
let target = Utf8CStr::from_string(&mut target);
|
||||
let new_path = FsPathBuf::default()
|
||||
.join(path)
|
||||
.join(info.target.trim_start_matches('/'));
|
||||
@ -46,7 +47,7 @@ pub(crate) fn switch_root(path: &Utf8CStr) {
|
||||
}
|
||||
unsafe {
|
||||
chdir(path.as_ptr()).check_io_err()?;
|
||||
FsPath::from(path).move_mount_to(path!("/"))?;
|
||||
path.move_mount_to(cstr!("/"))?;
|
||||
chroot(raw_cstr!("."));
|
||||
}
|
||||
|
||||
@ -79,7 +80,7 @@ pub(crate) fn is_rootfs() -> bool {
|
||||
impl MagiskInit {
|
||||
pub(crate) fn prepare_data(&self) {
|
||||
debug!("Setup data tmp");
|
||||
path!("/data").mkdir(0o755).log_ok();
|
||||
cstr!("/data").mkdir(0o755).log_ok();
|
||||
unsafe {
|
||||
mount(
|
||||
raw_cstr!("magisk"),
|
||||
@ -92,16 +93,16 @@ impl MagiskInit {
|
||||
.check_io_err()
|
||||
.log_ok();
|
||||
|
||||
path!("/init").copy_to(path!("/data/magiskinit")).log_ok();
|
||||
path!("/.backup").copy_to(path!("/data/.backup")).log_ok();
|
||||
path!("/overlay.d")
|
||||
.copy_to(path!("/data/overlay.d"))
|
||||
cstr!("/init").copy_to(cstr!("/data/magiskinit")).log_ok();
|
||||
cstr!("/.backup").copy_to(cstr!("/data/.backup")).log_ok();
|
||||
cstr!("/overlay.d")
|
||||
.copy_to(cstr!("/data/overlay.d"))
|
||||
.log_ok();
|
||||
}
|
||||
|
||||
pub(crate) fn exec_init(&mut self) {
|
||||
for path in self.mount_list.iter_mut().rev() {
|
||||
let path = FsPath::from(Utf8CStr::from_string(path));
|
||||
let path = Utf8CStr::from_string(path);
|
||||
if path.unmount().log().is_ok() {
|
||||
debug!("Unmount [{}]", path);
|
||||
}
|
||||
|
@ -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, FsPathMnt, LoggedResult, ResultExt, Utf8CStr,
|
||||
Utf8CString, clone_attr, cstr, cstr_buf, debug,
|
||||
};
|
||||
use std::io::BufReader;
|
||||
use std::{
|
||||
@ -47,7 +47,7 @@ pub struct OverlayAttr(Utf8CString, Utf8CString);
|
||||
|
||||
impl MagiskInit {
|
||||
pub(crate) fn parse_config_file(&mut self) {
|
||||
if let Ok(fd) = path!("/data/.backup/.magisk").open(O_RDONLY) {
|
||||
if let Ok(fd) = cstr!("/data/.backup/.magisk").open(O_RDONLY) {
|
||||
let mut reader = BufReader::new(fd);
|
||||
reader.foreach_props(|key, val| {
|
||||
if key == "PREINITDEVICE" {
|
||||
@ -102,7 +102,7 @@ impl MagiskInit {
|
||||
let mut mount_list = String::new();
|
||||
self.mount_impl(cstr!(ROOTOVL), dest, &mut mount_list)
|
||||
.log_ok();
|
||||
if let Ok(mut fd) = path!(ROOTMNT).create(O_CREAT | O_WRONLY, 0) {
|
||||
if let Ok(mut fd) = cstr!(ROOTMNT).create(O_CREAT | O_WRONLY, 0) {
|
||||
fd.write(mount_list.as_bytes()).log_ok();
|
||||
}
|
||||
}
|
||||
@ -110,7 +110,7 @@ impl MagiskInit {
|
||||
pub(crate) fn restore_overlay_contexts(&self) {
|
||||
self.overlay_con.iter().for_each(|attr| {
|
||||
let OverlayAttr(path, con) = attr;
|
||||
FsPath::from(path).set_secontext(con).log_ok();
|
||||
path.set_secontext(con).log_ok();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
use crate::consts::{PREINITMIRR, SELINUXMOCK};
|
||||
use crate::ffi::{MagiskInit, split_plat_cil};
|
||||
use crate::{preload_ack, preload_lib, preload_policy};
|
||||
use crate::ffi::{MagiskInit, preload_ack, preload_lib, preload_policy, split_plat_cil};
|
||||
use base::const_format::concatcp;
|
||||
use base::{
|
||||
BytesExt, FsPath, LibcReturn, LoggedResult, MappedFile, ResultExt, cstr, debug, error, info,
|
||||
libc, path, raw_cstr,
|
||||
BytesExt, FsPath, FsPathMnt, LibcReturn, LoggedResult, MappedFile, ResultExt, Utf8CStr, cstr,
|
||||
debug, error, info, libc, raw_cstr,
|
||||
};
|
||||
use magiskpolicy::ffi::SePolicy;
|
||||
use std::io::{Read, Write};
|
||||
@ -12,17 +11,17 @@ use std::ptr;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
||||
const POLICY_VERSION: &FsPath = path!("/selinux_version");
|
||||
const POLICY_VERSION: &Utf8CStr = cstr!("/selinux_version");
|
||||
|
||||
const MOCK_VERSION: &FsPath = path!(concatcp!(SELINUXMOCK, "/version"));
|
||||
const MOCK_LOAD: &FsPath = path!(concatcp!(SELINUXMOCK, "/load"));
|
||||
const MOCK_ENFORCE: &FsPath = path!(concatcp!(SELINUXMOCK, "/enforce"));
|
||||
const MOCK_REQPROT: &FsPath = path!(concatcp!(SELINUXMOCK, "/checkreqprot"));
|
||||
const MOCK_VERSION: &Utf8CStr = cstr!(concatcp!(SELINUXMOCK, "/version"));
|
||||
const MOCK_LOAD: &Utf8CStr = cstr!(concatcp!(SELINUXMOCK, "/load"));
|
||||
const MOCK_ENFORCE: &Utf8CStr = cstr!(concatcp!(SELINUXMOCK, "/enforce"));
|
||||
const MOCK_REQPROT: &Utf8CStr = cstr!(concatcp!(SELINUXMOCK, "/checkreqprot"));
|
||||
|
||||
const SELINUX_MNT: &str = "/sys/fs/selinux";
|
||||
const SELINUX_ENFORCE: &FsPath = path!(concatcp!(SELINUX_MNT, "/enforce"));
|
||||
const SELINUX_LOAD: &FsPath = path!(concatcp!(SELINUX_MNT, "/load"));
|
||||
const SELINUX_REQPROT: &FsPath = path!(concatcp!(SELINUX_MNT, "/checkreqprot"));
|
||||
const SELINUX_ENFORCE: &Utf8CStr = cstr!(concatcp!(SELINUX_MNT, "/enforce"));
|
||||
const SELINUX_LOAD: &Utf8CStr = cstr!(concatcp!(SELINUX_MNT, "/load"));
|
||||
const SELINUX_REQPROT: &Utf8CStr = cstr!(concatcp!(SELINUX_MNT, "/checkreqprot"));
|
||||
|
||||
enum SePatchStrategy {
|
||||
// 2SI, Android 10+
|
||||
@ -49,13 +48,13 @@ enum SePatchStrategy {
|
||||
// node, and because both has been replaced with FIFO files, init will block until we
|
||||
// handle it, effectively hijacking its control flow until the patched sepolicy is loaded.
|
||||
|
||||
fn mock_fifo(target: &FsPath, mock: &FsPath) -> LoggedResult<()> {
|
||||
fn mock_fifo(target: &Utf8CStr, mock: &Utf8CStr) -> LoggedResult<()> {
|
||||
debug!("Hijack [{}]", target);
|
||||
mock.mkfifo(0o666)?;
|
||||
mock.bind_mount_to(target).log()
|
||||
}
|
||||
|
||||
fn mock_file(target: &FsPath, mock: &FsPath) -> LoggedResult<()> {
|
||||
fn mock_file(target: &Utf8CStr, mock: &Utf8CStr) -> LoggedResult<()> {
|
||||
debug!("Hijack [{}]", target);
|
||||
drop(mock.create(libc::O_RDONLY, 0o666)?);
|
||||
mock.bind_mount_to(target).log()
|
||||
@ -68,7 +67,7 @@ impl MagiskInit {
|
||||
|
||||
fn cleanup_and_load(&self, rules: &str) {
|
||||
// Cleanup the hijacks
|
||||
path!("/init").unmount().ok();
|
||||
cstr!("/init").unmount().ok();
|
||||
SELINUX_LOAD.unmount().log_ok();
|
||||
SELINUX_ENFORCE.unmount().ok();
|
||||
SELINUX_REQPROT.unmount().ok();
|
||||
@ -79,7 +78,7 @@ impl MagiskInit {
|
||||
sepol.to_file(SELINUX_LOAD);
|
||||
|
||||
// For some reason, restorecon on /init won't work in some cases
|
||||
path!("/init")
|
||||
cstr!("/init")
|
||||
.follow_link()
|
||||
.set_secontext(cstr!("u:object_r:init_exec:s0"))
|
||||
.ok();
|
||||
@ -89,10 +88,10 @@ impl MagiskInit {
|
||||
}
|
||||
|
||||
fn handle_sepolicy_impl(&mut self) -> LoggedResult<()> {
|
||||
path!(SELINUXMOCK).mkdir(0o711)?;
|
||||
cstr!(SELINUXMOCK).mkdir(0o711)?;
|
||||
|
||||
let mut rules = String::new();
|
||||
let rule_file = path!(concatcp!("/data/", PREINITMIRR, "/sepolicy.rule"));
|
||||
let rule_file = cstr!(concatcp!("/data/", PREINITMIRR, "/sepolicy.rule"));
|
||||
if rule_file.exists() {
|
||||
debug!("Loading custom sepolicy patch: [{}]", rule_file);
|
||||
rule_file.open(libc::O_RDONLY)?.read_to_string(&mut rules)?;
|
||||
@ -102,7 +101,7 @@ impl MagiskInit {
|
||||
|
||||
let strat: SePatchStrategy;
|
||||
|
||||
if path!("/system/bin/init").exists() {
|
||||
if cstr!("/system/bin/init").exists() {
|
||||
strat = SePatchStrategy::LdPreload;
|
||||
} else {
|
||||
let init = MappedFile::open(cstr!("/init"))?;
|
||||
@ -124,7 +123,7 @@ impl MagiskInit {
|
||||
SePatchStrategy::LdPreload => {
|
||||
info!("SePatchStrategy: LD_PRELOAD");
|
||||
|
||||
path!("init-ld").copy_to(preload_lib())?;
|
||||
cstr!("init-ld").copy_to(preload_lib())?;
|
||||
unsafe {
|
||||
libc::setenv(raw_cstr!("LD_PRELOAD"), preload_lib().as_ptr(), 1);
|
||||
}
|
||||
@ -137,7 +136,7 @@ impl MagiskInit {
|
||||
// selinuxfs was not already mounted, mount it ourselves
|
||||
|
||||
// Remount procfs with proper options
|
||||
path!("/proc").remount_with_data(cstr!("hidepid=2,gid=3009"))?;
|
||||
cstr!("/proc").remount_with_data(cstr!("hidepid=2,gid=3009"))?;
|
||||
|
||||
// Preserve sysfs and procfs
|
||||
self.mount_list.retain(|s| s != "/proc" && s != "/sys");
|
||||
|
@ -1,8 +1,7 @@
|
||||
use crate::ffi::MagiskInit;
|
||||
use base::{
|
||||
LoggedResult, MappedFile, MutBytesExt, ResultExt, cstr, debug, error,
|
||||
FsPath, FsPathMnt, LoggedResult, MappedFile, MutBytesExt, ResultExt, cstr, debug, error,
|
||||
libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_WRONLY},
|
||||
path,
|
||||
};
|
||||
use std::io::Write;
|
||||
|
||||
@ -29,8 +28,8 @@ pub(crate) fn hexpatch_init_for_second_stage(writable: bool) {
|
||||
|
||||
if !writable {
|
||||
// If we cannot directly modify /init, we need to bind mount a replacement on top of it
|
||||
let src = path!("/init");
|
||||
let dest = path!("/data/init");
|
||||
let src = cstr!("/init");
|
||||
let dest = cstr!("/data/init");
|
||||
let _: LoggedResult<()> = try {
|
||||
{
|
||||
let mut fd = dest.create(O_CREAT | O_WRONLY, 0)?;
|
||||
@ -70,32 +69,32 @@ impl MagiskInit {
|
||||
// /sdcard exists and fallback to using hexpatch.
|
||||
|
||||
if self.config.force_normal_boot {
|
||||
path!("/first_stage_ramdisk/storage/self")
|
||||
cstr!("/first_stage_ramdisk/storage/self")
|
||||
.mkdirs(0o755)
|
||||
.log_ok();
|
||||
path!("/first_stage_ramdisk/storage/self/primary")
|
||||
.create_symlink_to(path!("/system/system/bin/init"))
|
||||
cstr!("/first_stage_ramdisk/storage/self/primary")
|
||||
.create_symlink_to(cstr!("/system/system/bin/init"))
|
||||
.log_ok();
|
||||
debug!("Symlink /first_stage_ramdisk/storage/self/primary -> /system/system/bin/init");
|
||||
path!("/first_stage_ramdisk/sdcard")
|
||||
cstr!("/first_stage_ramdisk/sdcard")
|
||||
.create(O_RDONLY | O_CREAT | O_CLOEXEC, 0)
|
||||
.log_ok();
|
||||
} else {
|
||||
path!("/storage/self").mkdirs(0o755).log_ok();
|
||||
path!("/storage/self/primary")
|
||||
.create_symlink_to(path!("/system/system/bin/init"))
|
||||
cstr!("/storage/self").mkdirs(0o755).log_ok();
|
||||
cstr!("/storage/self/primary")
|
||||
.create_symlink_to(cstr!("/system/system/bin/init"))
|
||||
.log_ok();
|
||||
debug!("Symlink /storage/self/primary -> /system/system/bin/init");
|
||||
}
|
||||
path!("/init").rename_to(path!("/sdcard")).log_ok();
|
||||
cstr!("/init").rename_to(cstr!("/sdcard")).log_ok();
|
||||
|
||||
// First try to mount magiskinit from rootfs to workaround Samsung RKP
|
||||
if path!("/sdcard").bind_mount_to(path!("/sdcard")).is_ok() {
|
||||
if cstr!("/sdcard").bind_mount_to(cstr!("/sdcard")).is_ok() {
|
||||
debug!("Bind mount /sdcard -> /sdcard");
|
||||
} else {
|
||||
// Binding mounting from rootfs is not supported before Linux 3.12
|
||||
path!("/data/magiskinit")
|
||||
.bind_mount_to(path!("/sdcard"))
|
||||
cstr!("/data/magiskinit")
|
||||
.bind_mount_to(cstr!("/sdcard"))
|
||||
.log_ok();
|
||||
debug!("Bind mount /data/magiskinit -> /sdcard");
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ impl SePolicy {
|
||||
|
||||
pub fn load_rule_file(&mut self, filename: &Utf8CStr) {
|
||||
let result: LoggedResult<()> = try {
|
||||
let file = FsPath::from(filename).open(O_RDONLY | O_CLOEXEC)?;
|
||||
let file = filename.open(O_RDONLY | O_CLOEXEC)?;
|
||||
let mut reader = BufReader::new(file);
|
||||
self.load_rules_from_reader(&mut reader);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user