diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java index feb22de94..77568ffb4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java @@ -197,7 +197,7 @@ public class MagiskFragment extends Fragment @Override public void onFinish() { progress.setMessage(getString(R.string.reboot_countdown, 0)); - magiskManager.rootShell.su( + magiskManager.rootShell.su_raw( "mv -f " + uninstaller + " /cache/" + MagiskManager.UNINSTALLER, "mv -f " + utils + " /data/magisk/" + MagiskManager.UTIL_FUNCTIONS, "reboot" diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java index 1976900b2..081bf14d5 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java @@ -154,7 +154,7 @@ public class MagiskLogFragment extends Fragment { return ""; case 1: - magiskManager.rootShell.su("echo > " + MAGISK_LOG); + magiskManager.rootShell.su_raw("echo > " + MAGISK_LOG); SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show(); return ""; diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java b/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java index e1d943b0a..d41a0dee8 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java @@ -125,7 +125,7 @@ public class MagiskManager extends Application { File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox"); if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) { busybox.getParentFile().mkdirs(); - rootShell.su( + rootShell.su_raw( "cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox, "chmod -R 755 " + busybox.getParent(), busybox + " --install -s " + busybox.getParent() @@ -148,7 +148,7 @@ public class MagiskManager extends Application { .putString("busybox_version", BUSYBOX_VERSION) .apply(); // Add busybox to PATH - rootShell.su("PATH=$PATH:" + busybox.getParent()); + rootShell.su_raw("PATH=$PATH:" + busybox.getParent()); // Create notification channel on Android O if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { diff --git a/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java b/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java index ea4473b9e..8f1726fb9 100644 --- a/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java @@ -175,11 +175,11 @@ public class SettingsActivity extends Activity { case "hosts": enabled = prefs.getBoolean("hosts", false); if (enabled) { - magiskManager.rootShell.su( + magiskManager.rootShell.su_raw( "cp -af /system/etc/hosts /magisk/.core/hosts", "mount -o bind /magisk/.core/hosts /system/etc/hosts"); } else { - magiskManager.rootShell.su( + magiskManager.rootShell.su_raw( "umount -l /system/etc/hosts", "rm -f /magisk/.core/hosts"); } diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java index fce6d2855..c7fa300ff 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java @@ -75,7 +75,7 @@ public class FlashZip extends ParallelTask { } private int cleanup(int ret) { - magiskManager.rootShell.su( + magiskManager.rootShell.su_raw( "rm -rf " + mCachedFile.getParent() + "/*", "rm -rf " + MagiskManager.TMP_FOLDER_PATH ); @@ -146,7 +146,7 @@ public class FlashZip extends ParallelTask { new AlertDialogBuilder(activity) .setTitle(R.string.reboot_title) .setMessage(R.string.reboot_msg) - .setPositiveButton(R.string.reboot, (dialogInterface, i) -> magiskManager.rootShell.su("reboot")) + .setPositiveButton(R.string.reboot, (dialogInterface, i) -> magiskManager.rootShell.su_raw("reboot")) .setNegativeButton(R.string.no_thanks, null) .show(); } diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/ProcessMagiskZip.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/ProcessMagiskZip.java index bdecbe9e5..39820e031 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/ProcessMagiskZip.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/ProcessMagiskZip.java @@ -33,7 +33,7 @@ public class ProcessMagiskZip extends ParallelTask { @Override protected Boolean doInBackground(Void... params) { if (Shell.rootAccess()) { - magiskManager.rootShell.su("rm -f /dev/.magisk", + magiskManager.rootShell.su_raw("rm -f /dev/.magisk", (mBoot != null) ? "echo \"BOOTIMAGE=" + mBoot + "\" >> /dev/.magisk" : "", "echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk", "echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk" diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Shell.java b/app/src/main/java/com/topjohnwu/magisk/utils/Shell.java index 29435b729..1aa3fe995 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Shell.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Shell.java @@ -18,12 +18,12 @@ public class Shell { // -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted public static int rootStatus; - private static boolean isInit = false; - private final Process rootShell; private final DataOutputStream rootSTDIN; private final DataInputStream rootSTDOUT; + private boolean isValid; + private Shell() { Process process; try { @@ -34,15 +34,17 @@ public class Shell { rootShell = null; rootSTDIN = null; rootSTDOUT = null; + isValid = false; return; } rootStatus = 1; + isValid = true; rootShell = process; rootSTDIN = new DataOutputStream(rootShell.getOutputStream()); rootSTDOUT = new DataInputStream(rootShell.getInputStream()); - su("umask 022"); + su_raw("umask 022"); List ret = su("echo -BOC-", "id"); if (ret.isEmpty()) { @@ -118,33 +120,43 @@ public class Shell { } public List su(String... commands) { + if (!isValid) return null; List res = new ArrayList<>(); su(res, commands); return res; } - public void su(List res, String... commands) { - try { - rootShell.exitValue(); - return; // The process is dead, return - } catch (IllegalThreadStateException ignored) { - // This should be the expected result - } + public void su_raw(String... commands) { + if (!isValid) return; synchronized (rootShell) { - StreamGobbler STDOUT = new StreamGobbler(rootSTDOUT, Collections.synchronizedList(res), true); - STDOUT.start(); try { for (String command : commands) { rootSTDIN.write((command + "\n").getBytes("UTF-8")); rootSTDIN.flush(); } - rootSTDIN.write(("echo \'-root-done-\'\n").getBytes("UTF-8")); - rootSTDIN.flush(); - STDOUT.join(); - } catch (InterruptedException | IOException e) { + } catch (IOException e) { e.printStackTrace(); rootShell.destroy(); + isValid = false; } } } + + public void su(List output, String... commands) { + if (!isValid) return; + try { + rootShell.exitValue(); + isValid = false; + return; // The process is dead, return + } catch (IllegalThreadStateException ignored) { + // This should be the expected result + } + synchronized (rootShell) { + StreamGobbler STDOUT = new StreamGobbler(rootSTDOUT, output, true); + STDOUT.start(); + su_raw(commands); + su_raw("echo \'-root-done-\'"); + try { STDOUT.join(); } catch (InterruptedException ignored) {} + } + } } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/StreamGobbler.java b/app/src/main/java/com/topjohnwu/magisk/utils/StreamGobbler.java index 479d53850..e4178f8ad 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/StreamGobbler.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/StreamGobbler.java @@ -29,13 +29,17 @@ public class StreamGobbler extends Thread { * @param outputList {@literal List} to write to, or null */ public StreamGobbler(InputStream inputStream, List outputList) { + try { + while (inputStream.available() != 0) { + inputStream.skip(inputStream.available()); + } + } catch (IOException ignored) {} reader = new BufferedReader(new InputStreamReader(inputStream)); writer = outputList; } public StreamGobbler(InputStream inputStream, List outputList, boolean root) { - reader = new BufferedReader(new InputStreamReader(inputStream)); - writer = outputList; + this(inputStream, outputList); isRoot = root; } @@ -48,7 +52,7 @@ public class StreamGobbler extends Thread { if (TextUtils.equals(line, "-root-done-")) return; writer.add(line); - Logger.shell(isRoot, "OUT: " + line); + Logger.shell(isRoot, line); } } catch (IOException e) { // reader probably closed, expected exit condition diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 19d985d2c..44338b488 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -52,12 +52,12 @@ public class Utils { public static void createFile(Shell shell, String path) { String folder = path.substring(0, path.lastIndexOf('/')); String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null; if [ -f \"" + path + "\" ]; then echo true; else echo false; fi"; - shell.su(command); + shell.su_raw(command); } public static void removeItem(Shell shell, String path) { String command = "rm -rf " + path + " 2>/dev/null; if [ -e " + path + " ]; then echo false; else echo true; fi"; - shell.su(command); + shell.su_raw(command); } public static List getModList(Shell shell, String path) { @@ -66,14 +66,8 @@ public class Utils { } public static List readFile(Shell shell, String path) { - List ret; String command = "cat " + path; - if (Shell.rootAccess()) { - ret = shell.su(command); - } else { - ret = Shell.sh(command); - } - return ret; + return shell.su(command); } public static void dlAndReceive(Context context, DownloadReceiver receiver, String link, String filename) {