mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 07:57:39 +00:00
Standardize logging and error handling
- Introduce new types: LoggedResult and LoggedError - Introduce new extension methods to log and add additional msgs - Never exit when logging error messages in Rust (all errors should be handled by using Result and Rust's error propagation) - Remove all usages of anyhow as it doesn't fit Magisk's use cases
This commit is contained in:
parent
dbc2236dd2
commit
4ee4cbada6
9
native/src/Cargo.lock
generated
9
native/src/Cargo.lock
generated
@ -20,12 +20,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "anyhow"
|
|
||||||
version = "1.0.71"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "argh"
|
name = "argh"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@ -75,7 +69,6 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|||||||
name = "base"
|
name = "base"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cxx",
|
"cxx",
|
||||||
"cxx-gen",
|
"cxx-gen",
|
||||||
@ -222,7 +215,6 @@ dependencies = [
|
|||||||
name = "magiskboot"
|
name = "magiskboot"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"argh",
|
"argh",
|
||||||
"base",
|
"base",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
@ -247,7 +239,6 @@ dependencies = [
|
|||||||
name = "magiskpolicy"
|
name = "magiskpolicy"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"base",
|
"base",
|
||||||
"cxx",
|
"cxx",
|
||||||
"cxx-gen",
|
"cxx-gen",
|
||||||
|
@ -8,7 +8,6 @@ cxx = { path = "external/cxx-rs" }
|
|||||||
cxx-gen = { path = "external/cxx-rs/gen/lib" }
|
cxx-gen = { path = "external/cxx-rs/gen/lib" }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
anyhow = "1.0"
|
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
num-derive = "0.3"
|
num-derive = "0.3"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
@ -14,4 +14,3 @@ cxx = { workspace = true }
|
|||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
cfg-if = { workspace = true }
|
cfg-if = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
|
@ -1,9 +1,9 @@
|
|||||||
// Functions listed here are just to export to C++
|
// Functions listed here are just to export to C++
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::os::fd::{BorrowedFd, OwnedFd, RawFd};
|
use std::os::fd::{BorrowedFd, OwnedFd, RawFd};
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use cxx::private::c_char;
|
use cxx::private::c_char;
|
||||||
use libc::mode_t;
|
use libc::mode_t;
|
||||||
|
|
||||||
@ -14,8 +14,7 @@ use crate::{
|
|||||||
|
|
||||||
pub(crate) fn fd_path_for_cxx(fd: RawFd, buf: &mut [u8]) -> isize {
|
pub(crate) fn fd_path_for_cxx(fd: RawFd, buf: &mut [u8]) -> isize {
|
||||||
fd_path(fd, buf)
|
fd_path(fd, buf)
|
||||||
.context("fd_path failed")
|
.log_cxx_with_msg(|w| w.write_str("fd_path failed"))
|
||||||
.log()
|
|
||||||
.map_or(-1_isize, |v| v as isize)
|
.map_or(-1_isize, |v| v as isize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ unsafe extern "C" fn frm_rf(fd: OwnedFd) -> bool {
|
|||||||
pub(crate) fn map_file_for_cxx(path: &[u8], rw: bool) -> &'static mut [u8] {
|
pub(crate) fn map_file_for_cxx(path: &[u8], rw: bool) -> &'static mut [u8] {
|
||||||
unsafe {
|
unsafe {
|
||||||
map_file(Utf8CStr::from_bytes_unchecked(path), rw)
|
map_file(Utf8CStr::from_bytes_unchecked(path), rw)
|
||||||
.log()
|
.log_cxx()
|
||||||
.unwrap_or(&mut [])
|
.unwrap_or(&mut [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,7 +61,7 @@ pub(crate) fn map_file_for_cxx(path: &[u8], rw: bool) -> &'static mut [u8] {
|
|||||||
pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8] {
|
pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8] {
|
||||||
unsafe {
|
unsafe {
|
||||||
map_fd(BorrowedFd::borrow_raw(fd), sz, rw)
|
map_fd(BorrowedFd::borrow_raw(fd), sz, rw)
|
||||||
.log()
|
.log_cxx()
|
||||||
.unwrap_or(&mut [])
|
.unwrap_or(&mut [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ mod xwrap;
|
|||||||
pub mod ffi {
|
pub mod ffi {
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum LogLevel {
|
pub enum LogLevel {
|
||||||
|
ErrorCxx,
|
||||||
Error,
|
Error,
|
||||||
Warn,
|
Warn,
|
||||||
Info,
|
Info,
|
||||||
@ -32,6 +33,7 @@ pub mod ffi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
|
#[rust_name = "log_from_cxx"]
|
||||||
fn log_with_rs(level: LogLevel, msg: &[u8]);
|
fn log_with_rs(level: LogLevel, msg: &[u8]);
|
||||||
fn exit_on_error(b: bool);
|
fn exit_on_error(b: bool);
|
||||||
fn set_log_level_state(level: LogLevel, enabled: bool);
|
fn set_log_level_state(level: LogLevel, enabled: bool);
|
||||||
|
@ -33,7 +33,7 @@ extern "C" int magisk_log_print(int prio, const char *tag, const char *fmt, ...)
|
|||||||
level = LogLevel::Warn;
|
level = LogLevel::Warn;
|
||||||
break;
|
break;
|
||||||
case ANDROID_LOG_ERROR:
|
case ANDROID_LOG_ERROR:
|
||||||
level = LogLevel::Error;
|
level = LogLevel::ErrorCxx;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@ -70,9 +70,9 @@ void LOGD(const char *fmt, ...) {}
|
|||||||
#endif
|
#endif
|
||||||
void LOGI(const char *fmt, ...) { LOG_BODY(Info) }
|
void LOGI(const char *fmt, ...) { LOG_BODY(Info) }
|
||||||
void LOGW(const char *fmt, ...) { LOG_BODY(Warn) }
|
void LOGW(const char *fmt, ...) { LOG_BODY(Warn) }
|
||||||
void LOGE(const char *fmt, ...) { LOG_BODY(Error) }
|
void LOGE(const char *fmt, ...) { LOG_BODY(ErrorCxx) }
|
||||||
|
|
||||||
// Export raw symbol to fortify compat
|
// Export raw symbol to fortify compat
|
||||||
extern "C" void __vloge(const char* fmt, va_list ap) {
|
extern "C" void __vloge(const char* fmt, va_list ap) {
|
||||||
fmt_and_log_with_rs(LogLevel::Error, fmt, ap);
|
fmt_and_log_with_rs(LogLevel::ErrorCxx, fmt, ap);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,23 @@
|
|||||||
use std::fmt::{Arguments, Display};
|
use std::fmt;
|
||||||
|
use std::fmt::{Arguments, Display, Write as fWrite};
|
||||||
use std::io::{stderr, stdout, Write};
|
use std::io::{stderr, stdout, Write};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use crate::ffi::LogLevel;
|
use crate::ffi::LogLevel;
|
||||||
use crate::fmt_to_buf;
|
use crate::BufFormatter;
|
||||||
|
|
||||||
|
// Error handling and logging throughout the Rust codebase in Magisk:
|
||||||
|
//
|
||||||
|
// All errors should be logged and consumed as soon as possible and converted into LoggedError.
|
||||||
|
// Implement `From<ErrorType> for LoggedError` for non-standard error types so that we can
|
||||||
|
// directly use the `?` operator to propagate LoggedResult.
|
||||||
|
//
|
||||||
|
// To log an error with more information, use `ResultExt::log_with_msg()`.
|
||||||
|
//
|
||||||
|
// The "cxx" method variants in `ResultExt` are only used for C++ interop and
|
||||||
|
// should not be used directly in any Rust code.
|
||||||
|
//
|
||||||
|
// For general logging, use the <level>!(...) macros.
|
||||||
|
|
||||||
// Ugly hack to avoid using enum
|
// Ugly hack to avoid using enum
|
||||||
#[allow(non_snake_case, non_upper_case_globals)]
|
#[allow(non_snake_case, non_upper_case_globals)]
|
||||||
@ -41,7 +55,7 @@ pub fn exit_on_error(b: bool) {
|
|||||||
impl LogLevel {
|
impl LogLevel {
|
||||||
fn as_disable_flag(&self) -> u32 {
|
fn as_disable_flag(&self) -> u32 {
|
||||||
match *self {
|
match *self {
|
||||||
LogLevel::Error => LogFlag::DisableError,
|
LogLevel::Error | LogLevel::ErrorCxx => LogFlag::DisableError,
|
||||||
LogLevel::Warn => LogFlag::DisableWarn,
|
LogLevel::Warn => LogFlag::DisableWarn,
|
||||||
LogLevel::Info => LogFlag::DisableInfo,
|
LogLevel::Info => LogFlag::DisableInfo,
|
||||||
LogLevel::Debug => LogFlag::DisableDebug,
|
LogLevel::Debug => LogFlag::DisableDebug,
|
||||||
@ -61,28 +75,32 @@ pub fn set_log_level_state(level: LogLevel, enabled: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_with_rs(level: LogLevel, msg: &[u8]) {
|
fn do_log<F: FnOnce(fn(level: LogLevel, msg: &[u8]))>(level: LogLevel, f: F) {
|
||||||
let logger = unsafe { LOGGER };
|
let logger = unsafe { LOGGER };
|
||||||
if (logger.flags & level.as_disable_flag()) != 0 {
|
if (logger.flags & level.as_disable_flag()) != 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(logger.write)(level, msg);
|
f(logger.write);
|
||||||
if level == LogLevel::Error && (logger.flags & LogFlag::ExitOnError) != 0 {
|
if level == LogLevel::ErrorCxx && (logger.flags & LogFlag::ExitOnError) != 0 {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_impl(level: LogLevel, args: Arguments) {
|
pub fn log_from_cxx(level: LogLevel, msg: &[u8]) {
|
||||||
let logger = unsafe { LOGGER };
|
do_log(level, |write| write(level, msg));
|
||||||
if (logger.flags & level.as_disable_flag()) != 0 {
|
}
|
||||||
return;
|
|
||||||
}
|
pub fn log_with_formatter<F: FnOnce(&mut BufFormatter) -> fmt::Result>(level: LogLevel, f: F) {
|
||||||
let mut buf: [u8; 4096] = [0; 4096];
|
do_log(level, |write| {
|
||||||
let len = fmt_to_buf(&mut buf, args);
|
let mut buf = [0_u8; 4096];
|
||||||
(logger.write)(level, &buf[..len]);
|
let mut w = BufFormatter::new(&mut buf);
|
||||||
if level == LogLevel::Error && (logger.flags & LogFlag::ExitOnError) != 0 {
|
let len = if f(&mut w).is_ok() { w.used } else { 0 };
|
||||||
exit(1);
|
write(level, &buf[..len]);
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log_with_args(level: LogLevel, args: Arguments) {
|
||||||
|
log_with_formatter(level, |w| w.write_fmt(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cmdline_logging() {
|
pub fn cmdline_logging() {
|
||||||
@ -103,44 +121,33 @@ pub fn cmdline_logging() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! perror {
|
|
||||||
($fmt:expr) => {
|
|
||||||
$crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!(
|
|
||||||
concat!($fmt, " failed with {}: {}"),
|
|
||||||
$crate::errno(),
|
|
||||||
$crate::error_str()
|
|
||||||
))
|
|
||||||
};
|
|
||||||
($fmt:expr, $($args:tt)*) => {
|
|
||||||
$crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!(
|
|
||||||
concat!($fmt, " failed with {}: {}"),
|
|
||||||
$($args)*,
|
|
||||||
$crate::errno(),
|
|
||||||
$crate::error_str()
|
|
||||||
))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! error {
|
macro_rules! error {
|
||||||
($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!($($args)+)))
|
($($args:tt)+) => {
|
||||||
|
$crate::log_with_args($crate::ffi::LogLevel::Error, format_args_nl!($($args)+))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! warn {
|
macro_rules! warn {
|
||||||
($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Warn, format_args_nl!($($args)+)))
|
($($args:tt)+) => {
|
||||||
|
$crate::log_with_args($crate::ffi::LogLevel::Warn, format_args_nl!($($args)+))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! info {
|
macro_rules! info {
|
||||||
($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Info, format_args_nl!($($args)+)))
|
($($args:tt)+) => {
|
||||||
|
$crate::log_with_args($crate::ffi::LogLevel::Info, format_args_nl!($($args)+))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! debug {
|
macro_rules! debug {
|
||||||
($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Debug, format_args_nl!($($args)+)))
|
($($args:tt)+) => {
|
||||||
|
$crate::log_with_args($crate::ffi::LogLevel::Debug, format_args_nl!($($args)+))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
@ -149,15 +156,111 @@ macro_rules! debug {
|
|||||||
($($args:tt)+) => {};
|
($($args:tt)+) => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ResultExt {
|
#[derive(Default)]
|
||||||
fn log(self) -> Self;
|
pub struct LoggedError {}
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, E: Display> ResultExt for Result<T, E> {
|
// Automatically handle all printable errors
|
||||||
fn log(self) -> Self {
|
impl<T: Display> From<T> for LoggedError {
|
||||||
if let Err(e) = &self {
|
fn from(e: T) -> Self {
|
||||||
error!("{:#}", e);
|
log_with_args(LogLevel::Error, format_args_nl!("{:#}", e));
|
||||||
}
|
LoggedError::default()
|
||||||
self
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type LoggedResult<T> = Result<T, LoggedError>;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_err {
|
||||||
|
($msg:literal $(,)?) => {{
|
||||||
|
$crate::log_with_args($crate::ffi::LogLevel::Error, format_args_nl!($msg));
|
||||||
|
$crate::LoggedError::default()
|
||||||
|
}};
|
||||||
|
($err:expr $(,)?) => {{
|
||||||
|
$crate::log_with_args($crate::ffi::LogLevel::Error, format_args_nl!("{}", $err));
|
||||||
|
$crate::LoggedError::default()
|
||||||
|
}};
|
||||||
|
($($args:tt)+) => {{
|
||||||
|
$crate::log_with_args($crate::ffi::LogLevel::Error, format_args_nl!($($args)+));
|
||||||
|
$crate::LoggedError::default()
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ResultExt<T>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
fn log(self) -> LoggedResult<T> {
|
||||||
|
self.log_impl(LogLevel::Error)
|
||||||
|
}
|
||||||
|
fn log_cxx(self) -> LoggedResult<T> {
|
||||||
|
self.log_impl(LogLevel::ErrorCxx)
|
||||||
|
}
|
||||||
|
fn log_with_msg<F: FnOnce(&mut BufFormatter) -> fmt::Result>(self, f: F) -> LoggedResult<T> {
|
||||||
|
self.log_with_msg_impl(LogLevel::Error, f)
|
||||||
|
}
|
||||||
|
fn log_cxx_with_msg<F: FnOnce(&mut BufFormatter) -> fmt::Result>(
|
||||||
|
self,
|
||||||
|
f: F,
|
||||||
|
) -> LoggedResult<T> {
|
||||||
|
self.log_with_msg_impl(LogLevel::ErrorCxx, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log_impl(self, level: LogLevel) -> LoggedResult<T>;
|
||||||
|
fn log_with_msg_impl<F: FnOnce(&mut BufFormatter) -> fmt::Result>(
|
||||||
|
self,
|
||||||
|
level: LogLevel,
|
||||||
|
f: F,
|
||||||
|
) -> LoggedResult<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ResultExt<T> for LoggedResult<T> {
|
||||||
|
fn log_impl(self, _: LogLevel) -> LoggedResult<T> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log_with_msg_impl<F: FnOnce(&mut BufFormatter) -> fmt::Result>(
|
||||||
|
self,
|
||||||
|
level: LogLevel,
|
||||||
|
f: F,
|
||||||
|
) -> LoggedResult<T> {
|
||||||
|
match self {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(_) => {
|
||||||
|
log_with_formatter(level, |w| {
|
||||||
|
f(w)?;
|
||||||
|
w.write_char('\n')
|
||||||
|
});
|
||||||
|
Err(LoggedError::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, E: Display> ResultExt<T> for Result<T, E> {
|
||||||
|
fn log_impl(self, level: LogLevel) -> LoggedResult<T> {
|
||||||
|
match self {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => {
|
||||||
|
log_with_args(level, format_args_nl!("{:#}", e));
|
||||||
|
Err(LoggedError::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log_with_msg_impl<F: FnOnce(&mut BufFormatter) -> fmt::Result>(
|
||||||
|
self,
|
||||||
|
level: LogLevel,
|
||||||
|
f: F,
|
||||||
|
) -> LoggedResult<T> {
|
||||||
|
match self {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => {
|
||||||
|
log_with_formatter(level, |w| {
|
||||||
|
f(w)?;
|
||||||
|
writeln!(w, ": {:#}", e)
|
||||||
|
});
|
||||||
|
Err(LoggedError::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,18 +26,18 @@ pub fn copy_cstr<T: AsRef<CStr> + ?Sized>(dest: &mut [u8], src: &T) -> usize {
|
|||||||
len - 1
|
len - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BufFmtWriter<'a> {
|
pub struct BufFormatter<'a> {
|
||||||
buf: &'a mut [u8],
|
buf: &'a mut [u8],
|
||||||
used: usize,
|
pub used: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BufFmtWriter<'a> {
|
impl<'a> BufFormatter<'a> {
|
||||||
fn new(buf: &'a mut [u8]) -> Self {
|
pub fn new(buf: &'a mut [u8]) -> Self {
|
||||||
BufFmtWriter { buf, used: 0 }
|
BufFormatter { buf, used: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Write for BufFmtWriter<'a> {
|
impl<'a> fmt::Write for BufFormatter<'a> {
|
||||||
// The buffer should always be null terminated
|
// The buffer should always be null terminated
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
if self.used >= self.buf.len() - 1 {
|
if self.used >= self.buf.len() - 1 {
|
||||||
@ -51,7 +51,7 @@ impl<'a> fmt::Write for BufFmtWriter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_to_buf(buf: &mut [u8], args: Arguments) -> usize {
|
pub fn fmt_to_buf(buf: &mut [u8], args: Arguments) -> usize {
|
||||||
let mut w = BufFmtWriter::new(buf);
|
let mut w = BufFormatter::new(buf);
|
||||||
if let Ok(()) = fmt::write(&mut w, args) {
|
if let Ok(()) = fmt::write(&mut w, args) {
|
||||||
w.used
|
w.used
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,24 +1,45 @@
|
|||||||
|
use std::fmt::Write;
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use libc::{
|
use libc::{
|
||||||
c_char, c_uint, c_ulong, c_void, dev_t, mode_t, nfds_t, off_t, pollfd, sockaddr, socklen_t,
|
c_char, c_uint, c_ulong, c_void, dev_t, mode_t, nfds_t, off_t, pollfd, sockaddr, socklen_t,
|
||||||
ssize_t, SYS_dup3,
|
ssize_t, SYS_dup3,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{cstr, errno, error, mkdirs, perror, ptr_to_str, raw_cstr, ResultExt, Utf8CStr};
|
use crate::{cstr, errno, mkdirs, ptr_to_str, raw_cstr, ResultExt, Utf8CStr};
|
||||||
|
|
||||||
|
macro_rules! error_cxx {
|
||||||
|
($($args:tt)+) => {
|
||||||
|
($crate::log_with_args($crate::ffi::LogLevel::ErrorCxx, format_args_nl!($($args)+)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! perror {
|
||||||
|
($fmt:expr) => {
|
||||||
|
$crate::log_with_formatter($crate::ffi::LogLevel::ErrorCxx, |w| {
|
||||||
|
w.write_str($fmt)?;
|
||||||
|
w.write_fmt(format_args!(" failed with {}: {}", $crate::errno(), $crate::error_str()))
|
||||||
|
})
|
||||||
|
};
|
||||||
|
($fmt:expr, $($args:tt)*) => {
|
||||||
|
$crate::log_with_formatter($crate::ffi::LogLevel::ErrorCxx, |w| {
|
||||||
|
w.write_fmt(format_args!($fmt, $($args)*))?;
|
||||||
|
w.write_fmt(format_args!(" failed with {}: {}", $crate::errno(), $crate::error_str()))
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
mod unsafe_impl {
|
mod unsafe_impl {
|
||||||
|
use std::fmt::Write;
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use libc::{c_char, nfds_t, off_t, pollfd};
|
use libc::{c_char, nfds_t, off_t, pollfd};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
perror, ptr_to_str, readlink_unsafe, realpath, slice_from_ptr, slice_from_ptr_mut,
|
ptr_to_str, readlink_unsafe, realpath, slice_from_ptr, slice_from_ptr_mut, ResultExt,
|
||||||
ResultExt, Utf8CStr,
|
Utf8CStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -40,8 +61,7 @@ mod unsafe_impl {
|
|||||||
unsafe extern "C" fn xrealpath(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
|
unsafe extern "C" fn xrealpath(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
|
||||||
match Utf8CStr::from_ptr(path) {
|
match Utf8CStr::from_ptr(path) {
|
||||||
Ok(p) => realpath(p, slice_from_ptr_mut(buf, bufsz))
|
Ok(p) => realpath(p, slice_from_ptr_mut(buf, bufsz))
|
||||||
.with_context(|| format!("realpath {} failed", p))
|
.log_cxx_with_msg(|w| w.write_fmt(format_args!("realpath {} failed", p)))
|
||||||
.log()
|
|
||||||
.map_or(-1, |v| v as isize),
|
.map_or(-1, |v| v as isize),
|
||||||
Err(_) => -1,
|
Err(_) => -1,
|
||||||
}
|
}
|
||||||
@ -172,7 +192,7 @@ pub fn xwrite(fd: RawFd, data: &[u8]) -> isize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !remain.is_empty() {
|
if !remain.is_empty() {
|
||||||
error!("write ({} != {})", write_sz, data.len())
|
error_cxx!("write ({} != {})", write_sz, data.len())
|
||||||
}
|
}
|
||||||
write_sz as isize
|
write_sz as isize
|
||||||
}
|
}
|
||||||
@ -211,7 +231,7 @@ pub fn xxread(fd: RawFd, data: &mut [u8]) -> isize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !remain.is_empty() {
|
if !remain.is_empty() {
|
||||||
error!("read ({} != {})", read_sz, data.len())
|
error_cxx!("read ({} != {})", read_sz, data.len())
|
||||||
}
|
}
|
||||||
read_sz as isize
|
read_sz as isize
|
||||||
}
|
}
|
||||||
@ -572,8 +592,7 @@ pub unsafe extern "C" fn xmkdir(path: *const c_char, mode: mode_t) -> i32 {
|
|||||||
pub unsafe extern "C" fn xmkdirs(path: *const c_char, mode: mode_t) -> i32 {
|
pub unsafe extern "C" fn xmkdirs(path: *const c_char, mode: mode_t) -> i32 {
|
||||||
match Utf8CStr::from_ptr(path) {
|
match Utf8CStr::from_ptr(path) {
|
||||||
Ok(p) => mkdirs(p, mode)
|
Ok(p) => mkdirs(p, mode)
|
||||||
.with_context(|| format!("mkdirs {} failed", p))
|
.log_cxx_with_msg(|w| w.write_fmt(format_args!("mkdirs {} failed", p)))
|
||||||
.log()
|
|
||||||
.map_or(-1, |_| 0),
|
.map_or(-1, |_| 0),
|
||||||
Err(_) => -1,
|
Err(_) => -1,
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ pb-rs = { workspace = true }
|
|||||||
base = { path = "../base" }
|
base = { path = "../base" }
|
||||||
cxx = { path = "../external/cxx-rs" }
|
cxx = { path = "../external/cxx-rs" }
|
||||||
byteorder = { workspace = true }
|
byteorder = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
|
||||||
size = { workspace = true }
|
size = { workspace = true }
|
||||||
quick-protobuf = { workspace = true }
|
quick-protobuf = { workspace = true }
|
||||||
argh = { workspace = true }
|
argh = { workspace = true }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter, Write as FmtWrite};
|
||||||
use std::fs::{metadata, read, DirBuilder, File};
|
use std::fs::{metadata, read, DirBuilder, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
@ -9,16 +9,15 @@ use std::path::Path;
|
|||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
use anyhow::{anyhow, Context};
|
use argh::{EarlyExit, FromArgs};
|
||||||
use size::{Base, Size, Style};
|
use size::{Base, Size, Style};
|
||||||
|
|
||||||
use argh::{EarlyExit, FromArgs};
|
|
||||||
use base::libc::{
|
use base::libc::{
|
||||||
c_char, dev_t, gid_t, major, makedev, minor, mknod, mode_t, uid_t, S_IFBLK, S_IFCHR, S_IFDIR,
|
c_char, dev_t, gid_t, major, makedev, minor, mknod, mode_t, uid_t, S_IFBLK, S_IFCHR, S_IFDIR,
|
||||||
S_IFLNK, S_IFMT, S_IFREG, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP,
|
S_IFLNK, S_IFMT, S_IFREG, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP,
|
||||||
S_IXOTH, S_IXUSR,
|
S_IXOTH, S_IXUSR,
|
||||||
};
|
};
|
||||||
use base::{MappedFile, ResultExt, StrErr, Utf8CStr, WriteExt};
|
use base::{log_err, LoggedResult, MappedFile, ResultExt, StrErr, Utf8CStr, WriteExt};
|
||||||
|
|
||||||
use crate::ramdisk::MagiskCpio;
|
use crate::ramdisk::MagiskCpio;
|
||||||
|
|
||||||
@ -217,13 +216,13 @@ impl Cpio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_from_data(data: &[u8]) -> anyhow::Result<Self> {
|
fn load_from_data(data: &[u8]) -> LoggedResult<Self> {
|
||||||
let mut cpio = Cpio::new();
|
let mut cpio = Cpio::new();
|
||||||
let mut pos = 0usize;
|
let mut pos = 0usize;
|
||||||
while pos < data.len() {
|
while pos < data.len() {
|
||||||
let hdr = unsafe { &*(data.as_ptr().add(pos) as *const CpioHeader) };
|
let hdr = unsafe { &*(data.as_ptr().add(pos) as *const CpioHeader) };
|
||||||
if &hdr.magic != b"070701" {
|
if &hdr.magic != b"070701" {
|
||||||
return Err(anyhow!("invalid cpio magic"));
|
return Err(log_err!("invalid cpio magic"));
|
||||||
}
|
}
|
||||||
pos += size_of::<CpioHeader>();
|
pos += size_of::<CpioHeader>();
|
||||||
let name = CStr::from_bytes_until_nul(&data[pos..])?
|
let name = CStr::from_bytes_until_nul(&data[pos..])?
|
||||||
@ -257,13 +256,13 @@ impl Cpio {
|
|||||||
Ok(cpio)
|
Ok(cpio)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn load_from_file(path: &Utf8CStr) -> anyhow::Result<Self> {
|
pub(crate) fn load_from_file(path: &Utf8CStr) -> LoggedResult<Self> {
|
||||||
eprintln!("Loading cpio: [{}]", path);
|
eprintln!("Loading cpio: [{}]", path);
|
||||||
let file = MappedFile::open(path)?;
|
let file = MappedFile::open(path)?;
|
||||||
Self::load_from_data(file.as_ref())
|
Self::load_from_data(file.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump(&self, path: &str) -> anyhow::Result<()> {
|
fn dump(&self, path: &str) -> LoggedResult<()> {
|
||||||
eprintln!("Dumping cpio: [{}]", path);
|
eprintln!("Dumping cpio: [{}]", path);
|
||||||
let mut file = File::create(path)?;
|
let mut file = File::create(path)?;
|
||||||
let mut pos = 0usize;
|
let mut pos = 0usize;
|
||||||
@ -324,8 +323,8 @@ impl Cpio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_entry(&self, path: &str, out: &Path) -> anyhow::Result<()> {
|
fn extract_entry(&self, path: &str, out: &Path) -> LoggedResult<()> {
|
||||||
let entry = self.entries.get(path).ok_or(anyhow!("No such file"))?;
|
let entry = self.entries.get(path).ok_or(log_err!("No such file"))?;
|
||||||
eprintln!("Extracting entry [{}] to [{}]", path, out.to_string_lossy());
|
eprintln!("Extracting entry [{}] to [{}]", path, out.to_string_lossy());
|
||||||
if let Some(parent) = out.parent() {
|
if let Some(parent) = out.parent() {
|
||||||
DirBuilder::new()
|
DirBuilder::new()
|
||||||
@ -358,13 +357,13 @@ impl Cpio {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(anyhow!("unknown entry type"));
|
return Err(log_err!("unknown entry type"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract(&self, path: Option<&str>, out: Option<&str>) -> anyhow::Result<()> {
|
fn extract(&self, path: Option<&str>, out: Option<&str>) -> LoggedResult<()> {
|
||||||
let path = path.map(norm_path);
|
let path = path.map(norm_path);
|
||||||
let out = out.map(Path::new);
|
let out = out.map(Path::new);
|
||||||
if let (Some(path), Some(out)) = (&path, &out) {
|
if let (Some(path), Some(out)) = (&path, &out) {
|
||||||
@ -384,9 +383,9 @@ impl Cpio {
|
|||||||
self.entries.contains_key(&norm_path(path))
|
self.entries.contains_key(&norm_path(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&mut self, mode: &mode_t, path: &str, file: &str) -> anyhow::Result<()> {
|
fn add(&mut self, mode: &mode_t, path: &str, file: &str) -> LoggedResult<()> {
|
||||||
if path.ends_with('/') {
|
if path.ends_with('/') {
|
||||||
return Err(anyhow!("path cannot end with / for add"));
|
return Err(log_err!("path cannot end with / for add"));
|
||||||
}
|
}
|
||||||
let file = Path::new(file);
|
let file = Path::new(file);
|
||||||
let content = read(file)?;
|
let content = read(file)?;
|
||||||
@ -403,7 +402,7 @@ impl Cpio {
|
|||||||
} else if metadata.file_type().is_char_device() {
|
} else if metadata.file_type().is_char_device() {
|
||||||
mode | S_IFCHR
|
mode | S_IFCHR
|
||||||
} else {
|
} else {
|
||||||
return Err(anyhow!("unsupported file type"));
|
return Err(log_err!("unsupported file type"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.entries.insert(
|
self.entries.insert(
|
||||||
@ -451,11 +450,11 @@ impl Cpio {
|
|||||||
eprintln!("Create symlink [{}] -> [{}]", dst, src);
|
eprintln!("Create symlink [{}] -> [{}]", dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mv(&mut self, from: &str, to: &str) -> anyhow::Result<()> {
|
fn mv(&mut self, from: &str, to: &str) -> LoggedResult<()> {
|
||||||
let entry = self
|
let entry = self
|
||||||
.entries
|
.entries
|
||||||
.remove(&norm_path(from))
|
.remove(&norm_path(from))
|
||||||
.ok_or(anyhow!("no such entry {}", from))?;
|
.ok_or(log_err!("no such entry {}", from))?;
|
||||||
self.entries.insert(norm_path(to), entry);
|
self.entries.insert(norm_path(to), entry);
|
||||||
eprintln!("Move [{}] -> [{}]", from, to);
|
eprintln!("Move [{}] -> [{}]", from, to);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -521,9 +520,9 @@ impl Display for CpioEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
|
pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
|
||||||
fn inner(argc: i32, argv: *const *const c_char) -> anyhow::Result<()> {
|
fn inner(argc: i32, argv: *const *const c_char) -> LoggedResult<()> {
|
||||||
if argc < 1 {
|
if argc < 1 {
|
||||||
return Err(anyhow!("no arguments"));
|
return Err(log_err!("no arguments"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmds: Result<Vec<&Utf8CStr>, StrErr> =
|
let cmds: Result<Vec<&Utf8CStr>, StrErr> =
|
||||||
@ -556,7 +555,7 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
|
|||||||
eprintln!("{}", output);
|
eprintln!("{}", output);
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
Err(_) => return Err(anyhow!(output)),
|
Err(_) => return Err(log_err!(output)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
match &mut cli.command {
|
match &mut cli.command {
|
||||||
@ -580,7 +579,7 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
|
|||||||
CpioCommands::Add(Add { mode, path, file }) => cpio.add(mode, path, file)?,
|
CpioCommands::Add(Add { mode, path, file }) => cpio.add(mode, path, file)?,
|
||||||
CpioCommands::Extract(Extract { paths }) => {
|
CpioCommands::Extract(Extract { paths }) => {
|
||||||
if !paths.is_empty() && paths.len() != 2 {
|
if !paths.is_empty() && paths.len() != 2 {
|
||||||
return Err(anyhow!("invalid arguments"));
|
return Err(log_err!("invalid arguments"));
|
||||||
}
|
}
|
||||||
cpio.extract(
|
cpio.extract(
|
||||||
paths.get(0).map(|x| x.as_str()),
|
paths.get(0).map(|x| x.as_str()),
|
||||||
@ -597,20 +596,19 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
inner(argc, argv)
|
inner(argc, argv)
|
||||||
.context("Failed to process cpio")
|
.log_with_msg(|w| w.write_str("Failed to process cpio"))
|
||||||
.log()
|
|
||||||
.is_ok()
|
.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn x8u<U: TryFrom<u32>>(x: &[u8; 8]) -> anyhow::Result<U> {
|
fn x8u<U: TryFrom<u32>>(x: &[u8; 8]) -> LoggedResult<U> {
|
||||||
// parse hex
|
// parse hex
|
||||||
let mut ret = 0u32;
|
let mut ret = 0u32;
|
||||||
for i in x {
|
for i in x {
|
||||||
let c = *i as char;
|
let c = *i as char;
|
||||||
let v = c.to_digit(16).ok_or(anyhow!("bad cpio header"))?;
|
let v = c.to_digit(16).ok_or(log_err!("bad cpio header"))?;
|
||||||
ret = ret * 16 + v;
|
ret = ret * 16 + v;
|
||||||
}
|
}
|
||||||
ret.try_into().map_err(|_| anyhow!("bad cpio header"))
|
ret.try_into().map_err(|_| log_err!("bad cpio header"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use base::{MappedFile, MutBytesExt, ResultExt, Utf8CStr};
|
use base::{LoggedResult, MappedFile, MutBytesExt, Utf8CStr};
|
||||||
|
|
||||||
// SAFETY: assert(buf.len() >= 1) && assert(len <= buf.len())
|
// SAFETY: assert(buf.len() >= 1) && assert(len <= buf.len())
|
||||||
macro_rules! match_patterns {
|
macro_rules! match_patterns {
|
||||||
@ -102,7 +102,7 @@ fn hex2byte(hex: &[u8]) -> Vec<u8> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn hexpatch(file: &[u8], from: &[u8], to: &[u8]) -> bool {
|
pub fn hexpatch(file: &[u8], from: &[u8], to: &[u8]) -> bool {
|
||||||
fn inner(file: &[u8], from: &[u8], to: &[u8]) -> anyhow::Result<bool> {
|
fn inner(file: &[u8], from: &[u8], to: &[u8]) -> LoggedResult<bool> {
|
||||||
let file = Utf8CStr::from_bytes(file)?;
|
let file = Utf8CStr::from_bytes(file)?;
|
||||||
let from = Utf8CStr::from_bytes(from)?;
|
let from = Utf8CStr::from_bytes(from)?;
|
||||||
let to = Utf8CStr::from_bytes(to)?;
|
let to = Utf8CStr::from_bytes(to)?;
|
||||||
@ -118,5 +118,5 @@ pub fn hexpatch(file: &[u8], from: &[u8], to: &[u8]) -> bool {
|
|||||||
|
|
||||||
Ok(!v.is_empty())
|
Ok(!v.is_empty())
|
||||||
}
|
}
|
||||||
inner(file, from, to).log().unwrap_or(false)
|
inner(file, from, to).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
|
use std::fmt::Write as FmtWrite;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufReader, Read, Seek, SeekFrom, Write};
|
use std::io::{BufReader, Read, Seek, SeekFrom, Write};
|
||||||
use std::os::fd::{AsRawFd, FromRawFd};
|
use std::os::fd::{AsRawFd, FromRawFd};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context};
|
|
||||||
use byteorder::{BigEndian, ReadBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
use quick_protobuf::{BytesReader, MessageRead};
|
use quick_protobuf::{BytesReader, MessageRead};
|
||||||
|
|
||||||
use base::libc::c_char;
|
use base::libc::c_char;
|
||||||
use base::{ReadSeekExt, StrErr, Utf8CStr};
|
use base::{error, LoggedError, LoggedResult, ReadSeekExt, StrErr, Utf8CStr};
|
||||||
use base::{ResultExt, WriteExt};
|
use base::{ResultExt, WriteExt};
|
||||||
|
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
@ -15,12 +15,14 @@ use crate::proto::update_metadata::mod_InstallOperation::Type;
|
|||||||
use crate::proto::update_metadata::DeltaArchiveManifest;
|
use crate::proto::update_metadata::DeltaArchiveManifest;
|
||||||
|
|
||||||
macro_rules! bad_payload {
|
macro_rules! bad_payload {
|
||||||
($msg:literal) => {
|
($msg:literal) => {{
|
||||||
anyhow!(concat!("invalid payload: ", $msg))
|
error!(concat!("Invalid payload: ", $msg));
|
||||||
};
|
LoggedError::default()
|
||||||
($($args:tt)*) => {
|
}};
|
||||||
anyhow!("invalid payload: {}", format_args!($($args)*))
|
($($args:tt)*) => {{
|
||||||
};
|
error!("Invalid payload: {}", format_args!($($args)*));
|
||||||
|
LoggedError::default()
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
const PAYLOAD_MAGIC: &str = "CrAU";
|
const PAYLOAD_MAGIC: &str = "CrAU";
|
||||||
@ -29,11 +31,11 @@ fn do_extract_boot_from_payload(
|
|||||||
in_path: &Utf8CStr,
|
in_path: &Utf8CStr,
|
||||||
partition_name: Option<&Utf8CStr>,
|
partition_name: Option<&Utf8CStr>,
|
||||||
out_path: Option<&Utf8CStr>,
|
out_path: Option<&Utf8CStr>,
|
||||||
) -> anyhow::Result<()> {
|
) -> LoggedResult<()> {
|
||||||
let mut reader = BufReader::new(if in_path == "-" {
|
let mut reader = BufReader::new(if in_path == "-" {
|
||||||
unsafe { File::from_raw_fd(0) }
|
unsafe { File::from_raw_fd(0) }
|
||||||
} else {
|
} else {
|
||||||
File::open(in_path).with_context(|| format!("cannot open '{in_path}'"))?
|
File::open(in_path).log_with_msg(|w| write!(w, "Cannot open '{}'", in_path))?
|
||||||
});
|
});
|
||||||
|
|
||||||
let buf = &mut [0u8; 4];
|
let buf = &mut [0u8; 4];
|
||||||
@ -88,13 +90,13 @@ fn do_extract_boot_from_payload(
|
|||||||
.iter()
|
.iter()
|
||||||
.find(|p| p.partition_name == "boot"),
|
.find(|p| p.partition_name == "boot"),
|
||||||
};
|
};
|
||||||
boot.ok_or(anyhow!("boot partition not found"))?
|
boot.ok_or_else(|| bad_payload!("boot partition not found"))?
|
||||||
}
|
}
|
||||||
Some(name) => manifest
|
Some(name) => manifest
|
||||||
.partitions
|
.partitions
|
||||||
.iter()
|
.iter()
|
||||||
.find(|p| p.partition_name.as_str() == name)
|
.find(|p| p.partition_name.as_str() == name)
|
||||||
.ok_or(anyhow!("partition '{name}' not found"))?,
|
.ok_or_else(|| bad_payload!("partition '{}' not found", name))?,
|
||||||
};
|
};
|
||||||
|
|
||||||
let out_str: String;
|
let out_str: String;
|
||||||
@ -107,7 +109,7 @@ fn do_extract_boot_from_payload(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut out_file =
|
let mut out_file =
|
||||||
File::create(out_path).with_context(|| format!("cannot write to '{out_path}'"))?;
|
File::create(out_path).log_with_msg(|w| write!(w, "Cannot write to '{}'", out_path))?;
|
||||||
|
|
||||||
// Skip the manifest signature
|
// Skip the manifest signature
|
||||||
reader.skip(manifest_sig_len as usize)?;
|
reader.skip(manifest_sig_len as usize)?;
|
||||||
@ -121,11 +123,11 @@ fn do_extract_boot_from_payload(
|
|||||||
for operation in operations.iter() {
|
for operation in operations.iter() {
|
||||||
let data_len = operation
|
let data_len = operation
|
||||||
.data_length
|
.data_length
|
||||||
.ok_or(bad_payload!("data length not found"))? as usize;
|
.ok_or_else(|| bad_payload!("data length not found"))? as usize;
|
||||||
|
|
||||||
let data_offset = operation
|
let data_offset = operation
|
||||||
.data_offset
|
.data_offset
|
||||||
.ok_or(bad_payload!("data offset not found"))?;
|
.ok_or_else(|| bad_payload!("data offset not found"))?;
|
||||||
|
|
||||||
let data_type = operation.type_pb;
|
let data_type = operation.type_pb;
|
||||||
|
|
||||||
@ -141,9 +143,9 @@ fn do_extract_boot_from_payload(
|
|||||||
let out_offset = operation
|
let out_offset = operation
|
||||||
.dst_extents
|
.dst_extents
|
||||||
.get(0)
|
.get(0)
|
||||||
.ok_or(bad_payload!("dst extents not found"))?
|
.ok_or_else(|| bad_payload!("dst extents not found"))?
|
||||||
.start_block
|
.start_block
|
||||||
.ok_or(bad_payload!("start block not found"))?
|
.ok_or_else(|| bad_payload!("start block not found"))?
|
||||||
* block_size;
|
* block_size;
|
||||||
|
|
||||||
match data_type {
|
match data_type {
|
||||||
@ -184,7 +186,7 @@ pub fn extract_boot_from_payload(
|
|||||||
in_path: *const c_char,
|
in_path: *const c_char,
|
||||||
partition: *const c_char,
|
partition: *const c_char,
|
||||||
out_path: *const c_char,
|
out_path: *const c_char,
|
||||||
) -> anyhow::Result<()> {
|
) -> LoggedResult<()> {
|
||||||
let in_path = unsafe { Utf8CStr::from_ptr(in_path) }?;
|
let in_path = unsafe { Utf8CStr::from_ptr(in_path) }?;
|
||||||
let partition = match unsafe { Utf8CStr::from_ptr(partition) } {
|
let partition = match unsafe { Utf8CStr::from_ptr(partition) } {
|
||||||
Ok(s) => Some(s),
|
Ok(s) => Some(s),
|
||||||
@ -197,8 +199,7 @@ pub fn extract_boot_from_payload(
|
|||||||
Err(e) => Err(e)?,
|
Err(e) => Err(e)?,
|
||||||
};
|
};
|
||||||
do_extract_boot_from_payload(in_path, partition, out_path)
|
do_extract_boot_from_payload(in_path, partition, out_path)
|
||||||
.context("Failed to extract from payload")?;
|
.log_with_msg(|w| w.write_str("Failed to extract from payload"))
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
inner(in_path, partition, out_path).log().is_ok()
|
inner(in_path, partition, out_path).is_ok()
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use std::env;
|
|||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
|
|
||||||
use base::libc::{S_IFDIR, S_IFMT, S_IFREG};
|
use base::libc::{S_IFDIR, S_IFMT, S_IFREG};
|
||||||
use base::Utf8CStr;
|
use base::{LoggedResult, Utf8CStr};
|
||||||
|
|
||||||
use crate::cpio::{Cpio, CpioEntry};
|
use crate::cpio::{Cpio, CpioEntry};
|
||||||
use crate::patch::{patch_encryption, patch_verity};
|
use crate::patch::{patch_encryption, patch_verity};
|
||||||
@ -12,8 +12,8 @@ use crate::patch::{patch_encryption, patch_verity};
|
|||||||
pub trait MagiskCpio {
|
pub trait MagiskCpio {
|
||||||
fn patch(&mut self);
|
fn patch(&mut self);
|
||||||
fn test(&self) -> i32;
|
fn test(&self) -> i32;
|
||||||
fn restore(&mut self) -> anyhow::Result<()>;
|
fn restore(&mut self) -> LoggedResult<()>;
|
||||||
fn backup(&mut self, origin: &Utf8CStr) -> anyhow::Result<()>;
|
fn backup(&mut self, origin: &Utf8CStr) -> LoggedResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAGISK_PATCHED: i32 = 1 << 0;
|
const MAGISK_PATCHED: i32 = 1 << 0;
|
||||||
@ -89,7 +89,7 @@ impl MagiskCpio for Cpio {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(&mut self) -> anyhow::Result<()> {
|
fn restore(&mut self) -> LoggedResult<()> {
|
||||||
let mut backups = HashMap::<String, Box<CpioEntry>>::new();
|
let mut backups = HashMap::<String, Box<CpioEntry>>::new();
|
||||||
let mut rm_list = String::new();
|
let mut rm_list = String::new();
|
||||||
self.entries
|
self.entries
|
||||||
@ -120,7 +120,7 @@ impl MagiskCpio for Cpio {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn backup(&mut self, origin: &Utf8CStr) -> anyhow::Result<()> {
|
fn backup(&mut self, origin: &Utf8CStr) -> LoggedResult<()> {
|
||||||
let mut backups = HashMap::<String, Box<CpioEntry>>::new();
|
let mut backups = HashMap::<String, Box<CpioEntry>>::new();
|
||||||
let mut rm_list = String::new();
|
let mut rm_list = String::new();
|
||||||
backups.insert(
|
backups.insert(
|
||||||
|
@ -13,4 +13,3 @@ cxx-gen = { workspace = true }
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
base = { path = "../base" }
|
base = { path = "../base" }
|
||||||
cxx = { workspace = true }
|
cxx = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
|
||||||
|
@ -38,13 +38,13 @@ impl SepolicyExt for sepolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_rule_file(self: Pin<&mut sepolicy>, filename: &[u8]) {
|
fn load_rule_file(self: Pin<&mut sepolicy>, filename: &[u8]) {
|
||||||
fn inner(sepol: Pin<&mut sepolicy>, filename: &[u8]) -> anyhow::Result<()> {
|
fn inner(sepol: Pin<&mut sepolicy>, filename: &[u8]) -> LoggedResult<()> {
|
||||||
let filename = str::from_utf8(filename)?;
|
let filename = str::from_utf8(filename)?;
|
||||||
let mut reader = BufReader::new(File::open(filename)?);
|
let mut reader = BufReader::new(File::open(filename)?);
|
||||||
sepol.load_rules_from_reader(&mut reader);
|
sepol.load_rules_from_reader(&mut reader);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
inner(self, filename).log().ok();
|
inner(self, filename).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) {
|
fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user