Support compressing during cpio backup

This commit is contained in:
LoveSy
2023-12-08 23:30:55 +08:00
committed by topjohnwu
parent d73c2daf6d
commit 8b7fae278b
9 changed files with 145 additions and 11 deletions

View File

@@ -732,3 +732,24 @@ bool decompress(rust::Slice<const uint8_t> buf, int fd) {
}
return true;
}
bool xz(rust::Slice<const uint8_t> buf, rust::Vec<uint8_t> &out) {
auto strm = get_encoder(XZ, make_unique<rust_vec_channel>(out));
if (!strm->write(buf.data(), buf.length())) {
return false;
}
return true;
}
bool unxz(rust::Slice<const uint8_t> buf, rust::Vec<uint8_t> &out) {
format_t type = check_fmt(buf.data(), buf.length());
if (type != XZ) {
LOGE("Input file is not in xz format!\n");
return false;
}
auto strm = get_decoder(XZ, make_unique<rust_vec_channel>(out));
if (!strm->write(buf.data(), buf.length())) {
return false;
}
return true;
}

View File

@@ -10,3 +10,5 @@ out_strm_ptr get_decoder(format_t type, out_strm_ptr &&base);
void compress(const char *method, const char *infile, const char *outfile);
void decompress(char *infile, const char *outfile);
bool decompress(rust::Slice<const uint8_t> buf, int fd);
bool xz(rust::Slice<const uint8_t> buf, rust::Vec<uint8_t> &out);
bool unxz(rust::Slice<const uint8_t> buf, rust::Vec<uint8_t> &out);

View File

@@ -15,6 +15,7 @@ use bytemuck::{from_bytes, Pod, Zeroable};
use num_traits::cast::AsPrimitive;
use size::{Base, Size, Style};
use crate::ffi::{unxz, xz};
use base::libc::{
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,
@@ -81,6 +82,8 @@ struct Exists {
struct Backup {
#[argh(positional, arg_name = "orig")]
origin: String,
#[argh(switch, short = 'n')]
skip_compress: bool,
}
#[derive(FromArgs)]
@@ -177,8 +180,8 @@ Supported commands:
patch
Apply ramdisk patches
Configure with env variables: KEEPVERITY KEEPFORCEENCRYPT
backup ORIG
Create ramdisk backups from ORIG
backup ORIG [-n]
Create ramdisk backups from ORIG, specify [-n] to skip compression
restore
Restore ramdisk from ramdisk backup stored within incpio
"#
@@ -495,6 +498,26 @@ impl Cpio {
}
}
impl CpioEntry {
pub(crate) fn compress(&mut self) -> LoggedResult<()> {
let mut compressed = Vec::new();
if !xz(&self.data, &mut compressed) {
return Err(log_err!("xz compression failed"));
}
self.data = compressed;
Ok(())
}
pub(crate) fn decompress(&mut self) -> LoggedResult<()> {
let mut decompressed = Vec::new();
if !unxz(&self.data, &mut decompressed) {
return Err(log_err!("xz decompression failed"));
}
self.data = decompressed;
Ok(())
}
}
impl Display for CpioEntry {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
@@ -572,9 +595,10 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
exit(1);
}
}
CpioSubCommand::Backup(Backup { origin }) => {
cpio.backup(Utf8CStr::from_string(origin))?
}
CpioSubCommand::Backup(Backup {
origin,
skip_compress,
}) => cpio.backup(Utf8CStr::from_string(origin), *skip_compress)?,
CpioSubCommand::Remove(Remove { path, recursive }) => cpio.rm(path, *recursive),
CpioSubCommand::Move(Move { from, to }) => cpio.mv(from, to)?,
CpioSubCommand::MakeDir(MakeDir { mode, dir }) => cpio.mkdir(mode, dir),

View File

@@ -25,6 +25,8 @@ pub mod ffi {
unsafe extern "C++" {
include!("compress.hpp");
fn decompress(buf: &[u8], fd: i32) -> bool;
fn xz(buf: &[u8], out: &mut Vec<u8>) -> bool;
fn unxz(buf: &[u8], out: &mut Vec<u8>) -> bool;
include!("bootimg.hpp");
#[cxx_name = "boot_img"]

View File

@@ -13,7 +13,7 @@ pub trait MagiskCpio {
fn patch(&mut self);
fn test(&self) -> i32;
fn restore(&mut self) -> LoggedResult<()>;
fn backup(&mut self, origin: &Utf8CStr) -> LoggedResult<()>;
fn backup(&mut self, origin: &Utf8CStr, skip_compress: bool) -> LoggedResult<()>;
}
const MAGISK_PATCHED: i32 = 1 << 0;
@@ -89,13 +89,17 @@ impl MagiskCpio for Cpio {
let mut rm_list = String::new();
self.entries
.extract_if(|name, _| name.starts_with(".backup/"))
.for_each(|(name, entry)| {
.for_each(|(name, mut entry)| {
if name == ".backup/.rmlist" {
if let Ok(data) = from_utf8(&entry.data) {
rm_list.push_str(data);
}
} else if name != ".backup/.magisk" {
let new_name = &name[8..];
let new_name = if name.ends_with(".xz") && entry.decompress().is_ok() {
&name[8..name.len() - 3]
} else {
&name[8..]
};
eprintln!("Restore [{}] -> [{}]", name, new_name);
backups.insert(new_name.to_string(), entry);
}
@@ -115,7 +119,7 @@ impl MagiskCpio for Cpio {
Ok(())
}
fn backup(&mut self, origin: &Utf8CStr) -> LoggedResult<()> {
fn backup(&mut self, origin: &Utf8CStr, skip_compress: bool) -> LoggedResult<()> {
let mut backups = HashMap::<String, Box<CpioEntry>>::new();
let mut rm_list = String::new();
backups.insert(
@@ -170,8 +174,12 @@ impl MagiskCpio for Cpio {
}
};
match action {
Action::Backup(name, entry) => {
let backup = format!(".backup/{}", name);
Action::Backup(name, mut entry) => {
let backup = if !skip_compress && entry.compress().is_ok() {
format!(".backup/{}.xz", name)
} else {
format!(".backup/{}", name)
};
eprintln!("Backup [{}] -> [{}]", name, backup);
backups.insert(backup, entry);
}