From 71cb86c2e9a9e1e9c323cf06dd287e8a69616904 Mon Sep 17 00:00:00 2001 From: powellnorma <101364699+powellnorma@users.noreply.github.com> Date: Thu, 16 May 2024 04:30:20 +0200 Subject: [PATCH] ksud: refine get_tmp_path (#1713) Fixes #1710 What do you think? * It first uses `TEMP_DIR` (`/debug_ramdisk`) if it exists + is is empty. * Otherwise it tries to create a random directory in `/dev`. * If that fails, it goes through a list of directories (including `TEMP_DIR_LEGACY`), and chooses the first one that is empty. * If no empty directory it chooses the first one that exists --------- Co-authored-by: user --- userspace/ksud/src/utils.rs | 69 ++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/userspace/ksud/src/utils.rs b/userspace/ksud/src/utils.rs index 5abd6a4b..06b529d1 100644 --- a/userspace/ksud/src/utils.rs +++ b/userspace/ksud/src/utils.rs @@ -1,12 +1,13 @@ use anyhow::{bail, Context, Error, Ok, Result}; use std::{ - fs::{create_dir_all, remove_file, write, File, OpenOptions}, + fs::{self, create_dir_all, remove_file, write, File, OpenOptions}, io::{ ErrorKind::{AlreadyExists, NotFound}, Write, }, path::Path, process::Command, + sync::OnceLock, }; use crate::{assets, boot_patch, defs, ksucalls, module, restorecon}; @@ -188,14 +189,66 @@ pub fn has_magisk() -> bool { which::which("magisk").is_ok() } +fn is_ok_empty(dir: &str) -> bool { + use std::result::Result::{Err, Ok}; + + match fs::read_dir(dir) { + Ok(mut entries) => entries.next().is_none(), + Err(_) => false, + } +} + +fn find_temp_path() -> String { + use std::result::Result::{Err, Ok}; + + if is_ok_empty(defs::TEMP_DIR) { + return defs::TEMP_DIR.to_string(); + } + + // Try to create a random directory in /dev/ + let r = tempdir::TempDir::new_in("/dev/", ""); + match r { + Ok(tmp_dir) => { + if let Some(path) = tmp_dir.into_path().to_str() { + return path.to_string(); + } + } + Err(_e) => {} + } + + let dirs = [ + defs::TEMP_DIR, + "/patch_hw", + "/oem", + "/root", + defs::TEMP_DIR_LEGACY, + ]; + + // find empty directory + for dir in dirs { + if is_ok_empty(dir) { + return dir.to_string(); + } + } + + // Fallback to non-empty directory + for dir in dirs { + if metadata(dir).is_ok() { + return dir.to_string(); + } + } + + "".to_string() +} + pub fn get_tmp_path() -> &'static str { - if metadata(defs::TEMP_DIR_LEGACY).is_ok() { - return defs::TEMP_DIR_LEGACY; - } - if metadata(defs::TEMP_DIR).is_ok() { - return defs::TEMP_DIR; - } - "" + static CHOSEN_TMP_PATH: OnceLock = OnceLock::new(); + + CHOSEN_TMP_PATH.get_or_init(|| { + let r = find_temp_path(); + log::info!("Chosen temp_path: {}", r); + r + }) } #[cfg(target_os = "android")]