Use symlink to setup preinit

This commit is contained in:
LoveSy 2024-07-17 23:03:37 +08:00 committed by John Wu
parent 2754b1dcf8
commit 0869a90fe3

View File

@ -49,16 +49,13 @@ pub fn setup_mounts() {
let preinit_dir = Utf8CStr::from_string(&mut preinit_dir); let preinit_dir = Utf8CStr::from_string(&mut preinit_dir);
let r: LoggedResult<()> = try { let r: LoggedResult<()> = try {
FsPath::from(preinit_dir).mkdir(0o700)?; FsPath::from(preinit_dir).mkdir(0o700)?;
mnt_path.mkdirs(0o755)?; let mut buf = Utf8CStrBufArr::default();
if mnt_path.parent(&mut buf) {
FsPath::from(&buf).mkdirs(0o755)?;
}
mnt_path.remove().ok();
unsafe { unsafe {
libc::mount( libc::symlink(preinit_dir.as_ptr(), mnt_path.as_ptr()).as_os_err()?
preinit_dir.as_ptr(),
mnt_path.as_ptr(),
ptr::null(),
libc::MS_BIND,
ptr::null(),
)
.as_os_err()?
} }
}; };
if r.is_ok() { if r.is_ok() {
@ -134,14 +131,12 @@ pub fn setup_mounts() {
} }
// when partitions have the same fs type, the order is: // when partitions have the same fs type, the order is:
// - preinit: it's selected previously, so it's always the first
// - data: it has sufficient space and can be safely written // - data: it has sufficient space and can be safely written
// - cache: size is limited, but still can be safely written // - cache: size is limited, but still can be safely written
// - metadata: size is limited, and it might cause unexpected behavior if written // - metadata: size is limited, and it might cause unexpected behavior if written
// - persist: it's the last resort, as it's dangerous to write to it // - persist: it's the last resort, as it's dangerous to write to it
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(PartialEq, Eq, PartialOrd, Ord)]
enum PartId { enum PartId {
PreInit,
Data, Data,
Cache, Cache,
Metadata, Metadata,
@ -165,16 +160,10 @@ pub fn find_preinit_device() -> String {
} else { } else {
EncryptType::File EncryptType::File
}; };
let mount = unsafe { libc::getuid() } == 0 && std::env::var("MAGISKTMP").is_ok();
let make_dev = mount && std::env::var_os("MAKEDEV").is_some();
let mut matched_info = parse_mount_info("self") let mut matched_info = parse_mount_info("self")
.into_iter() .into_iter()
.filter_map(|info| { .filter_map(|info| {
// if preinit is already mounted, choose it unconditionally
if info.target.ends_with(PREINITMIRR) {
return Some((PartId::PreInit, info));
}
if info.root != "/" || !info.source.starts_with('/') || info.source.contains("/dm-") { if info.root != "/" || !info.source.starts_with('/') || info.source.contains("/dm-") {
return None; return None;
} }
@ -222,47 +211,45 @@ pub fn find_preinit_device() -> String {
_ => ap.cmp(bp), _ => ap.cmp(bp),
}, },
); );
let preinit_source = match preinit_info { let info = &preinit_info.1;
(PartId::PreInit, info) => &info.source, let mut target = info.target.clone();
(_, info) => { let mut preinit_dir = resolve_preinit_dir(Utf8CStr::from_string(&mut target));
let mut target = info.target.clone(); if unsafe { libc::getuid() } == 0
let mut preinit_dir = resolve_preinit_dir(Utf8CStr::from_string(&mut target)); && let Ok(tmp) = std::env::var("MAGISKTMP")
if mount && let Ok(tmp) = std::env::var("MAGISKTMP") { && !tmp.is_empty()
let mut buf = Utf8CStrBufArr::default(); {
let mirror_dir = FsPathBuf::new(&mut buf).join(&tmp).join(PREINITMIRR); let mut buf = Utf8CStrBufArr::default();
let preinit_dir = FsPath::from(Utf8CStr::from_string(&mut preinit_dir)); let mirror_dir = FsPathBuf::new(&mut buf).join(&tmp).join(PREINITMIRR);
let _: LoggedResult<()> = try { let preinit_dir = FsPath::from(Utf8CStr::from_string(&mut preinit_dir));
preinit_dir.mkdirs(0o700)?; let _: LoggedResult<()> = try {
mirror_dir.mkdirs(0o700)?; preinit_dir.mkdirs(0o700)?;
unsafe { let mut buf = Utf8CStrBufArr::default();
libc::mount( if mirror_dir.parent(&mut buf) {
preinit_dir.as_ptr(), FsPath::from(&buf).mkdirs(0o755)?;
mirror_dir.as_ptr(), }
ptr::null(), mirror_dir.remove().ok();
libc::MS_BIND, unsafe {
ptr::null(), libc::umount2(mirror_dir.as_ptr(), libc::MNT_DETACH)
) .as_os_err()
.as_os_err()?; .ok(); // ignore error
} libc::symlink(preinit_dir.as_ptr(), mirror_dir.as_ptr()).as_os_err()?;
}; }
if make_dev { };
let dev_path = FsPathBuf::new(&mut buf).join(&tmp).join(PREINITDEV); if std::env::var_os("MAKEDEV").is_some() {
unsafe { let dev_path = FsPathBuf::new(&mut buf).join(&tmp).join(PREINITDEV);
libc::mknod( unsafe {
dev_path.as_ptr(), libc::mknod(
libc::S_IFBLK | 0o600, dev_path.as_ptr(),
info.device as dev_t, libc::S_IFBLK | 0o600,
) info.device as dev_t,
.as_os_err() )
.log() .as_os_err()
.ok(); .log()
} .ok();
}
} }
&info.source
} }
}; }
Path::new(&preinit_source) Path::new(&info.source)
.file_name() .file_name()
.unwrap() .unwrap()
.to_str() .to_str()