mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 07:57:39 +00:00
Support 32-bit magiskboot
This commit is contained in:
parent
0d9ec0931b
commit
2e4440b702
@ -4,16 +4,14 @@ use std::ffi::CStr;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write};
|
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::os::android::fs::MetadataExt;
|
|
||||||
use std::os::fd::{AsFd, BorrowedFd, IntoRawFd};
|
use std::os::fd::{AsFd, BorrowedFd, IntoRawFd};
|
||||||
use std::os::unix::fs::FileTypeExt;
|
|
||||||
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
|
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
|
||||||
use std::{io, mem, ptr, slice};
|
use std::{io, mem, ptr, slice};
|
||||||
|
|
||||||
use bytemuck::{bytes_of_mut, Pod};
|
use bytemuck::{bytes_of_mut, Pod};
|
||||||
use libc::{
|
use libc::{
|
||||||
c_uint, dirent, makedev, mode_t, EEXIST, ENOENT, F_OK, O_CLOEXEC, O_CREAT, O_PATH, O_RDONLY,
|
c_uint, dirent, makedev, mode_t, EEXIST, ENOENT, F_OK, O_CLOEXEC, O_CREAT, O_PATH, O_RDONLY,
|
||||||
O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFREG,
|
O_RDWR, O_TRUNC, O_WRONLY,
|
||||||
};
|
};
|
||||||
use num_traits::AsPrimitive;
|
use num_traits::AsPrimitive;
|
||||||
|
|
||||||
@ -151,6 +149,40 @@ impl FileAttr {
|
|||||||
con: Utf8CStrBufArr::new(),
|
con: Utf8CStrBufArr::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[allow(clippy::unnecessary_cast)]
|
||||||
|
fn is(&self, mode: mode_t) -> bool {
|
||||||
|
(self.st.st_mode & libc::S_IFMT as u32) as mode_t == mode
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_dir(&self) -> bool {
|
||||||
|
self.is(libc::S_IFDIR)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_file(&self) -> bool {
|
||||||
|
self.is(libc::S_IFREG)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_symlink(&self) -> bool {
|
||||||
|
self.is(libc::S_IFLNK)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_block_device(&self) -> bool {
|
||||||
|
self.is(libc::S_IFBLK)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_char_device(&self) -> bool {
|
||||||
|
self.is(libc::S_IFCHR)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_fifo(&self) -> bool {
|
||||||
|
self.is(libc::S_IFIFO)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_socket(&self) -> bool {
|
||||||
|
self.is(libc::S_IFSOCK)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "selinux")]
|
#[cfg(feature = "selinux")]
|
||||||
@ -187,10 +219,26 @@ impl DirEntry<'_> {
|
|||||||
self.d_type == libc::DT_REG
|
self.d_type == libc::DT_REG
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_lnk(&self) -> bool {
|
pub fn is_symlink(&self) -> bool {
|
||||||
self.d_type == libc::DT_LNK
|
self.d_type == libc::DT_LNK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_block_device(&self) -> bool {
|
||||||
|
self.d_type == libc::DT_BLK
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_char_device(&self) -> bool {
|
||||||
|
self.d_type == libc::DT_CHR
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_fifo(&self) -> bool {
|
||||||
|
self.d_type == libc::DT_FIFO
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_socket(&self) -> bool {
|
||||||
|
self.d_type == libc::DT_SOCK
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unlink(&self) -> io::Result<()> {
|
pub fn unlink(&self) -> io::Result<()> {
|
||||||
let flag = if self.is_dir() { libc::AT_REMOVEDIR } else { 0 };
|
let flag = if self.is_dir() { libc::AT_REMOVEDIR } else { 0 };
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -372,7 +420,7 @@ impl Directory {
|
|||||||
};
|
};
|
||||||
std::io::copy(&mut src, &mut dest)?;
|
std::io::copy(&mut src, &mut dest)?;
|
||||||
fd_set_attr(dest.as_raw_fd(), &attr)?;
|
fd_set_attr(dest.as_raw_fd(), &attr)?;
|
||||||
} else if e.is_lnk() {
|
} else if e.is_symlink() {
|
||||||
let mut path = Utf8CStrBufArr::default();
|
let mut path = Utf8CStrBufArr::default();
|
||||||
e.read_link(&mut path)?;
|
e.read_link(&mut path)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -550,10 +598,9 @@ impl FsPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_all(&self) -> io::Result<()> {
|
pub fn remove_all(&self) -> io::Result<()> {
|
||||||
let f = self.open(O_RDONLY | O_CLOEXEC)?;
|
let attr = self.get_attr()?;
|
||||||
let st = f.metadata()?;
|
if attr.is_dir() {
|
||||||
if st.is_dir() {
|
let mut dir = Directory::try_from(open_fd!(self, O_RDONLY | O_CLOEXEC)?)?;
|
||||||
let mut dir = Directory::try_from(OwnedFd::from(f))?;
|
|
||||||
dir.remove_all()?;
|
dir.remove_all()?;
|
||||||
}
|
}
|
||||||
self.remove()
|
self.remove()
|
||||||
@ -652,7 +699,7 @@ impl FsPath {
|
|||||||
|
|
||||||
pub fn set_attr(&self, attr: &FileAttr) -> io::Result<()> {
|
pub fn set_attr(&self, attr: &FileAttr) -> io::Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if (attr.st.st_mode & libc::S_IFMT as c_uint) != S_IFLNK.as_() {
|
if !attr.is_symlink() {
|
||||||
libc::chmod(self.as_ptr(), (attr.st.st_mode & 0o777).as_()).as_os_err()?;
|
libc::chmod(self.as_ptr(), (attr.st.st_mode & 0o777).as_()).as_os_err()?;
|
||||||
}
|
}
|
||||||
libc::lchown(self.as_ptr(), attr.st.st_uid, attr.st.st_gid).as_os_err()?;
|
libc::lchown(self.as_ptr(), attr.st.st_uid, attr.st.st_gid).as_os_err()?;
|
||||||
@ -674,7 +721,7 @@ impl FsPath {
|
|||||||
|
|
||||||
pub fn copy_to(&self, path: &FsPath) -> io::Result<()> {
|
pub fn copy_to(&self, path: &FsPath) -> io::Result<()> {
|
||||||
let attr = self.get_attr()?;
|
let attr = self.get_attr()?;
|
||||||
if (attr.st.st_mode & libc::S_IFMT as c_uint) == S_IFDIR.as_() {
|
if attr.is_dir() {
|
||||||
path.mkdir(0o777)?;
|
path.mkdir(0o777)?;
|
||||||
let mut src = Directory::open(self)?;
|
let mut src = Directory::open(self)?;
|
||||||
let dest = Directory::open(path)?;
|
let dest = Directory::open(path)?;
|
||||||
@ -682,11 +729,11 @@ impl FsPath {
|
|||||||
} else {
|
} else {
|
||||||
// It's OK if remove failed
|
// It's OK if remove failed
|
||||||
path.remove().ok();
|
path.remove().ok();
|
||||||
if (attr.st.st_mode & libc::S_IFMT as c_uint) == S_IFREG.as_() {
|
if attr.is_file() {
|
||||||
let mut src = self.open(O_RDONLY | O_CLOEXEC)?;
|
let mut src = self.open(O_RDONLY | O_CLOEXEC)?;
|
||||||
let mut dest = path.create(O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0o777)?;
|
let mut dest = path.create(O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0o777)?;
|
||||||
std::io::copy(&mut src, &mut dest)?;
|
std::io::copy(&mut src, &mut dest)?;
|
||||||
} else if (attr.st.st_mode & libc::S_IFMT as c_uint) == S_IFLNK.as_() {
|
} else if attr.is_symlink() {
|
||||||
let mut buf = Utf8CStrBufArr::default();
|
let mut buf = Utf8CStrBufArr::default();
|
||||||
self.read_link(&mut buf)?;
|
self.read_link(&mut buf)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -701,7 +748,7 @@ impl FsPath {
|
|||||||
pub fn move_to(&self, path: &FsPath) -> io::Result<()> {
|
pub fn move_to(&self, path: &FsPath) -> io::Result<()> {
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
let attr = path.get_attr()?;
|
let attr = path.get_attr()?;
|
||||||
if (attr.st.st_mode & libc::S_IFMT as c_uint) == S_IFDIR.as_() {
|
if attr.is_dir() {
|
||||||
let mut src = Directory::open(self)?;
|
let mut src = Directory::open(self)?;
|
||||||
let dest = Directory::open(path)?;
|
let dest = Directory::open(path)?;
|
||||||
return src.move_into(&dest);
|
return src.move_into(&dest);
|
||||||
@ -714,7 +761,7 @@ impl FsPath {
|
|||||||
|
|
||||||
pub fn link_to(&self, path: &FsPath) -> io::Result<()> {
|
pub fn link_to(&self, path: &FsPath) -> io::Result<()> {
|
||||||
let attr = self.get_attr()?;
|
let attr = self.get_attr()?;
|
||||||
if (attr.st.st_mode & libc::S_IFMT as c_uint) == S_IFDIR.as_() {
|
if attr.is_dir() {
|
||||||
path.mkdir(0o777)?;
|
path.mkdir(0o777)?;
|
||||||
path.set_attr(&attr)?;
|
path.set_attr(&attr)?;
|
||||||
let mut src = Directory::open(self)?;
|
let mut src = Directory::open(self)?;
|
||||||
@ -828,13 +875,13 @@ pub(crate) fn map_file(path: &Utf8CStr, rw: bool) -> io::Result<&'static mut [u8
|
|||||||
let flag = if rw { O_RDWR } else { O_RDONLY };
|
let flag = if rw { O_RDWR } else { O_RDONLY };
|
||||||
let f = File::from(open_fd!(path, flag | O_CLOEXEC)?);
|
let f = File::from(open_fd!(path, flag | O_CLOEXEC)?);
|
||||||
|
|
||||||
let st = f.metadata()?;
|
let attr = FsPath::from(path).get_attr()?;
|
||||||
let sz = if st.file_type().is_block_device() {
|
let sz = if attr.is_block_device() {
|
||||||
let mut sz = 0_u64;
|
let mut sz = 0_u64;
|
||||||
unsafe { ioctl(f.as_raw_fd(), BLKGETSIZE64, &mut sz) }.as_os_err()?;
|
unsafe { ioctl(f.as_raw_fd(), BLKGETSIZE64, &mut sz) }.as_os_err()?;
|
||||||
sz
|
sz
|
||||||
} else {
|
} else {
|
||||||
st.st_size()
|
attr.st.st_size as u64
|
||||||
};
|
};
|
||||||
|
|
||||||
map_fd(f.as_fd(), sz as usize, rw)
|
map_fd(f.as_fd(), sz as usize, rw)
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::fs::{metadata, read, DirBuilder, File};
|
use std::fs::{DirBuilder, File};
|
||||||
use std::io::Write;
|
use std::io::{Read, Write};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::os::unix::fs::{symlink, DirBuilderExt, FileTypeExt, MetadataExt};
|
use std::os::unix::fs::{symlink, DirBuilderExt};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::str;
|
use std::str;
|
||||||
@ -15,16 +15,17 @@ use bytemuck::{from_bytes, Pod, Zeroable};
|
|||||||
use num_traits::cast::AsPrimitive;
|
use num_traits::cast::AsPrimitive;
|
||||||
use size::{Base, Size, Style};
|
use size::{Base, Size, Style};
|
||||||
|
|
||||||
use crate::ffi::{unxz, xz};
|
|
||||||
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, O_CLOEXEC, O_RDONLY,
|
||||||
S_IFLNK, S_IFMT, S_IFREG, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP,
|
S_IFBLK, S_IFCHR, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP,
|
||||||
S_IXOTH, S_IXUSR,
|
S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR,
|
||||||
};
|
};
|
||||||
use base::{
|
use base::{
|
||||||
log_err, map_args, EarlyExitExt, LoggedResult, MappedFile, ResultExt, Utf8CStr, WriteExt,
|
log_err, map_args, EarlyExitExt, FsPath, LoggedResult, MappedFile, ResultExt, Utf8CStr,
|
||||||
|
WriteExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::ffi::{unxz, xz};
|
||||||
use crate::ramdisk::MagiskCpio;
|
use crate::ramdisk::MagiskCpio;
|
||||||
|
|
||||||
#[derive(FromArgs)]
|
#[derive(FromArgs)]
|
||||||
@ -397,28 +398,35 @@ 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) -> LoggedResult<()> {
|
fn add(&mut self, mode: mode_t, path: &str, file: &mut String) -> LoggedResult<()> {
|
||||||
if path.ends_with('/') {
|
if path.ends_with('/') {
|
||||||
return Err(log_err!("path cannot end with / for add"));
|
return Err(log_err!("path cannot end with / for add"));
|
||||||
}
|
}
|
||||||
let file = Path::new(file);
|
let file = Utf8CStr::from_string(file);
|
||||||
let content = read(file)?;
|
let file = FsPath::from(&file);
|
||||||
let metadata = metadata(file)?;
|
let attr = file.get_attr()?;
|
||||||
let mut rdevmajor: dev_t = 0;
|
|
||||||
let mut rdevminor: dev_t = 0;
|
let mut content = Vec::<u8>::new();
|
||||||
let mode = if metadata.file_type().is_file() {
|
let rdevmajor: dev_t;
|
||||||
|
let rdevminor: dev_t;
|
||||||
|
|
||||||
|
let mode = if attr.is_file() {
|
||||||
|
rdevmajor = 0;
|
||||||
|
rdevminor = 0;
|
||||||
|
file.open(O_RDONLY | O_CLOEXEC)?.read_to_end(&mut content)?;
|
||||||
mode | S_IFREG
|
mode | S_IFREG
|
||||||
} else {
|
} else {
|
||||||
rdevmajor = unsafe { major(metadata.rdev().try_into()?).try_into()? };
|
rdevmajor = unsafe { major(attr.st.st_rdev.as_()) }.as_();
|
||||||
rdevminor = unsafe { minor(metadata.rdev().try_into()?).try_into()? };
|
rdevminor = unsafe { minor(attr.st.st_rdev.as_()) }.as_();
|
||||||
if metadata.file_type().is_block_device() {
|
if attr.is_block_device() {
|
||||||
mode | S_IFBLK
|
mode | S_IFBLK
|
||||||
} else if metadata.file_type().is_char_device() {
|
} else if attr.is_char_device() {
|
||||||
mode | S_IFCHR
|
mode | S_IFCHR
|
||||||
} else {
|
} else {
|
||||||
return Err(log_err!("unsupported file type"));
|
return Err(log_err!("unsupported file type"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.entries.insert(
|
self.entries.insert(
|
||||||
norm_path(path),
|
norm_path(path),
|
||||||
Box::new(CpioEntry {
|
Box::new(CpioEntry {
|
||||||
@ -611,7 +619,7 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
|
|||||||
CpioSubCommand::Move(Move { from, to }) => cpio.mv(from, to)?,
|
CpioSubCommand::Move(Move { from, to }) => cpio.mv(from, to)?,
|
||||||
CpioSubCommand::MakeDir(MakeDir { mode, dir }) => cpio.mkdir(mode, dir),
|
CpioSubCommand::MakeDir(MakeDir { mode, dir }) => cpio.mkdir(mode, dir),
|
||||||
CpioSubCommand::Link(Link { src, dst }) => cpio.ln(src, dst),
|
CpioSubCommand::Link(Link { src, dst }) => cpio.ln(src, dst),
|
||||||
CpioSubCommand::Add(Add { mode, path, file }) => cpio.add(mode, path, file)?,
|
CpioSubCommand::Add(Add { mode, path, file }) => cpio.add(*mode, path, file)?,
|
||||||
CpioSubCommand::Extract(Extract { paths }) => {
|
CpioSubCommand::Extract(Extract { paths }) => {
|
||||||
if !paths.is_empty() && paths.len() != 2 {
|
if !paths.is_empty() && paths.len() != 2 {
|
||||||
return Err(log_err!("invalid arguments"));
|
return Err(log_err!("invalid arguments"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user