diff --git a/native/src/Cargo.lock b/native/src/Cargo.lock index f73b2097c..5492d8257 100644 --- a/native/src/Cargo.lock +++ b/native/src/Cargo.lock @@ -69,6 +69,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" name = "base" version = "0.0.0" dependencies = [ + "argh", "cfg-if", "cxx", "cxx-gen", diff --git a/native/src/base/Cargo.toml b/native/src/base/Cargo.toml index 371b53329..bfb8e57f8 100644 --- a/native/src/base/Cargo.toml +++ b/native/src/base/Cargo.toml @@ -14,3 +14,4 @@ cxx = { workspace = true } libc = { workspace = true } cfg-if = { workspace = true } thiserror = { workspace = true } +argh = { workspace = true } diff --git a/native/src/base/misc.rs b/native/src/base/misc.rs index d0cc45359..1a048f05a 100644 --- a/native/src/base/misc.rs +++ b/native/src/base/misc.rs @@ -3,9 +3,11 @@ use std::ffi::{CStr, FromBytesWithNulError, OsStr}; use std::fmt::{Arguments, Debug, Display, Formatter}; use std::ops::Deref; use std::path::Path; +use std::process::exit; use std::str::Utf8Error; use std::{fmt, io, mem, slice, str}; +use argh::EarlyExit; use libc::c_char; use thiserror::Error; @@ -297,18 +299,18 @@ where fn as_raw_bytes(&self) -> &[u8] { unsafe { let self_ptr = self as *const Self as *const u8; - slice::from_raw_parts(self_ptr, std::mem::size_of::()) + slice::from_raw_parts(self_ptr, mem::size_of::()) } } fn as_raw_bytes_mut(&mut self) -> &mut [u8] { unsafe { let self_ptr = self as *mut Self as *mut u8; - slice::from_raw_parts_mut(self_ptr, std::mem::size_of::()) + slice::from_raw_parts_mut(self_ptr, mem::size_of::()) } } fn bytes_size(&self) -> usize { - std::mem::size_of::() + mem::size_of::() } } @@ -369,3 +371,34 @@ impl> MutBytesExt for T { ffi::mut_u8_patch(self.as_mut(), from, to) } } + +// SAFETY: libc guarantees argc and argv is properly setup +#[allow(clippy::not_unsafe_ptr_arg_deref)] +pub fn map_args<'a>(argc: i32, argv: *const *const c_char) -> Result, StrErr> { + unsafe { slice::from_raw_parts(argv, argc as usize) } + .iter() + .map(|s| unsafe { Utf8CStr::from_ptr(*s) }) + .collect() +} + +pub trait EarlyExitExt { + fn early_exit(self) -> T; +} + +impl EarlyExitExt for Result { + fn early_exit(self) -> T { + match self { + Ok(t) => t, + Err(EarlyExit { output, status }) => match status { + Ok(_) => { + eprintln!("{}", output); + exit(0) + } + Err(_) => { + eprintln!("{}", output); + exit(1) + } + }, + } + } +} diff --git a/native/src/boot/cpio.rs b/native/src/boot/cpio.rs index bf0819c7a..cf2402a9d 100644 --- a/native/src/boot/cpio.rs +++ b/native/src/boot/cpio.rs @@ -7,9 +7,8 @@ use std::mem::size_of; use std::os::unix::fs::{symlink, DirBuilderExt, FileTypeExt, MetadataExt}; use std::path::Path; use std::process::exit; -use std::slice; -use argh::{EarlyExit, FromArgs}; +use argh::FromArgs; use size::{Base, Size, Style}; use base::libc::{ @@ -17,7 +16,9 @@ use base::libc::{ S_IFLNK, S_IFMT, S_IFREG, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR, }; -use base::{log_err, LoggedResult, MappedFile, ResultExt, StrErr, Utf8CStr, WriteExt}; +use base::{ + log_err, map_args, EarlyExitExt, LoggedResult, MappedFile, ResultExt, Utf8CStr, WriteExt, +}; use crate::ramdisk::MagiskCpio; @@ -525,12 +526,7 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool { return Err(log_err!("no arguments")); } - let cmds: Result, StrErr> = - unsafe { slice::from_raw_parts(argv, argc as usize) } - .iter() - .map(|s| unsafe { Utf8CStr::from_ptr(*s) }) - .collect(); - let cmds = cmds?; + let cmds = map_args(argc, argv)?; let file = cmds[0]; let mut cpio = if Path::new(file).exists() { @@ -538,26 +534,20 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool { } else { Cpio::new() }; + for cmd in &cmds[1..] { if cmd.starts_with('#') { continue; } - let mut cli = match CpioCli::from_args( + let mut cli = CpioCli::from_args( &["magiskboot", "cpio", file], cmd.split(' ') .filter(|x| !x.is_empty()) .collect::>() .as_slice(), - ) { - Ok(cli) => cli, - Err(EarlyExit { output, status }) => match status { - Ok(_) => { - eprintln!("{}", output); - exit(0) - } - Err(_) => return Err(log_err!(output)), - }, - }; + ) + .early_exit(); + match &mut cli.command { CpioCommands::Test(Test {}) => exit(cpio.test()), CpioCommands::Restore(Restore {}) => cpio.restore()?, @@ -590,7 +580,7 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool { cpio.ls(path.as_str(), *recursive); exit(0); } - } + }; } cpio.dump(file)?; Ok(()) diff --git a/native/src/boot/main.cpp b/native/src/boot/main.cpp index e43f0255e..f69a2f330 100644 --- a/native/src/boot/main.cpp +++ b/native/src/boot/main.cpp @@ -177,9 +177,8 @@ int main(int argc, char *argv[]) { compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]); } else if (argc > 4 && action == "hexpatch") { return hexpatch(byte_view(argv[2]), byte_view(argv[3]), byte_view(argv[4])) ? 0 : 1; - } else if (argc > 2 && action == "cpio"sv) { - if (!rust::cpio_commands(argc - 2, argv + 2)) - usage(argv[0]); + } else if (argc > 2 && action == "cpio") { + return rust::cpio_commands(argc - 2, argv + 2) ? 0 : 1; } else if (argc > 3 && action == "dtb") { if (dtb_commands(argc - 2, argv + 2)) usage(argv[0]);