diff --git a/build.gradle b/build.gradle index da17920b4..9b417c9fa 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ android { applicationId "com.topjohnwu.magisk" minSdkVersion 21 targetSdkVersion 27 - versionCode 94 + versionCode 96 versionName "5.5.5" javaCompileOptions { annotationProcessorOptions { @@ -46,7 +46,7 @@ repositories { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation project(':utils') - implementation 'com.github.topjohnwu:libsu:1.0.1' + implementation 'com.github.topjohnwu:libsu:1.1.0' implementation 'com.android.support:recyclerview-v7:27.0.2' implementation 'com.android.support:cardview-v7:27.0.2' implementation 'com.android.support:design:27.0.2' diff --git a/src/main/assets/changelog.md b/src/main/assets/changelog.md index 10ae4b44b..2d157d1e9 100644 --- a/src/main/assets/changelog.md +++ b/src/main/assets/changelog.md @@ -1,4 +1,3 @@ -### v5.5.5 (93) +### v5.5.5 (96) - Remove JNI requirement, Magisk Manager is now pure Java -- Update the method to handle global su database (v15+), should fix root request not saving issue -on many devices +- Update the method handling su database (v15+), may fix the issue that root requests won't save diff --git a/src/main/java/com/topjohnwu/magisk/MagiskManager.java b/src/main/java/com/topjohnwu/magisk/MagiskManager.java index 366fb07f1..bf6af5725 100644 --- a/src/main/java/com/topjohnwu/magisk/MagiskManager.java +++ b/src/main/java/com/topjohnwu/magisk/MagiskManager.java @@ -8,6 +8,7 @@ import android.content.res.Resources; import android.os.Handler; import android.preference.PreferenceManager; import android.support.annotation.NonNull; +import android.text.TextUtils; import android.widget.Toast; import com.topjohnwu.magisk.container.Module; @@ -16,8 +17,10 @@ import com.topjohnwu.magisk.database.SuDatabaseHelper; import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.magisk.utils.Utils; +import com.topjohnwu.superuser.BusyBox; import com.topjohnwu.superuser.Shell; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; @@ -86,26 +89,28 @@ public class MagiskManager extends Shell.ContainerApp { public MagiskManager() { weakSelf = new WeakReference<>(this); - Shell.setFlags(Shell.FLAG_MOUNT_MASTER); - Shell.setInitializer(new Shell.Initializer() { - @Override - public void onRootShellInit(@NonNull Shell shell) { - try (InputStream in = MagiskManager.get().getAssets().open(Const.UTIL_FUNCTIONS)) { - shell.loadInputStream(null, null, in); - } catch (IOException e) { - e.printStackTrace(); - } - shell.run(null, null, - "export PATH=" + Const.BUSYBOX_PATH + ":$PATH", - "mount_partitions", - "run_migrations"); - } - }); } @Override public void onCreate() { super.onCreate(); + + Shell.setFlags(Shell.FLAG_MOUNT_MASTER); + BusyBox.BB_PATH = new File(Const.BUSYBOX_PATH); + Shell.setInitializer(new Shell.Initializer() { + @Override + public void onRootShellInit(@NonNull Shell shell) { + try (InputStream in = MagiskManager.get().getAssets().open(Const.UTIL_FUNCTIONS)) { + shell.loadInputStream(null, null, in); + } catch (IOException e) { + e.printStackTrace(); + } + shell.run(null, null, + "mount_partitions", + "run_migrations"); + } + }); + prefs = PreferenceManager.getDefaultSharedPreferences(this); // Handle duplicate package @@ -163,8 +168,8 @@ public class MagiskManager extends Shell.ContainerApp { prefs.edit() .putBoolean(Const.Key.DARK_THEME, isDarkTheme) .putBoolean(Const.Key.MAGISKHIDE, magiskHide) - .putBoolean(Const.Key.HOSTS, Utils.itemExist(Const.MAGISK_HOST_FILE())) - .putBoolean(Const.Key.COREONLY, Utils.itemExist(Const.MAGISK_DISABLE_FILE)) + .putBoolean(Const.Key.HOSTS, Const.MAGISK_HOST_FILE().exists()) + .putBoolean(Const.Key.COREONLY, Const.MAGISK_DISABLE_FILE.exists()) .putString(Const.Key.SU_REQUEST_TIMEOUT, String.valueOf(suRequestTimeout)) .putString(Const.Key.SU_AUTO_RESPONSE, String.valueOf(suResponseType)) .putString(Const.Key.SU_NOTIFICATION, String.valueOf(suNotificationType)) @@ -188,64 +193,22 @@ public class MagiskManager extends Shell.ContainerApp { } public void loadMagiskInfo() { - List ret; - ret = Shell.Sync.sh("magisk -v"); - if (!Utils.isValidShellResponse(ret)) { - ret = Shell.Sync.sh("getprop magisk.version"); - if (Utils.isValidShellResponse(ret)) { - try { - magiskVersionString = ret.get(0); - magiskVersionCode = (int) Double.parseDouble(ret.get(0)) * 10; - } catch (NumberFormatException ignored) {} - } - } else { - magiskVersionString = ret.get(0).split(":")[0]; - ret = Shell.Sync.sh("magisk -V"); - try { - magiskVersionCode = Integer.parseInt(ret.get(0)); - } catch (NumberFormatException ignored) {} - } - if (magiskVersionCode > 1435) { - ret = Shell.Sync.su("resetprop -p " + Const.MAGISKHIDE_PROP); - } else { - ret = Shell.Sync.sh("getprop " + Const.MAGISKHIDE_PROP); - } try { - magiskHide = !Utils.isValidShellResponse(ret) || Integer.parseInt(ret.get(0)) != 0; - } catch (NumberFormatException e) { - magiskHide = true; - } + magiskVersionString = Utils.cmd("magisk -v").split(":")[0]; + magiskVersionCode = Integer.parseInt(Utils.cmd("magisk -V")); + String s = Utils.cmd((magiskVersionCode > 1435 ? "resetprop -p " : "getprop ") + Const.MAGISKHIDE_PROP); + magiskHide = s == null || Integer.parseInt(s) != 0; + } catch (Exception ignored) {} - ret = Shell.Sync.su("echo \"$BOOTIMAGE\""); - if (Utils.isValidShellResponse(ret)) - bootBlock = ret.get(0); + bootBlock = Utils.cmd("echo \"$BOOTIMAGE\""); } public void getDefaultInstallFlags() { - List ret; - ret = Shell.Sync.su("echo \"$DTBOIMAGE\""); - if (Utils.isValidShellResponse(ret)) - keepVerity = true; + keepVerity = Boolean.parseBoolean(Utils.cmd("getvar KEEPVERITY; echo $KEEPVERITY")) || + Utils.cmd("echo \"$DTBOIMAGE\"") != null; - ret = Shell.Sync.su( - "getvar KEEPVERITY", - "echo $KEEPVERITY"); - try { - if (Utils.isValidShellResponse(ret)) - keepVerity = Boolean.parseBoolean(ret.get(0)); - } catch (NumberFormatException ignored) {} - - ret = Shell.Sync.sh("getprop ro.crypto.state"); - if (Utils.isValidShellResponse(ret) && ret.get(0).equals("encrypted")) - keepEnc = true; - - ret = Shell.Sync.su( - "getvar KEEPFORCEENCRYPT", - "echo $KEEPFORCEENCRYPT"); - try { - if (Utils.isValidShellResponse(ret)) - keepEnc = Boolean.parseBoolean(ret.get(0)); - } catch (NumberFormatException ignored) {} + keepEnc = Boolean.parseBoolean(Utils.cmd("getvar KEEPFORCEENCRYPT; echo $KEEPFORCEENCRYPT")) || + TextUtils.equals("encrypted", Utils.cmd("getprop ro.crypto.state")); } public void setPermissionGrantCallback(Runnable callback) { diff --git a/src/main/java/com/topjohnwu/magisk/SettingsActivity.java b/src/main/java/com/topjohnwu/magisk/SettingsActivity.java index 5599d2308..6b4c15b94 100644 --- a/src/main/java/com/topjohnwu/magisk/SettingsActivity.java +++ b/src/main/java/com/topjohnwu/magisk/SettingsActivity.java @@ -27,6 +27,7 @@ import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.superuser.Shell; +import java.io.IOException; import java.util.Locale; import butterknife.BindView; @@ -223,9 +224,11 @@ public class SettingsActivity extends Activity implements Topic.Subscriber { break; case Const.Key.COREONLY: if (prefs.getBoolean(key, false)) { - Utils.createFile(Const.MAGISK_DISABLE_FILE); + try { + Const.MAGISK_DISABLE_FILE.createNewFile(); + } catch (IOException ignored) {} } else { - Utils.removeItem(Const.MAGISK_DISABLE_FILE); + Const.MAGISK_DISABLE_FILE.delete(); } Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show(); break; diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/CheckSafetyNet.java b/src/main/java/com/topjohnwu/magisk/asyncs/CheckSafetyNet.java index 376f5e97d..8899755b5 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/CheckSafetyNet.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/CheckSafetyNet.java @@ -4,9 +4,9 @@ import android.app.Activity; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.utils.Const; -import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.WebService; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.superuser.ShellUtils; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -38,7 +38,7 @@ public class CheckSafetyNet extends ParallelTask { try ( OutputStream out = new BufferedOutputStream(new FileOutputStream(dexPath)); InputStream in = new BufferedInputStream(conn.getInputStream())) { - Utils.inToOut(in, out); + ShellUtils.pump(in, out); } conn.disconnect(); } diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java b/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java index 707876e6b..dbee3e03d 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java @@ -11,6 +11,7 @@ import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.ZipUtils; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.superuser.ShellUtils; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -38,8 +39,8 @@ public class FlashZip extends ParallelTask { private boolean unzipAndCheck() throws Exception { ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android", true); - List ret = Utils.readFile(new File(mCachedFile.getParentFile(), "updater-script")); - return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK"); + String s = Utils.cmd("head -n 1 " + new File(mCachedFile.getParentFile(), "updater-script")); + return s != null && s.contains("#MAGISK"); } @Override @@ -55,7 +56,7 @@ public class FlashZip extends ParallelTask { ) { if (in == null) throw new FileNotFoundException(); InputStream buf= new BufferedInputStream(in); - Utils.inToOut(buf, out); + ShellUtils.pump(buf, out); } catch (FileNotFoundException e) { console.add("! Invalid Uri"); throw e; @@ -65,7 +66,7 @@ public class FlashZip extends ParallelTask { } if (!unzipAndCheck()) return 0; console.add("- Installing " + Utils.getNameFromUri(mm, mUri)); - Shell.getShell().run(console, logs, + Shell.Sync.su(console, logs, "cd " + mCachedFile.getParent(), "BOOTMODE=true sh update-binary dummy 1 " + mCachedFile + " || echo 'Failed!'" ); diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java b/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java index 262a4ae93..5ac8939d0 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java @@ -10,12 +10,12 @@ import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.ZipUtils; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.superuser.ShellUtils; import com.topjohnwu.utils.JarMap; import java.io.File; import java.io.FileInputStream; import java.security.SecureRandom; -import java.util.List; import java.util.jar.JarEntry; public class HideManager extends ParallelTask { @@ -130,12 +130,11 @@ public class HideManager extends ParallelTask { } // Install the application - - List ret = Shell.Sync.su(Utils.fmt("pm install %s >/dev/null && echo true || echo false", repack)); - repack.delete(); - if (!Utils.isValidShellResponse(ret) || !Boolean.parseBoolean(ret.get(0))) + if (ShellUtils.fastCmdResult(Shell.getShell(), "pm install " + repack)) return false; + repack.delete(); + mm.suDB.setStrings(Const.Key.SU_REQUESTER, pkg); Utils.dumpPrefs(); Utils.uninstallPkg(Const.ORIG_PKG_NAME); diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java b/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java index 8a0d6d7af..e1d8555eb 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java @@ -1,7 +1,6 @@ package com.topjohnwu.magisk.asyncs; import android.app.Activity; -import android.content.res.AssetManager; import android.net.Uri; import android.os.Build; import android.text.TextUtils; @@ -14,6 +13,9 @@ import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.ZipUtils; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.superuser.ShellUtils; +import com.topjohnwu.superuser.io.SuFile; +import com.topjohnwu.superuser.io.SuFileInputStream; import com.topjohnwu.utils.SignBoot; import org.kamranzafar.jtar.TarInputStream; @@ -28,7 +30,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -70,7 +71,7 @@ public class InstallMagisk extends ParallelTask { mm.createDeviceProtectedStorageContext() : mm).getFilesDir().getParent() , "install"); - Shell.Async.sh("rm -rf " + install); + Shell.Sync.sh("rm -rf " + install); List abis = Arrays.asList(Build.SUPPORTED_ABIS); String arch; @@ -108,11 +109,9 @@ public class InstallMagisk extends ParallelTask { boolean highCompression = false; switch (mode) { case PATCH_MODE: - console.add("- Use boot/ramdisk image: " + boot); // Copy boot image to local - try ( - InputStream in = mm.getContentResolver().openInputStream(mBootImg); - OutputStream out = new FileOutputStream(boot) + try (InputStream in = mm.getContentResolver().openInputStream(mBootImg); + OutputStream out = new FileOutputStream(boot) ) { InputStream source; if (in == null) throw new FileNotFoundException(); @@ -130,7 +129,7 @@ public class InstallMagisk extends ParallelTask { // Direct copy raw image source = new BufferedInputStream(in); } - Utils.inToOut(source, out); + ShellUtils.pump(source, out); } catch (FileNotFoundException e) { console.add("! Invalid Uri"); throw e; @@ -140,18 +139,13 @@ public class InstallMagisk extends ParallelTask { } break; case DIRECT_MODE: - console.add("- Use boot/ramdisk image: " + mBootLocation); + console.add("- Patch boot/ramdisk image: " + mBootLocation); if (mm.remoteMagiskVersionCode >= 1463) { - List ret = new ArrayList<>(); - Shell.getShell().run(ret, logs, - install + "/magiskboot --parse " + mBootLocation, - "echo $?" - ); - if (Utils.isValidShellResponse(ret)) { - highCompression = Integer.parseInt(ret.get(ret.size() - 1)) == 2; - if (highCompression) - console.add("! Insufficient boot partition size detected"); - } + highCompression = Integer.parseInt(Utils.cmd(Utils.fmt( + "%s/magiskboot --parse %s; echo $?", + install, mBootLocation))) == 2; + if (highCompression) + console.add("! Insufficient boot partition size detected"); } if (boot.createNewFile()) { Shell.Sync.su("cat " + mBootLocation + " > " + boot); @@ -175,15 +169,8 @@ public class InstallMagisk extends ParallelTask { throw e; } - // Force non-root shell - Shell shell; - if (Shell.rootAccess()) - shell = Shell.newInstance("sh"); - else - shell = Shell.getShell(); - // Patch boot image - shell.run(console, logs, + Shell.Sync.sh(console, logs, "cd " + install, Utils.fmt("KEEPFORCEENCRYPT=%b KEEPVERITY=%b HIGHCOMP=%b " + "sh update-binary indep boot_patch.sh %s || echo 'Failed!'", @@ -192,24 +179,22 @@ public class InstallMagisk extends ParallelTask { if (TextUtils.equals(console.get(console.size() - 1), "Failed!")) return false; - shell.run(null, null, "mv -f new-boot.img ../", + Shell.Sync.sh("mv -f new-boot.img ../", "mv bin/busybox busybox", "rm -rf bin *.img update-binary", "cd /"); - File patched_boot = new File(install.getParent(), "new-boot.img"); + SuFile patched_boot = new SuFile(install.getParent(), "new-boot.img"); if (isSigned) { console.add("- Signing boot image with test keys"); File signed = new File(install.getParent(), "signed.img"); - AssetManager assets = mm.getAssets(); - try ( - InputStream in = new FileInputStream(patched_boot); - OutputStream out = new BufferedOutputStream(new FileOutputStream(signed)) + try (InputStream in = new SuFileInputStream(patched_boot); + OutputStream out = new BufferedOutputStream(new FileOutputStream(signed)) ) { SignBoot.doSignature("/boot", in, out, null, null); } - shell.run(null, null, "mv -f " + signed + " " + patched_boot); + Shell.Sync.sh("mv -f " + signed + " " + patched_boot); } switch (mode) { @@ -227,8 +212,8 @@ public class InstallMagisk extends ParallelTask { out = new BufferedOutputStream(new FileOutputStream(dest)); break; } - try (InputStream in = new BufferedInputStream(new FileInputStream(patched_boot))) { - Utils.inToOut(in, out); + try (InputStream in = new SuFileInputStream(patched_boot)) { + ShellUtils.pump(in, out); out.close(); } console.add(""); @@ -239,7 +224,7 @@ public class InstallMagisk extends ParallelTask { break; case DIRECT_MODE: String binPath = mm.remoteMagiskVersionCode >= 1464 ? "/data/adb/magisk" : "/data/magisk"; - Shell.getShell().run(console, logs, + Shell.Sync.su(console, logs, Utils.fmt("rm -rf %s/*; mkdir -p %s; chmod 700 /data/adb", binPath, binPath), Utils.fmt("cp -af %s/* %s; rm -rf %s", install, binPath, install), Utils.fmt("flash_boot_image %s %s", patched_boot, mBootLocation), diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/MarkDownWindow.java b/src/main/java/com/topjohnwu/magisk/asyncs/MarkDownWindow.java index d6b7c3ed3..ece1dbc05 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/MarkDownWindow.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/MarkDownWindow.java @@ -6,8 +6,8 @@ import android.webkit.WebView; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.WebService; +import com.topjohnwu.superuser.ShellUtils; import org.commonmark.node.Node; import org.commonmark.parser.Parser; @@ -44,7 +44,7 @@ public class MarkDownWindow extends ParallelTask { md = WebService.getString(mUrl); } else { try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - Utils.inToOut(is, out); + ShellUtils.pump(is, out); md = out.toString(); is.close(); } catch (IOException e) { @@ -57,7 +57,7 @@ public class MarkDownWindow extends ParallelTask { InputStream in = mm.getAssets().open(mm.isDarkTheme ? "dark.css" : "light.css"); ByteArrayOutputStream out = new ByteArrayOutputStream() ) { - Utils.inToOut(in, out); + ShellUtils.pump(in, out); css = out.toString(); } catch (IOException e) { e.printStackTrace(); diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java b/src/main/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java index 566e191c1..c98addf36 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java @@ -17,6 +17,7 @@ import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.WebService; import com.topjohnwu.magisk.utils.ZipUtils; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.superuser.ShellUtils; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -68,7 +69,7 @@ public class ProcessRepoZip extends ParallelTask { continue; } out.putNextEntry(new JarEntry(path)); - Utils.inToOut(in, out); + ShellUtils.pump(in, out); } } } @@ -107,7 +108,7 @@ public class ProcessRepoZip extends ParallelTask { InputStream in = new BufferedInputStream(new ProgressInputStream(conn.getInputStream())); OutputStream out = new BufferedOutputStream(new FileOutputStream(temp1)) ) { - Utils.inToOut(in, out); + ShellUtils.pump(in, out); in.close(); } conn.disconnect(); diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/RestoreImages.java b/src/main/java/com/topjohnwu/magisk/asyncs/RestoreImages.java index 972acc4b9..e70e3171f 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/RestoreImages.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/RestoreImages.java @@ -6,27 +6,22 @@ import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.superuser.Shell; - -import java.util.List; +import com.topjohnwu.superuser.ShellUtils; public class RestoreImages extends ParallelTask { @Override protected Boolean doInBackground(Void... voids) { String sha1; - List ret = Utils.readFile("/.backup/.sha1"); - if (Utils.isValidShellResponse(ret)) { - sha1 = ret.get(0); - } else { - ret = Shell.Sync.su("cat /init.magisk.rc | grep STOCKSHA1"); - if (!Utils.isValidShellResponse(ret)) + sha1 = Utils.cmd("cat /.backup/.sha1"); + if (sha1 == null) { + sha1 = Utils.cmd("cat /init.magisk.rc | grep STOCKSHA1"); + if (sha1 == null) return false; - sha1 = ret.get(0).substring(ret.get(0).indexOf('=') + 1); + sha1 = sha1.substring(sha1.indexOf('=') + 1); } - ret = Shell.Sync.su("restore_imgs " + sha1 + " && echo true || echo false"); - - return Utils.isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(ret.size() - 1)); + return ShellUtils.fastCmdResult(Shell.getShell(), "restore_imgs " + sha1); } @Override diff --git a/src/main/java/com/topjohnwu/magisk/container/Module.java b/src/main/java/com/topjohnwu/magisk/container/Module.java index c364f8461..59524bfdb 100644 --- a/src/main/java/com/topjohnwu/magisk/container/Module.java +++ b/src/main/java/com/topjohnwu/magisk/container/Module.java @@ -1,21 +1,24 @@ package com.topjohnwu.magisk.container; -import com.topjohnwu.magisk.utils.Utils; +import com.topjohnwu.superuser.Shell; +import com.topjohnwu.superuser.io.SuFile; + +import java.io.IOException; public class Module extends BaseModule { - private String mRemoveFile, mDisableFile, mUpdateFile; + private SuFile mRemoveFile, mDisableFile, mUpdateFile; private boolean mEnable, mRemove, mUpdated; public Module(String path) { try { - parseProps(Utils.readFile(path + "/module.prop")); + parseProps(Shell.Sync.su("cat " + path + "/module.prop")); } catch (NumberFormatException ignored) {} - mRemoveFile = path + "/remove"; - mDisableFile = path + "/disable"; - mUpdateFile = path + "/update"; + mRemoveFile = new SuFile(path + "/remove", true); + mDisableFile = new SuFile(path + "/disable", true); + mUpdateFile = new SuFile(path + "/update", true); if (getId() == null) { int sep = path.lastIndexOf('/'); @@ -26,19 +29,21 @@ public class Module extends BaseModule { setName(getId()); } - mEnable = !Utils.itemExist(mDisableFile); - mRemove = Utils.itemExist(mRemoveFile); - mUpdated = Utils.itemExist(mUpdateFile); + mEnable = !mDisableFile.exists(); + mRemove = mRemoveFile.exists(); + mUpdated = mUpdateFile.exists(); } public void createDisableFile() { mEnable = false; - Utils.createFile(mDisableFile); + try { + mDisableFile.createNewFile(); + } catch (IOException ignored) {} } public void removeDisableFile() { mEnable = true; - Utils.removeItem(mDisableFile); + mDisableFile.delete(); } public boolean isEnabled() { @@ -47,12 +52,14 @@ public class Module extends BaseModule { public void createRemoveFile() { mRemove = true; - Utils.createFile(mRemoveFile); + try { + mRemoveFile.createNewFile(); + } catch (IOException ignored) {} } public void deleteRemoveFile() { mRemove = false; - Utils.removeItem(mRemoveFile); + mRemoveFile.delete(); } public boolean willBeRemoved() { diff --git a/src/main/java/com/topjohnwu/magisk/utils/Const.java b/src/main/java/com/topjohnwu/magisk/utils/Const.java index 986747f2b..71362c2f2 100644 --- a/src/main/java/com/topjohnwu/magisk/utils/Const.java +++ b/src/main/java/com/topjohnwu/magisk/utils/Const.java @@ -4,6 +4,7 @@ import android.os.Environment; import android.os.Process; import com.topjohnwu.magisk.MagiskManager; +import com.topjohnwu.superuser.io.SuFile; import java.io.File; import java.util.Arrays; @@ -24,8 +25,8 @@ public class Const { public static final String SU_KEYSTORE_KEY = "su_key"; // Paths - private static String MAGISK_PATH = null; - public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk"; + private static SuFile MAGISK_PATH = null; + public static final SuFile MAGISK_DISABLE_FILE = new SuFile("/cache/.disable_magisk", true); public static final String BUSYBOX_PATH = "/sbin/.core/busybox"; public static final String TMP_FOLDER_PATH = "/dev/tmp"; public static final String MAGISK_LOG = "/cache/magisk.log"; @@ -37,21 +38,23 @@ public class Const { public static final int SNET_VER = 7; public static final int MIN_MODULE_VER = 1400; - public synchronized static String MAGISK_PATH() { + public synchronized static SuFile MAGISK_PATH() { + SuFile file; if (MAGISK_PATH == null) { - if (Utils.itemExist("/sbin/.core/img")) { - MAGISK_PATH = "/sbin/.core/img"; - } else if (Utils.itemExist("/dev/magisk/img")) { - MAGISK_PATH = "/dev/magisk/img"; + file = new SuFile("/sbin/.core/img", true); + if (file.exists()) { + MAGISK_PATH = file; + } else if ((file = new SuFile("/dev/magisk/img", true)).exists()) { + MAGISK_PATH = file; } else { - MAGISK_PATH = "/magisk"; + MAGISK_PATH = new SuFile("/magisk", true); } } return MAGISK_PATH; } - public static String MAGISK_HOST_FILE() { - return MAGISK_PATH() + "/.core/hosts"; + public static SuFile MAGISK_HOST_FILE() { + return new SuFile(MAGISK_PATH() + "/.core/hosts"); } /* A list of apps that should not be shown as hide-able */ diff --git a/src/main/java/com/topjohnwu/magisk/utils/ShowUI.java b/src/main/java/com/topjohnwu/magisk/utils/ShowUI.java index 004dfa78a..bb02d2a89 100644 --- a/src/main/java/com/topjohnwu/magisk/utils/ShowUI.java +++ b/src/main/java/com/topjohnwu/magisk/utils/ShowUI.java @@ -23,6 +23,7 @@ import com.topjohnwu.magisk.receivers.DownloadReceiver; import com.topjohnwu.magisk.receivers.ManagerUpdate; import com.topjohnwu.magisk.receivers.RebootReceiver; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.superuser.ShellUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -111,11 +112,11 @@ public class ShowUI { if (Shell.rootAccess()) { options.add(mm.getString(R.string.direct_install)); } - List res = Shell.Sync.su("echo $SLOT"); - if (Utils.isValidShellResponse(res)) { + String s = Utils.cmd("echo $SLOT"); + if (s != null) { options.add(mm.getString(R.string.install_second_slot)); } - char[] slot = Utils.isValidShellResponse(res) ? res.get(0).toCharArray() : null; + char[] slot = s == null ? null : s.toCharArray(); new AlertDialog.Builder(activity) .setTitle(R.string.select_method) .setItems( @@ -185,12 +186,11 @@ public class ShowUI { if (slot[1] == 'a') slot[1] = 'b'; else slot[1] = 'a'; // Then find the boot image again - List ret = Shell.Sync.su( - "SLOT=" + String.valueOf(slot), - "find_boot_image", + boot = Utils.cmd( + "SLOT=" + String.valueOf(slot) + + "; find_boot_image;" + "echo \"$BOOTIMAGE\"" ); - boot = Utils.isValidShellResponse(ret) ? ret.get(ret.size() - 1) : null; Shell.Async.su("mount_partitions"); if (boot == null) return; @@ -253,14 +253,14 @@ public class ShowUI { .setPositiveButton(R.string.complete_uninstall, (d, i) -> { ByteArrayOutputStream uninstaller = new ByteArrayOutputStream(); try (InputStream in = mm.getAssets().open(Const.UNINSTALLER)) { - Utils.inToOut(in, uninstaller); + ShellUtils.pump(in, uninstaller); } catch (IOException e) { e.printStackTrace(); return; } ByteArrayOutputStream utils = new ByteArrayOutputStream(); try (InputStream in = mm.getAssets().open(Const.UTIL_FUNCTIONS)) { - Utils.inToOut(in, utils); + ShellUtils.pump(in, utils); } catch (IOException e) { e.printStackTrace(); return; diff --git a/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 918ce60b4..9f6cb79c6 100644 --- a/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -19,7 +19,6 @@ import android.support.annotation.StringRes; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; -import android.text.TextUtils; import android.widget.Toast; import com.google.gson.Gson; @@ -31,11 +30,10 @@ import com.topjohnwu.magisk.components.SnackbarMaker; import com.topjohnwu.magisk.database.SuDatabaseHelper; import com.topjohnwu.magisk.receivers.DownloadReceiver; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.superuser.ShellUtils; +import com.topjohnwu.superuser.io.SuFile; import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -47,37 +45,8 @@ public class Utils { public static boolean isDownloading = false; - public static boolean itemExist(Object path) { - List ret = Shell.Sync.su(fmt("[ -e %s ] && echo true || echo false", path)); - return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0)); - } - - public static void createFile(Object path) { - Shell.Async.su(fmt("mkdir -p `dirname '%s'` 2>/dev/null; touch '%s' 2>/dev/null", path, path)); - } - - public static boolean javaCreateFile(File path) { - path.getParentFile().mkdirs(); - try { - path.createNewFile(); - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - - public static void removeItem(Object path) { - Shell.Async.su(fmt("rm -rf %s 2>/dev/null", path)); - } - - public static List readFile(Object path) { - return Shell.Sync.su(fmt("cat %s | sed '$a\\ ' | sed '$d'", path)); - } - - public static String checkInode(Object path) { - List ret = Shell.Sync.su(fmt("ls -i %s", path)); - return isValidShellResponse(ret) ? ret.get(0).trim().split("\\s+")[0] : path.toString(); + public static String cmd(String cmd) { + return ShellUtils.fastCmd(Shell.getShell(), cmd); } public static void uninstallPkg(String pkg) { @@ -118,16 +87,6 @@ public class Utils { .replace("\\", "_"); } - public static boolean isValidShellResponse(List list) { - if (list != null && list.size() != 0) { - // Check if all empty - for (String res : list) { - if (!TextUtils.isEmpty(res)) return true; - } - } - return false; - } - public static int getPrefsInt(SharedPreferences prefs, String key, int def) { return Integer.parseInt(prefs.getString(key, String.valueOf(def))); } @@ -230,14 +189,6 @@ public class Utils { } } - public static File getDB(String dbName) { - return getDB(MagiskManager.get(), dbName); - } - - public static File getDB(Context context, String dbName) { - return new File(context.getFilesDir().getParent() + "/databases", dbName); - } - public static AssetManager getAssets(String apk) { try { AssetManager asset = AssetManager.class.newInstance(); @@ -249,22 +200,10 @@ public class Utils { } } - public static int inToOut(InputStream in, OutputStream out) throws IOException { - int read, total = 0; - byte buffer[] = new byte[4096]; - while ((read = in.read(buffer)) > 0) { - out.write(buffer, 0, read); - total += read; - } - out.flush(); - return total; - } - public static void patchDTBO() { MagiskManager mm = MagiskManager.get(); if (mm.magiskVersionCode >= 1446 && !mm.keepVerity) { - List ret = Shell.Sync.su("patch_dtbo_image && echo true || echo false"); - if (Utils.isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(ret.size() - 1))) { + if (ShellUtils.fastCmdResult(Shell.getShell(), "patch_dtbo_image")) { ShowUI.dtboPatchedNotification(); } } @@ -285,9 +224,9 @@ public class Utils { } public static void loadPrefs() { - String config = fmt("/data/user/%d/%s", Const.USER_ID, Const.MANAGER_CONFIGS); - List ret = readFile(config); - if (isValidShellResponse(ret)) { + SuFile config = new SuFile(fmt("/data/user/%d/%s", Const.USER_ID, Const.MANAGER_CONFIGS), true); + List ret = Shell.Sync.su("cat " + config); + if (ShellUtils.isValidOutput(ret)) { SharedPreferences.Editor editor = MagiskManager.get().prefs.edit(); String json = ret.get(0); Gson gson = new Gson(); @@ -306,7 +245,7 @@ public class Utils { editor.remove(Const.Key.ETAG_KEY); editor.apply(); MagiskManager.get().loadConfig(); - removeItem(config); + config.delete(); } } diff --git a/src/main/java/com/topjohnwu/magisk/utils/ZipUtils.java b/src/main/java/com/topjohnwu/magisk/utils/ZipUtils.java index 61b41cbcf..628646e0a 100644 --- a/src/main/java/com/topjohnwu/magisk/utils/ZipUtils.java +++ b/src/main/java/com/topjohnwu/magisk/utils/ZipUtils.java @@ -1,5 +1,6 @@ package com.topjohnwu.magisk.utils; +import com.topjohnwu.superuser.ShellUtils; import com.topjohnwu.utils.JarMap; import com.topjohnwu.utils.SignAPK; @@ -39,7 +40,7 @@ public class ZipUtils { File dest = new File(folder, name); dest.getParentFile().mkdirs(); try (FileOutputStream out = new FileOutputStream(dest)) { - Utils.inToOut(zipfile, out); + ShellUtils.pump(zipfile, out); } } } catch(Exception e) {