Fix unable to patch images when app is hidden
This commit is contained in:
parent
f37e8f4ca8
commit
e7350d5041
@ -207,7 +207,7 @@ dependencies {
|
|||||||
implementation("io.noties.markwon:image:${vMarkwon}")
|
implementation("io.noties.markwon:image:${vMarkwon}")
|
||||||
implementation("com.caverock:androidsvg:1.4")
|
implementation("com.caverock:androidsvg:1.4")
|
||||||
|
|
||||||
val vLibsu = "3.1.0"
|
val vLibsu = "3.1.1"
|
||||||
implementation("com.github.topjohnwu.libsu:core:${vLibsu}")
|
implementation("com.github.topjohnwu.libsu:core:${vLibsu}")
|
||||||
implementation("com.github.topjohnwu.libsu:io:${vLibsu}")
|
implementation("com.github.topjohnwu.libsu:io:${vLibsu}")
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import com.topjohnwu.superuser.internal.NOPList
|
|||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
import com.topjohnwu.superuser.io.SuFile
|
||||||
import com.topjohnwu.superuser.io.SuFileInputStream
|
import com.topjohnwu.superuser.io.SuFileInputStream
|
||||||
|
import com.topjohnwu.superuser.io.SuFileOutputStream
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import net.jpountz.lz4.LZ4FrameInputStream
|
import net.jpountz.lz4.LZ4FrameInputStream
|
||||||
@ -53,6 +54,7 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
private val shell = Shell.getShell()
|
private val shell = Shell.getShell()
|
||||||
private val service: NetworkService by inject()
|
private val service: NetworkService by inject()
|
||||||
protected val context: Context by inject(Protected)
|
protected val context: Context by inject(Protected)
|
||||||
|
private val useRootDir = shell.isRoot && Info.noDataExec
|
||||||
|
|
||||||
private fun findImage(): Boolean {
|
private fun findImage(): Boolean {
|
||||||
val bootPath = "find_boot_image; echo \"\$BOOTIMAGE\"".fsh()
|
val bootPath = "find_boot_image; echo \"\$BOOTIMAGE\"".fsh()
|
||||||
@ -109,8 +111,7 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
} ?: emptyArray()
|
} ?: emptyArray()
|
||||||
for (lib in libs) {
|
for (lib in libs) {
|
||||||
val name = lib.name.substring(3, lib.name.length - 3)
|
val name = lib.name.substring(3, lib.name.length - 3)
|
||||||
val bin = File(installDir, name)
|
symlink(lib.path, "$installDir/$name")
|
||||||
symlink(lib.path, bin.path)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,16 +133,41 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (useRootDir) {
|
||||||
|
// Move everything to tmpfs to workaround Samsung bullshit
|
||||||
|
SuFile(Const.TMPDIR).also {
|
||||||
|
arrayOf(
|
||||||
|
"rm -rf $it",
|
||||||
|
"mkdir -p $it",
|
||||||
|
"cp_readlink $installDir $it",
|
||||||
|
"rm -rf $installDir"
|
||||||
|
).sh()
|
||||||
|
installDir = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optimization for SuFile I/O streams to skip an internal trial and error
|
||||||
|
private fun installDirFile(name: String): File {
|
||||||
|
return if (useRootDir)
|
||||||
|
SuFile(installDir, name)
|
||||||
|
else
|
||||||
|
File(installDir, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun InputStream.cleanPump(out: OutputStream) = withStreams(this, out) { src, _ ->
|
||||||
|
src.copyTo(out)
|
||||||
|
}
|
||||||
|
|
||||||
private fun newTarEntry(name: String, size: Long): TarEntry {
|
private fun newTarEntry(name: String, size: Long): TarEntry {
|
||||||
console.add("-- Writing: $name")
|
console.add("-- Writing: $name")
|
||||||
return TarEntry(TarHeader.createHeader(name, size, 0, false, 420 /* 0644 */))
|
return TarEntry(TarHeader.createHeader(name, size, 0, false, 420 /* 0644 */))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
private fun handleTar(input: InputStream, output: OutputStream): OutputStream {
|
private fun processTar(input: InputStream, output: OutputStream): OutputStream {
|
||||||
console.add("- Processing tar file")
|
console.add("- Processing tar file")
|
||||||
val tarOut = TarOutputStream(output)
|
val tarOut = TarOutputStream(output)
|
||||||
TarInputStream(input).use { tarIn ->
|
TarInputStream(input).use { tarIn ->
|
||||||
@ -161,8 +187,8 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
val name = entry.name.replace(".lz4", "")
|
val name = entry.name.replace(".lz4", "")
|
||||||
console.add("-- Extracting: $name")
|
console.add("-- Extracting: $name")
|
||||||
|
|
||||||
val extract = File(installDir, name)
|
val extract = installDirFile(name)
|
||||||
decompressedStream().writeTo(extract)
|
decompressedStream().cleanPump(SuFileOutputStream.open(extract))
|
||||||
} else if (entry.name.contains("vbmeta.img")) {
|
} else if (entry.name.contains("vbmeta.img")) {
|
||||||
val rawData = decompressedStream().readBytes()
|
val rawData = decompressedStream().readBytes()
|
||||||
// Valid vbmeta.img should be at least 256 bytes
|
// Valid vbmeta.img should be at least 256 bytes
|
||||||
@ -182,8 +208,8 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val boot = File(installDir, "boot.img")
|
val boot = installDirFile("boot.img")
|
||||||
val recovery = File(installDir, "recovery.img")
|
val recovery = installDirFile("recovery.img")
|
||||||
if (Config.recovery && recovery.exists() && boot.exists()) {
|
if (Config.recovery && recovery.exists() && boot.exists()) {
|
||||||
// Install to recovery
|
// Install to recovery
|
||||||
srcBoot = recovery
|
srcBoot = recovery
|
||||||
@ -192,10 +218,11 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
"cd $installDir",
|
"cd $installDir",
|
||||||
"./magiskboot unpack boot.img",
|
"./magiskboot unpack boot.img",
|
||||||
"./magiskboot repack boot.img",
|
"./magiskboot repack boot.img",
|
||||||
|
"cat new-boot.img > boot.img",
|
||||||
"./magiskboot cleanup",
|
"./magiskboot cleanup",
|
||||||
"mv new-boot.img boot.img",
|
"rm -f new-boot.img",
|
||||||
"cd /").sh()
|
"cd /").sh()
|
||||||
boot.inputStream().use {
|
SuFileInputStream.open(boot).use {
|
||||||
tarOut.putNextEntry(newTarEntry("boot.img", boot.length()))
|
tarOut.putNextEntry(newTarEntry("boot.img", boot.length()))
|
||||||
it.copyTo(tarOut)
|
it.copyTo(tarOut)
|
||||||
}
|
}
|
||||||
@ -236,13 +263,14 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
outStream = if (magic.contentEquals("ustar".toByteArray())) {
|
outStream = if (magic.contentEquals("ustar".toByteArray())) {
|
||||||
|
// tar file
|
||||||
outFile = MediaStoreUtils.getFile("$filename.tar", true)
|
outFile = MediaStoreUtils.getFile("$filename.tar", true)
|
||||||
handleTar(src, outFile!!.uri.outputStream())
|
processTar(src, outFile!!.uri.outputStream())
|
||||||
} else {
|
} else {
|
||||||
// Raw image
|
// raw image
|
||||||
srcBoot = File(installDir, "boot.img")
|
srcBoot = installDirFile("boot.img")
|
||||||
console.add("- Copying image to cache")
|
console.add("- Copying image to cache")
|
||||||
src.writeTo(srcBoot)
|
src.cleanPump(SuFileOutputStream.open(srcBoot))
|
||||||
outFile = MediaStoreUtils.getFile("$filename.img", true)
|
outFile = MediaStoreUtils.getFile("$filename.img", true)
|
||||||
outFile!!.uri.outputStream()
|
outFile!!.uri.outputStream()
|
||||||
}
|
}
|
||||||
@ -262,13 +290,13 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
|
|
||||||
// Output file
|
// Output file
|
||||||
try {
|
try {
|
||||||
val patched = File(installDir, "new-boot.img")
|
val newBoot = installDirFile("new-boot.img")
|
||||||
if (outStream is TarOutputStream) {
|
if (outStream is TarOutputStream) {
|
||||||
val name = if (srcBoot.path.contains("recovery")) "recovery.img" else "boot.img"
|
val name = if (srcBoot.path.contains("recovery")) "recovery.img" else "boot.img"
|
||||||
outStream.putNextEntry(newTarEntry(name, patched.length()))
|
outStream.putNextEntry(newTarEntry(name, newBoot.length()))
|
||||||
}
|
}
|
||||||
withStreams(patched.inputStream(), outStream) { src, out -> src.copyTo(out) }
|
SuFileInputStream.open(newBoot).cleanPump(outStream)
|
||||||
patched.delete()
|
newBoot.delete()
|
||||||
|
|
||||||
console.add("")
|
console.add("")
|
||||||
console.add("****************************")
|
console.add("****************************")
|
||||||
@ -284,34 +312,16 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
|
|
||||||
// Fix up binaries
|
// Fix up binaries
|
||||||
srcBoot.delete()
|
srcBoot.delete()
|
||||||
"cp_readlink $installDir".sh()
|
if (shell.isRoot) {
|
||||||
|
"fix_env $installDir".sh()
|
||||||
|
} else {
|
||||||
|
"cp_readlink $installDir".sh()
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun patchBoot(): Boolean {
|
private fun patchBoot(): Boolean {
|
||||||
val inRootDir = shell.isRoot && Info.noDataExec
|
|
||||||
|
|
||||||
val newBootImg: File
|
|
||||||
if (inRootDir) {
|
|
||||||
// Move everything to tmpfs to workaround Samsung bullshit
|
|
||||||
SuFile("${Const.TMPDIR}/install").also {
|
|
||||||
arrayOf(
|
|
||||||
"rm -rf $it",
|
|
||||||
"mkdir -p $it",
|
|
||||||
"cp_readlink $installDir $it",
|
|
||||||
"rm -rf $installDir"
|
|
||||||
).sh()
|
|
||||||
installDir = it
|
|
||||||
}
|
|
||||||
newBootImg = SuFile(installDir, "new-boot.img")
|
|
||||||
} else {
|
|
||||||
newBootImg = File(installDir, "new-boot.img")
|
|
||||||
// Create output files before hand
|
|
||||||
newBootImg.createNewFile()
|
|
||||||
File(installDir, "stock_boot.img").createNewFile()
|
|
||||||
}
|
|
||||||
|
|
||||||
var isSigned = false
|
var isSigned = false
|
||||||
if (srcBoot.let { it !is SuFile || !it.isCharacter }) {
|
if (srcBoot.let { it !is SuFile || !it.isCharacter }) {
|
||||||
try {
|
try {
|
||||||
@ -323,10 +333,18 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
console.add("! Unable to check signature")
|
console.add("! Unable to check signature")
|
||||||
|
Timber.e(e)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val newBoot = installDirFile("new-boot.img")
|
||||||
|
if (!useRootDir) {
|
||||||
|
// Create output files before hand
|
||||||
|
newBoot.createNewFile()
|
||||||
|
File(installDir, "stock_boot.img").createNewFile()
|
||||||
|
}
|
||||||
|
|
||||||
val cmds = arrayOf(
|
val cmds = arrayOf(
|
||||||
"cd $installDir",
|
"cd $installDir",
|
||||||
"KEEPFORCEENCRYPT=${Config.keepEnc} " +
|
"KEEPFORCEENCRYPT=${Config.keepEnc} " +
|
||||||
@ -343,8 +361,9 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
console.add("- Signing boot image with verity keys")
|
console.add("- Signing boot image with verity keys")
|
||||||
val signed = File.createTempFile("signed", ".img", context.cacheDir)
|
val signed = File.createTempFile("signed", ".img", context.cacheDir)
|
||||||
try {
|
try {
|
||||||
withStreams(SuFileInputStream.open(newBootImg).buffered(),
|
val src = SuFileInputStream.open(newBoot).buffered()
|
||||||
signed.outputStream().buffered()) { src, out ->
|
val out = signed.outputStream().buffered()
|
||||||
|
withStreams(src, out) { _, _ ->
|
||||||
SignBoot.doSignature(null, null, src, out, "/boot")
|
SignBoot.doSignature(null, null, src, out, "/boot")
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
@ -352,12 +371,7 @@ abstract class MagiskInstallImpl protected constructor(
|
|||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (inRootDir) {
|
job.add("cat $signed > $newBoot", "rm -f $signed")
|
||||||
job.add("cp -f $signed $newBootImg", "rm -f $signed")
|
|
||||||
} else {
|
|
||||||
signed.copyTo(newBootImg, overwrite = true)
|
|
||||||
signed.delete()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
job.exec()
|
job.exec()
|
||||||
return true
|
return true
|
||||||
@ -414,11 +428,7 @@ abstract class MagiskInstaller(
|
|||||||
if (success) {
|
if (success) {
|
||||||
console.add("- All done!")
|
console.add("- All done!")
|
||||||
} else {
|
} else {
|
||||||
if (installDir is SuFile) {
|
Shell.sh("rm -rf $installDir").submit()
|
||||||
Shell.sh("rm -rf ${Const.TMPDIR}").submit()
|
|
||||||
} else {
|
|
||||||
Shell.sh("rm -rf $installDir").submit()
|
|
||||||
}
|
|
||||||
console.add("! Installation failed")
|
console.add("! Installation failed")
|
||||||
}
|
}
|
||||||
return success
|
return success
|
||||||
|
Loading…
x
Reference in New Issue
Block a user