mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 17:17:26 +00:00
Compare commits
12 Commits
manager-v7
...
manager-v7
Author | SHA1 | Date | |
---|---|---|---|
![]() |
12bbc7fd6b | ||
![]() |
bf9ac8252b | ||
![]() |
4a3f5dc619 | ||
![]() |
ca156befbd | ||
![]() |
4db41e2ac4 | ||
![]() |
982a43fce1 | ||
![]() |
dd76a74e1c | ||
![]() |
70cb52b2c7 | ||
![]() |
5c7f69acaa | ||
![]() |
f1d9015e5f | ||
![]() |
e8d900c58e | ||
![]() |
a6241ae912 |
@@ -1,26 +1,20 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.topjohnwu.magisk.model.entity.UpdateInfo;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
|
||||
public final class Info {
|
||||
|
||||
public static int magiskVersionCode = -1;
|
||||
// Current status
|
||||
public static String magiskVersionString = "";
|
||||
// Update Info
|
||||
public static String remoteMagiskVersionString = "";
|
||||
public static int remoteMagiskVersionCode = -1;
|
||||
public static String magiskLink = "";
|
||||
public static String magiskNoteLink = "";
|
||||
public static String magiskMD5 = "";
|
||||
public static String remoteManagerVersionString = "";
|
||||
public static int remoteManagerVersionCode = -1;
|
||||
public static String managerLink = "";
|
||||
public static String managerNoteLink = "";
|
||||
public static String uninstallerLink = "";
|
||||
|
||||
// Install flags
|
||||
@NonNull
|
||||
public static String magiskVersionString = "";
|
||||
|
||||
public static UpdateInfo remote = new UpdateInfo();
|
||||
|
||||
public static boolean keepVerity = false;
|
||||
public static boolean keepEnc = false;
|
||||
public static boolean recovery = false;
|
||||
|
@@ -8,6 +8,7 @@ import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
||||
import com.topjohnwu.magisk.model.entity.toMap
|
||||
import com.topjohnwu.magisk.model.entity.toPolicy
|
||||
import com.topjohnwu.magisk.utils.now
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
@@ -47,12 +48,7 @@ class PolicyDao(
|
||||
condition {
|
||||
equals("uid", uid)
|
||||
}
|
||||
}.map { it.firstOrNull()?.toPolicy(context.packageManager) }
|
||||
.doOnError {
|
||||
if (it is PackageManager.NameNotFoundException) {
|
||||
delete(uid).subscribe()
|
||||
}
|
||||
}
|
||||
}.map { it.first().toPolicySafe() }
|
||||
|
||||
fun update(policy: MagiskPolicy) = query<Replace> {
|
||||
values(policy.toMap())
|
||||
@@ -62,8 +58,24 @@ class PolicyDao(
|
||||
condition {
|
||||
equals("uid/100000", Const.USER_ID)
|
||||
}
|
||||
}.flattenAsFlowable { it }
|
||||
.map { it.toPolicy(context.packageManager) }
|
||||
.toList()
|
||||
}.map { it.mapNotNull { it.toPolicySafe() } }
|
||||
|
||||
|
||||
private fun Map<String, String>.toPolicySafe(): MagiskPolicy? {
|
||||
val taskResult = runCatching { toPolicy(context.packageManager) }
|
||||
val result = taskResult.getOrNull()
|
||||
val exception = taskResult.exceptionOrNull()
|
||||
|
||||
Timber.e(exception)
|
||||
|
||||
when (exception) {
|
||||
is PackageManager.NameNotFoundException -> {
|
||||
val uid = getOrElse("uid") { null } ?: return null
|
||||
delete(uid).subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
package com.topjohnwu.magisk.data.network
|
||||
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.model.entity.MagiskConfig
|
||||
import com.topjohnwu.magisk.model.entity.UpdateInfo
|
||||
import io.reactivex.Single
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.http.GET
|
||||
@@ -15,19 +15,19 @@ interface GithubRawApiServices {
|
||||
//region topjohnwu/magisk_files
|
||||
|
||||
@GET("$MAGISK_FILES/master/stable.json")
|
||||
fun fetchStableUpdate(): Single<MagiskConfig>
|
||||
fun fetchStableUpdate(): Single<UpdateInfo>
|
||||
|
||||
@GET("$MAGISK_FILES/master/beta.json")
|
||||
fun fetchBetaUpdate(): Single<MagiskConfig>
|
||||
fun fetchBetaUpdate(): Single<UpdateInfo>
|
||||
|
||||
@GET("$MAGISK_FILES/master/canary_builds/release.json")
|
||||
fun fetchCanaryUpdate(): Single<MagiskConfig>
|
||||
fun fetchCanaryUpdate(): Single<UpdateInfo>
|
||||
|
||||
@GET("$MAGISK_FILES/master/canary_builds/canary.json")
|
||||
fun fetchCanaryDebugUpdate(): Single<MagiskConfig>
|
||||
fun fetchCanaryDebugUpdate(): Single<UpdateInfo>
|
||||
|
||||
@GET
|
||||
fun fetchCustomUpdate(@Url url: String): Single<MagiskConfig>
|
||||
fun fetchCustomUpdate(@Url url: String): Single<UpdateInfo>
|
||||
|
||||
@GET("$MAGISK_FILES/{$REVISION}/snet.apk")
|
||||
@Streaming
|
||||
|
@@ -7,7 +7,6 @@ import com.topjohnwu.magisk.model.entity.MagiskLog
|
||||
import com.topjohnwu.magisk.model.entity.WrappedMagiskLog
|
||||
import com.topjohnwu.magisk.utils.toSingle
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
@@ -21,7 +20,6 @@ class LogRepository(
|
||||
|
||||
fun fetchMagiskLogs() = "tail -n 5000 ${Const.MAGISK_LOG}".suRaw()
|
||||
.filter { it.isNotEmpty() }
|
||||
.map { Timber.i(it.toString()); it }
|
||||
|
||||
fun clearLogs() = logDao.deleteAll()
|
||||
fun clearOutdated() = logDao.deleteOutdated()
|
||||
|
@@ -50,27 +50,14 @@ class MagiskRepository(
|
||||
else -> throw IllegalArgumentException()
|
||||
}.flatMap {
|
||||
// If remote version is lower than current installed, try switching to beta
|
||||
if (it.magisk.versionCode.toIntOrNull() ?: -1 < Info.magiskVersionCode
|
||||
if (it.magisk.versionCode < Info.magiskVersionCode
|
||||
&& Config.updateChannel == Config.Value.DEFAULT_CHANNEL) {
|
||||
Config.updateChannel = Config.Value.BETA_CHANNEL
|
||||
apiRaw.fetchBetaUpdate()
|
||||
} else {
|
||||
Single.just(it)
|
||||
}
|
||||
}.doOnSuccess {
|
||||
Info.remoteMagiskVersionString = it.magisk.version
|
||||
Info.remoteMagiskVersionCode = it.magisk.versionCode.toIntOrNull() ?: -1
|
||||
Info.magiskLink = it.magisk.link
|
||||
Info.magiskNoteLink = it.magisk.note
|
||||
Info.magiskMD5 = it.magisk.hash
|
||||
|
||||
Info.remoteManagerVersionString = it.app.version
|
||||
Info.remoteManagerVersionCode = it.app.versionCode.toIntOrNull() ?: -1
|
||||
Info.managerLink = it.app.link
|
||||
Info.managerNoteLink = it.app.note
|
||||
|
||||
Info.uninstallerLink = it.uninstaller.link
|
||||
}
|
||||
}.map { Info.remote = it; it }
|
||||
|
||||
fun fetchApps() =
|
||||
Single.fromCallable { packageManager.getInstalledApplications(0) }
|
||||
|
@@ -1,11 +0,0 @@
|
||||
package com.topjohnwu.magisk.model.entity
|
||||
|
||||
import se.ansman.kotshi.JsonSerializable
|
||||
|
||||
@JsonSerializable
|
||||
data class MagiskApp(
|
||||
val version: String,
|
||||
val versionCode: String,
|
||||
val link: String,
|
||||
val note: String
|
||||
)
|
@@ -1,10 +0,0 @@
|
||||
package com.topjohnwu.magisk.model.entity
|
||||
|
||||
import se.ansman.kotshi.JsonSerializable
|
||||
|
||||
@JsonSerializable
|
||||
data class MagiskConfig(
|
||||
val app: MagiskApp,
|
||||
val uninstaller: MagiskLink,
|
||||
val magisk: MagiskFlashable
|
||||
)
|
@@ -1,13 +0,0 @@
|
||||
package com.topjohnwu.magisk.model.entity
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import se.ansman.kotshi.JsonSerializable
|
||||
|
||||
@JsonSerializable
|
||||
data class MagiskFlashable(
|
||||
val version: String,
|
||||
val versionCode: String,
|
||||
val link: String,
|
||||
val note: String,
|
||||
@Json(name = "md5") val hash: String
|
||||
)
|
@@ -1,8 +0,0 @@
|
||||
package com.topjohnwu.magisk.model.entity
|
||||
|
||||
import se.ansman.kotshi.JsonSerializable
|
||||
|
||||
@JsonSerializable
|
||||
data class MagiskLink(
|
||||
val link: String
|
||||
)
|
@@ -0,0 +1,33 @@
|
||||
package com.topjohnwu.magisk.model.entity
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import se.ansman.kotshi.JsonSerializable
|
||||
|
||||
@JsonSerializable
|
||||
data class UpdateInfo(
|
||||
val app: ManagerJson = ManagerJson(),
|
||||
val uninstaller: UninstallerJson = UninstallerJson(),
|
||||
val magisk: MagiskJson = MagiskJson()
|
||||
)
|
||||
|
||||
@JsonSerializable
|
||||
data class UninstallerJson(
|
||||
val link: String = ""
|
||||
)
|
||||
|
||||
@JsonSerializable
|
||||
data class MagiskJson(
|
||||
val version: String = "",
|
||||
val versionCode: Int = -1,
|
||||
val link: String = "",
|
||||
val note: String = "",
|
||||
@Json(name = "md5") val hash: String = ""
|
||||
)
|
||||
|
||||
@JsonSerializable
|
||||
data class ManagerJson(
|
||||
val version: String = "",
|
||||
val versionCode: Int = -1,
|
||||
val link: String = "",
|
||||
val note: String = ""
|
||||
)
|
@@ -73,7 +73,8 @@ open class GeneralReceiver : BroadcastReceiver() {
|
||||
}
|
||||
Intent.ACTION_LOCALE_CHANGED -> Shortcuts.setup(context)
|
||||
Const.Key.BROADCAST_MANAGER_UPDATE -> {
|
||||
Info.managerLink = intent.getStringExtra(Const.Key.INTENT_SET_LINK)
|
||||
Info.remote = Info.remote.copy(app = Info.remote.app.copy(
|
||||
link = intent.getStringExtra(Const.Key.INTENT_SET_LINK) ?: ""))
|
||||
DownloadApp.upgrade(intent.getStringExtra(Const.Key.INTENT_SET_NAME))
|
||||
}
|
||||
Const.Key.BROADCAST_REBOOT -> reboot()
|
||||
|
@@ -18,9 +18,9 @@ class UpdateCheckService : DelegateWorker() {
|
||||
Shell.getShell()
|
||||
return runCatching {
|
||||
magiskRepo.fetchUpdate().blockingGet()
|
||||
if (BuildConfig.VERSION_CODE < Info.remoteManagerVersionCode)
|
||||
if (BuildConfig.VERSION_CODE < Info.remote.app.versionCode)
|
||||
Notifications.managerUpdate()
|
||||
else if (Info.magiskVersionCode < Info.remoteMagiskVersionCode)
|
||||
else if (Info.magiskVersionCode < Info.remote.magisk.versionCode)
|
||||
Notifications.magiskUpdate()
|
||||
ListenableWorker.Result.success()
|
||||
}.getOrElse {
|
||||
|
@@ -123,9 +123,9 @@ public abstract class MagiskInstaller {
|
||||
|
||||
File zip = new File(App.self.getCacheDir(), "magisk.zip");
|
||||
|
||||
if (!ShellUtils.checkSum("MD5", zip, Info.magiskMD5)) {
|
||||
if (!ShellUtils.checkSum("MD5", zip, Info.remote.getMagisk().getHash())) {
|
||||
console.add("- Downloading zip");
|
||||
Networking.get(Info.magiskLink)
|
||||
Networking.get(Info.remote.getMagisk().getLink())
|
||||
.setDownloadProgressListener(new ProgressLog())
|
||||
.execForFile(zip);
|
||||
} else {
|
||||
|
@@ -3,8 +3,6 @@ package com.topjohnwu.magisk.tasks;
|
||||
import android.database.Cursor;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.topjohnwu.magisk.App;
|
||||
import com.topjohnwu.magisk.Config;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
@@ -20,7 +18,6 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
@@ -33,16 +30,11 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import io.reactivex.Single;
|
||||
|
||||
@Deprecated
|
||||
public class UpdateRepos {
|
||||
private static final DateFormat DATE_FORMAT;
|
||||
|
||||
static {
|
||||
DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private final RepoDatabaseHelper repoDB;
|
||||
@@ -71,6 +63,17 @@ public class UpdateRepos {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Static instance of (Simple)DateFormat is not threadsafe so in order to make it safe it needs
|
||||
* to be created beforehand on the same thread where it'll be used.
|
||||
* See https://stackoverflow.com/a/18383395
|
||||
*/
|
||||
private static SimpleDateFormat getDateFormat() {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||
format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
return format;
|
||||
}
|
||||
|
||||
/* We sort repos by last push, which means that we only need to check whether the
|
||||
* first page is updated to determine whether the online repo database is changed
|
||||
*/
|
||||
@@ -95,10 +98,12 @@ public class UpdateRepos {
|
||||
return true;
|
||||
|
||||
try {
|
||||
SimpleDateFormat dateFormat = getDateFormat();
|
||||
|
||||
for (int i = 0; i < res.getResult().length(); i++) {
|
||||
JSONObject rawRepo = res.getResult().getJSONObject(i);
|
||||
String id = rawRepo.getString("name");
|
||||
Date date = DATE_FORMAT.parse(rawRepo.getString("pushed_at"));
|
||||
Date date = dateFormat.parse(rawRepo.getString("pushed_at"));
|
||||
moduleQueue.offer(new Pair<>(id, date));
|
||||
}
|
||||
} catch (JSONException | ParseException e) {
|
||||
|
@@ -5,14 +5,11 @@ import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.skoumal.teanity.extensions.subscribeK
|
||||
import com.topjohnwu.magisk.*
|
||||
import com.topjohnwu.magisk.data.database.SettingsDao
|
||||
import com.topjohnwu.magisk.tasks.UpdateRepos
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import com.topjohnwu.magisk.view.Shortcuts
|
||||
import com.topjohnwu.net.Networking
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import org.koin.android.ext.android.get
|
||||
|
||||
@@ -61,14 +58,6 @@ open class SplashActivity : AppCompatActivity() {
|
||||
// Setup shortcuts
|
||||
Shortcuts.setup(this)
|
||||
|
||||
// Magisk working as expected
|
||||
if (Shell.rootAccess() && Info.magiskVersionCode > 0) {
|
||||
// Load repos
|
||||
if (Networking.checkNetworkStatus(this)) {
|
||||
get<UpdateRepos>().exec().subscribeK()
|
||||
}
|
||||
}
|
||||
|
||||
val intent = Intent(this, ClassMap[MainActivity::class.java])
|
||||
intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION))
|
||||
DONE = true
|
||||
|
@@ -56,7 +56,7 @@ class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
|
||||
|
||||
private fun installMagisk() {
|
||||
// Show Manager update first
|
||||
if (Info.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
|
||||
if (Info.remote.app.versionCode > BuildConfig.VERSION_CODE) {
|
||||
installManager()
|
||||
return
|
||||
}
|
||||
|
@@ -172,7 +172,7 @@ class HomeViewModel(
|
||||
state = State.LOADED
|
||||
magiskState.value = when (Info.magiskVersionCode) {
|
||||
in Int.MIN_VALUE until 0 -> MagiskState.NOT_INSTALLED
|
||||
!in Info.remoteMagiskVersionCode..Int.MAX_VALUE -> MagiskState.OBSOLETE
|
||||
!in Info.remote.magisk.versionCode..Int.MAX_VALUE -> MagiskState.OBSOLETE
|
||||
else -> MagiskState.UP_TO_DATE
|
||||
}
|
||||
|
||||
@@ -183,9 +183,9 @@ class HomeViewModel(
|
||||
}
|
||||
|
||||
magiskLatestVersion.value = version
|
||||
.format(Info.remoteMagiskVersionString, Info.remoteMagiskVersionCode)
|
||||
.format(Info.remote.magisk.version, Info.remote.magisk.versionCode)
|
||||
|
||||
managerState.value = when (Info.remoteManagerVersionCode) {
|
||||
managerState.value = when (Info.remote.app.versionCode) {
|
||||
in Int.MIN_VALUE until 0 -> MagiskState.NOT_INSTALLED //wrong update channel
|
||||
in (BuildConfig.VERSION_CODE + 1)..Int.MAX_VALUE -> MagiskState.OBSOLETE
|
||||
else -> MagiskState.UP_TO_DATE
|
||||
@@ -195,7 +195,7 @@ class HomeViewModel(
|
||||
.format(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
|
||||
|
||||
managerLatestVersion.value = version
|
||||
.format(Info.remoteManagerVersionString, Info.remoteManagerVersionCode)
|
||||
.format(Info.remote.app.version, Info.remote.app.versionCode)
|
||||
}
|
||||
|
||||
private fun ensureEnv() {
|
||||
|
@@ -61,9 +61,10 @@ class SuperuserViewModel(
|
||||
{ it.item.packageName }
|
||||
))
|
||||
}
|
||||
.map { it to items.calculateDiff(it) }
|
||||
.applySchedulers()
|
||||
.applyViewModel(this)
|
||||
.subscribeK { items.update(it) }
|
||||
.subscribeK { items.update(it.first, it.second) }
|
||||
.add()
|
||||
}
|
||||
|
||||
|
@@ -186,9 +186,17 @@ fun setHidden(view: FloatingActionButton, hide: Boolean) {
|
||||
}
|
||||
|
||||
@BindingAdapter("scrollPosition", "scrollPositionSmooth", requireAll = false)
|
||||
fun setScrollPosition(view: RecyclerView, position: Int, smoothScroll: Boolean) = when {
|
||||
smoothScroll -> view.smoothScrollToPosition(position)
|
||||
else -> view.scrollToPosition(position)
|
||||
fun setScrollPosition(view: RecyclerView, position: Int, smoothScroll: Boolean) {
|
||||
val adapterItemCount = view.adapter?.itemCount ?: -1
|
||||
if (position !in 0 until adapterItemCount) {
|
||||
// the position is not in adapter bounds, adapter will throw exception for invalid positions
|
||||
return
|
||||
}
|
||||
|
||||
when {
|
||||
smoothScroll -> view.smoothScrollToPosition(position)
|
||||
else -> view.scrollToPosition(position)
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("recyclerScrollEvent")
|
||||
|
@@ -26,7 +26,7 @@ public class DownloadApp {
|
||||
|
||||
public static void restore() {
|
||||
String name = Utils.INSTANCE.fmt("MagiskManager v%s(%d)",
|
||||
Info.remoteManagerVersionString, Info.remoteManagerVersionCode);
|
||||
Info.remote.getApp().getVersion(), Info.remote.getApp().getVersionCode());
|
||||
dlInstall(name, new RestoreManager());
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class DownloadApp {
|
||||
File apk = new File(App.self.getCacheDir(), "manager.apk");
|
||||
ProgressNotification progress = new ProgressNotification(name);
|
||||
listener.progress = progress;
|
||||
Networking.get(Info.managerLink)
|
||||
Networking.get(Info.remote.getApp().getLink())
|
||||
.setExecutor(App.THREAD_POOL)
|
||||
.setDownloadProgressListener(progress)
|
||||
.setErrorHandler((conn, e) -> progress.dlFail())
|
||||
|
@@ -63,11 +63,11 @@ public class Notifications {
|
||||
public static void managerUpdate() {
|
||||
App app = App.self;
|
||||
String name = Utils.INSTANCE.fmt("MagiskManager v%s(%d)",
|
||||
Info.remoteManagerVersionString, Info.remoteManagerVersionCode);
|
||||
Info.remote.getApp().getVersion(), Info.remote.getApp().getVersionCode());
|
||||
|
||||
Intent intent = new Intent(app, ClassMap.get(GeneralReceiver.class));
|
||||
intent.setAction(Const.Key.BROADCAST_MANAGER_UPDATE);
|
||||
intent.putExtra(Const.Key.INTENT_SET_LINK, Info.managerLink);
|
||||
intent.putExtra(Const.Key.INTENT_SET_LINK, Info.remote.getApp().getLink());
|
||||
intent.putExtra(Const.Key.INTENT_SET_NAME, name);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(app,
|
||||
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
@@ -57,11 +57,11 @@ internal class InstallMethodDialog(activity: MagiskActivity<*, *>, options: List
|
||||
private fun downloadOnly(activity: MagiskActivity<*, *>) {
|
||||
activity.withExternalRW {
|
||||
onSuccess {
|
||||
val filename = "Magisk-v${Info.remoteMagiskVersionString}" +
|
||||
"(${Info.remoteMagiskVersionCode}).zip"
|
||||
val filename = "Magisk-v${Info.remote.magisk.version}" +
|
||||
"(${Info.remote.magisk.versionCode}).zip"
|
||||
val zip = File(Const.EXTERNAL_PATH, filename)
|
||||
val progress = ProgressNotification(filename)
|
||||
Networking.get(Info.magiskLink)
|
||||
Networking.get(Info.remote.magisk.link)
|
||||
.setDownloadProgressListener(progress)
|
||||
.setErrorHandler { _, _ -> progress.dlFail() }
|
||||
.getAsFile(zip) {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package com.topjohnwu.magisk.view.dialogs
|
||||
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import com.topjohnwu.magisk.Info
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.ui.base.MagiskActivity
|
||||
@@ -13,8 +12,8 @@ import java.util.*
|
||||
|
||||
class MagiskInstallDialog(a: MagiskActivity<*, *>) : CustomAlertDialog(a) {
|
||||
init {
|
||||
val filename = "Magisk v${Info.remoteMagiskVersionString}" +
|
||||
"(${Info.remoteMagiskVersionCode})"
|
||||
val filename = "Magisk v${Info.remote.magisk.version}" +
|
||||
"(${Info.remote.magisk.versionCode})"
|
||||
setTitle(a.getString(R.string.repo_install_title, a.getString(R.string.magisk)))
|
||||
setMessage(a.getString(R.string.repo_install_msg, filename))
|
||||
setCancelable(true)
|
||||
@@ -31,13 +30,13 @@ class MagiskInstallDialog(a: MagiskActivity<*, *>) : CustomAlertDialog(a) {
|
||||
}
|
||||
InstallMethodDialog(a, options).show()
|
||||
}
|
||||
if (!TextUtils.isEmpty(Info.magiskNoteLink)) {
|
||||
if (Info.remote.magisk.note.isNotEmpty()) {
|
||||
setNeutralButton(R.string.release_notes) { _, _ ->
|
||||
if (Info.magiskNoteLink.contains("forum.xda-developers")) {
|
||||
if (Info.remote.magisk.note.contains("forum.xda-developers")) {
|
||||
// Open forum links in browser
|
||||
Utils.openLink(a, Uri.parse(Info.magiskNoteLink))
|
||||
Utils.openLink(a, Uri.parse(Info.remote.magisk.note))
|
||||
} else {
|
||||
MarkDownWindow.show(a, null, Info.magiskNoteLink)
|
||||
MarkDownWindow.show(a, null, Info.remote.magisk.note)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -9,15 +9,15 @@ import com.topjohnwu.magisk.view.MarkDownWindow
|
||||
class ManagerInstallDialog(a: Activity) : CustomAlertDialog(a) {
|
||||
|
||||
init {
|
||||
val name = "MagiskManager v${Info.remoteManagerVersionString}" +
|
||||
"(${Info.remoteManagerVersionCode})"
|
||||
val name = "MagiskManager v${Info.remote.app.version}" +
|
||||
"(${Info.remote.app.versionCode})"
|
||||
setTitle(a.getString(R.string.repo_install_title, a.getString(R.string.app_name)))
|
||||
setMessage(a.getString(R.string.repo_install_msg, name))
|
||||
setCancelable(true)
|
||||
setPositiveButton(R.string.install) { _, _ -> DownloadApp.upgrade(name) }
|
||||
if (Info.managerNoteLink.isNotEmpty()) {
|
||||
if (Info.remote.app.note.isNotEmpty()) {
|
||||
setNeutralButton(R.string.app_changelog) { _, _ ->
|
||||
MarkDownWindow.show(a, null, Info.managerNoteLink) }
|
||||
MarkDownWindow.show(a, null, Info.remote.app.note) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,9 +4,7 @@ import android.app.Activity
|
||||
import android.app.ProgressDialog
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import android.widget.Toast
|
||||
|
||||
import com.topjohnwu.magisk.ClassMap
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.Info
|
||||
@@ -16,7 +14,6 @@ import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.view.ProgressNotification
|
||||
import com.topjohnwu.net.Networking
|
||||
import com.topjohnwu.superuser.Shell
|
||||
|
||||
import java.io.File
|
||||
|
||||
class UninstallDialog(activity: Activity) : CustomAlertDialog(activity) {
|
||||
@@ -37,11 +34,11 @@ class UninstallDialog(activity: Activity) : CustomAlertDialog(activity) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(Info.uninstallerLink)) {
|
||||
if (Info.remote.uninstaller.link.isNotEmpty()) {
|
||||
setPositiveButton(R.string.complete_uninstall) { d, i ->
|
||||
val zip = File(activity.filesDir, "uninstaller.zip")
|
||||
val progress = ProgressNotification(zip.name)
|
||||
Networking.get(Info.uninstallerLink)
|
||||
Networking.get(Info.remote.uninstaller.link)
|
||||
.setDownloadProgressListener(progress)
|
||||
.setErrorHandler { _, _ -> progress.dlFail() }
|
||||
.getAsFile(zip) { f ->
|
||||
|
@@ -38,7 +38,7 @@
|
||||
</HorizontalScrollView>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
hide="@{viewModel.scrollPosition == item.items.size - 1}"
|
||||
hide="@{viewModel.scrollPosition == item.items.size - 1 || item.items.size == 0}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# v7.3.0
|
||||
- **HUGE** code base modernization, thanks @diareuse!
|
||||
- Reboot device using proper API (no more abrupt reboot)
|
||||
- New floating button in Magisk logs to go to bottom
|
||||
# v7.3.1
|
||||
- Fix blank Superuser fragment under some circumstances
|
||||
- Fix incomplete repo database bug: if you experience this issue from the old version, go to Settings → Clear Repo Cache and refresh the Download fragment
|
||||
- Fix crashing when pressing fast scrolling button when logs are empty
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <utils.h>
|
||||
#include <logging.h>
|
||||
#include <selinux.h>
|
||||
|
||||
#include "init.h"
|
||||
|
||||
@@ -73,17 +74,17 @@ static void setup_block(const char *partname, char *block_dev) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MagiskInit::read_dt_fstab(const char *name, char *partname, char *fstype) {
|
||||
bool BaseInit::read_dt_fstab(const char *name, char *partname, char *fstype) {
|
||||
char path[128];
|
||||
int fd;
|
||||
sprintf(path, "%s/fstab/%s/dev", cmd.dt_dir, name);
|
||||
sprintf(path, "%s/fstab/%s/dev", cmd->dt_dir, name);
|
||||
if ((fd = xopen(path, O_RDONLY | O_CLOEXEC)) >= 0) {
|
||||
read(fd, path, sizeof(path));
|
||||
close(fd);
|
||||
// Some custom treble use different names, so use what we read
|
||||
char *part = rtrim(strrchr(path, '/') + 1);
|
||||
sprintf(partname, "%s%s", part, strend(part, cmd.slot) ? cmd.slot : "");
|
||||
sprintf(path, "%s/fstab/%s/type", cmd.dt_dir, name);
|
||||
sprintf(partname, "%s%s", part, strend(part, cmd->slot) ? cmd->slot : "");
|
||||
sprintf(path, "%s/fstab/%s/type", cmd->dt_dir, name);
|
||||
if ((fd = xopen(path, O_RDONLY | O_CLOEXEC)) >= 0) {
|
||||
read(fd, fstype, 32);
|
||||
close(fd);
|
||||
@@ -106,38 +107,57 @@ if (!is_lnk("/" #name) && read_dt_fstab(#name, partname, fstype)) { \
|
||||
mnt_##name = true; \
|
||||
}
|
||||
|
||||
void MagiskInit::early_mount() {
|
||||
void LegacyInit::early_mount() {
|
||||
char partname[32];
|
||||
char fstype[32];
|
||||
char block_dev[64];
|
||||
|
||||
if (cmd.system_as_root) {
|
||||
LOGD("Early mount system_root\n");
|
||||
sprintf(partname, "system%s", cmd.slot);
|
||||
setup_block(partname, block_dev);
|
||||
xmkdir("/system_root", 0755);
|
||||
if (xmount(block_dev, "/system_root", "ext4", MS_RDONLY, nullptr))
|
||||
xmount(block_dev, "/system_root", "erofs", MS_RDONLY, nullptr);
|
||||
xmkdir("/system", 0755);
|
||||
xmount("/system_root/system", "/system", nullptr, MS_BIND, nullptr);
|
||||
|
||||
// Android Q
|
||||
if (is_lnk("/system_root/init"))
|
||||
load_sepol = true;
|
||||
|
||||
// System-as-root with monolithic sepolicy
|
||||
if (access("/system_root/sepolicy", F_OK) == 0)
|
||||
cp_afc("/system_root/sepolicy", "/sepolicy");
|
||||
|
||||
// Copy if these partitions are symlinks
|
||||
link_root("/vendor");
|
||||
link_root("/product");
|
||||
link_root("/odm");
|
||||
} else {
|
||||
mount_root(system);
|
||||
}
|
||||
|
||||
mount_root(system);
|
||||
mount_root(vendor);
|
||||
mount_root(product);
|
||||
mount_root(odm);
|
||||
}
|
||||
|
||||
void SARInit::early_mount() {
|
||||
char partname[32];
|
||||
char fstype[32];
|
||||
char block_dev[64];
|
||||
|
||||
LOGD("Early mount system_root\n");
|
||||
sprintf(partname, "system%s", cmd->slot);
|
||||
setup_block(partname, block_dev);
|
||||
xmkdir("/system_root", 0755);
|
||||
if (xmount(block_dev, "/system_root", "ext4", MS_RDONLY, nullptr))
|
||||
xmount(block_dev, "/system_root", "erofs", MS_RDONLY, nullptr);
|
||||
xmkdir("/system", 0755);
|
||||
xmount("/system_root/system", "/system", nullptr, MS_BIND, nullptr);
|
||||
|
||||
// Android Q
|
||||
if (is_lnk("/system_root/init"))
|
||||
load_sepol = true;
|
||||
|
||||
// System-as-root with monolithic sepolicy
|
||||
if (access("/system_root/sepolicy", F_OK) == 0)
|
||||
cp_afc("/system_root/sepolicy", "/sepolicy");
|
||||
|
||||
link_root("/vendor");
|
||||
link_root("/product");
|
||||
link_root("/odm");
|
||||
mount_root(vendor);
|
||||
mount_root(product);
|
||||
mount_root(odm);
|
||||
}
|
||||
|
||||
#define umount_root(name) \
|
||||
if (mnt_##name) \
|
||||
umount("/" #name);
|
||||
|
||||
void BaseInit::cleanup() {
|
||||
umount(SELINUX_MNT);
|
||||
umount("/sys");
|
||||
umount("/proc");
|
||||
umount_root(system);
|
||||
umount_root(vendor);
|
||||
umount_root(product);
|
||||
umount_root(odm);
|
||||
}
|
||||
|
@@ -92,7 +92,7 @@ static bool check_key_combo() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MagiskInit::load_kernel_info() {
|
||||
void load_kernel_info(cmdline *cmd) {
|
||||
// Communicate with kernel using procfs and sysfs
|
||||
xmkdir("/proc", 0755);
|
||||
xmount("proc", "/proc", "proc", 0, nullptr);
|
||||
@@ -106,14 +106,14 @@ void MagiskInit::load_kernel_info() {
|
||||
parse_cmdline([&](auto key, auto value) -> void {
|
||||
LOGD("cmdline: [%s]=[%s]\n", key.data(), value);
|
||||
if (key == "androidboot.slot_suffix") {
|
||||
strcpy(cmd.slot, value);
|
||||
strcpy(cmd->slot, value);
|
||||
} else if (key == "androidboot.slot") {
|
||||
cmd.slot[0] = '_';
|
||||
strcpy(cmd.slot + 1, value);
|
||||
cmd->slot[0] = '_';
|
||||
strcpy(cmd->slot + 1, value);
|
||||
} else if (key == "skip_initramfs") {
|
||||
cmd.system_as_root = true;
|
||||
cmd->system_as_root = true;
|
||||
} else if (key == "androidboot.android_dt_dir") {
|
||||
strcpy(cmd.dt_dir, value);
|
||||
strcpy(cmd->dt_dir, value);
|
||||
} else if (key == "enter_recovery") {
|
||||
enter_recovery = value[0] == '1';
|
||||
} else if (key == "androidboot.hardware") {
|
||||
@@ -140,13 +140,13 @@ void MagiskInit::load_kernel_info() {
|
||||
|
||||
if (recovery_mode) {
|
||||
LOGD("Running in recovery mode, waiting for key...\n");
|
||||
cmd.system_as_root = !check_key_combo();
|
||||
cmd->system_as_root = !check_key_combo();
|
||||
}
|
||||
|
||||
if (cmd.dt_dir[0] == '\0')
|
||||
strcpy(cmd.dt_dir, DEFAULT_DT_DIR);
|
||||
if (cmd->dt_dir[0] == '\0')
|
||||
strcpy(cmd->dt_dir, DEFAULT_DT_DIR);
|
||||
|
||||
LOGD("system_as_root=[%d]\n", cmd.system_as_root);
|
||||
LOGD("slot=[%s]\n", cmd.slot);
|
||||
LOGD("dt_dir=[%s]\n", cmd.dt_dir);
|
||||
LOGD("system_as_root=[%d]\n", cmd->system_as_root);
|
||||
LOGD("slot=[%s]\n", cmd->slot);
|
||||
LOGD("dt_dir=[%s]\n", cmd->dt_dir);
|
||||
}
|
||||
|
@@ -6,13 +6,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <xz.h>
|
||||
#include <magisk.h>
|
||||
#include <selinux.h>
|
||||
#include <cpio.h>
|
||||
#include <utils.h>
|
||||
#include <flags.h>
|
||||
@@ -48,12 +46,10 @@ static void setup_klog() {
|
||||
#define setup_klog(...)
|
||||
#endif
|
||||
|
||||
static int test_main(int argc, char *argv[]);
|
||||
|
||||
constexpr const char *init_applet[] =
|
||||
{ "magiskpolicy", "supolicy", "init_test", nullptr };
|
||||
{ "magiskpolicy", "supolicy", nullptr };
|
||||
constexpr int (*init_applet_main[])(int, char *[]) =
|
||||
{ magiskpolicy_main, magiskpolicy_main, test_main, nullptr };
|
||||
{ magiskpolicy_main, magiskpolicy_main, nullptr };
|
||||
|
||||
static bool unxz(int fd, const uint8_t *buf, size_t size) {
|
||||
uint8_t out[8192];
|
||||
@@ -117,50 +113,27 @@ static int dump_manager(const char *path, mode_t mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MagiskInit::preset() {
|
||||
root = open("/", O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (cmd.system_as_root) {
|
||||
// Clear rootfs
|
||||
LOGD("Cleaning rootfs\n");
|
||||
frm_rf(root, { "overlay", "proc", "sys" });
|
||||
} else {
|
||||
decompress_ramdisk();
|
||||
|
||||
// Revert original init binary
|
||||
rename("/.backup/init", "/init");
|
||||
rm_rf("/.backup");
|
||||
|
||||
// Do not go further if device is booting into recovery
|
||||
if (access("/sbin/recovery", F_OK) == 0) {
|
||||
LOGD("Ramdisk is recovery, abort\n");
|
||||
re_exec_init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define umount_root(name) \
|
||||
if (mnt_##name) \
|
||||
umount("/" #name);
|
||||
|
||||
void MagiskInit::cleanup() {
|
||||
umount(SELINUX_MNT);
|
||||
umount("/sys");
|
||||
umount("/proc");
|
||||
umount_root(system);
|
||||
umount_root(vendor);
|
||||
umount_root(product);
|
||||
umount_root(odm);
|
||||
}
|
||||
|
||||
void MagiskInit::re_exec_init() {
|
||||
void BaseInit::re_exec_init() {
|
||||
LOGD("Re-exec /init\n");
|
||||
cleanup();
|
||||
execv("/init", argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void MagiskInit::start() {
|
||||
void LegacyInit::preset() {
|
||||
LOGD("Reverting /init\n");
|
||||
root = open("/", O_RDONLY | O_CLOEXEC);
|
||||
rename("/.backup/init", "/init");
|
||||
rm_rf("/.backup");
|
||||
}
|
||||
|
||||
void SARInit::preset() {
|
||||
LOGD("Cleaning rootfs\n");
|
||||
root = open("/", O_RDONLY | O_CLOEXEC);
|
||||
frm_rf(root, { "overlay", "proc", "sys" });
|
||||
}
|
||||
|
||||
void BaseInit::start() {
|
||||
// Prevent file descriptor confusion
|
||||
mknod("/null", S_IFCHR | 0666, makedev(1, 3));
|
||||
int null = open("/null", O_RDWR | O_CLOEXEC);
|
||||
@@ -171,10 +144,6 @@ void MagiskInit::start() {
|
||||
if (null > STDERR_FILENO)
|
||||
close(null);
|
||||
|
||||
setup_klog();
|
||||
|
||||
load_kernel_info();
|
||||
|
||||
full_read("/init", &self.buf, &self.sz);
|
||||
full_read("/.backup/.magisk", &config.buf, &config.sz);
|
||||
|
||||
@@ -184,26 +153,27 @@ void MagiskInit::start() {
|
||||
re_exec_init();
|
||||
}
|
||||
|
||||
void MagiskInit::test() {
|
||||
cmdline_logging();
|
||||
log_cb.ex = nop_ex;
|
||||
class RecoveryInit : public BaseInit {
|
||||
public:
|
||||
RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {};
|
||||
void start() override {
|
||||
LOGD("Ramdisk is recovery, abort\n");
|
||||
rename("/.backup/init", "/init");
|
||||
rm_rf("/.backup");
|
||||
re_exec_init();
|
||||
}
|
||||
};
|
||||
|
||||
chdir(dirname(argv[0]));
|
||||
chroot(".");
|
||||
chdir("/");
|
||||
|
||||
load_kernel_info();
|
||||
preset();
|
||||
early_mount();
|
||||
setup_rootfs();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
static int test_main(int, char *argv[]) {
|
||||
MagiskInit init(argv);
|
||||
init.test();
|
||||
return 0;
|
||||
}
|
||||
class TestInit : public SARInit {
|
||||
public:
|
||||
TestInit(char *argv[], cmdline *cmd) : SARInit(argv, cmd) {};
|
||||
void start() override {
|
||||
preset();
|
||||
early_mount();
|
||||
setup_rootfs();
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
umask(0);
|
||||
@@ -220,11 +190,40 @@ int main(int argc, char *argv[]) {
|
||||
return dump_manager(argv[3], 0644);
|
||||
}
|
||||
|
||||
if (getpid() != 1)
|
||||
return 1;
|
||||
#ifdef MAGISK_DEBUG
|
||||
bool run_test = getenv("INIT_TEST") != nullptr;
|
||||
#else
|
||||
constexpr bool run_test = false;
|
||||
#endif
|
||||
|
||||
MagiskInit init(argv);
|
||||
if (run_test) {
|
||||
chdir(dirname(argv[0]));
|
||||
chroot(".");
|
||||
chdir("/");
|
||||
cmdline_logging();
|
||||
log_cb.ex = nop_ex;
|
||||
} else {
|
||||
if (getpid() != 1)
|
||||
return 1;
|
||||
setup_klog();
|
||||
}
|
||||
|
||||
cmdline cmd{};
|
||||
load_kernel_info(&cmd);
|
||||
|
||||
unique_ptr<BaseInit> init;
|
||||
if (run_test) {
|
||||
init = make_unique<TestInit>(argv, &cmd);
|
||||
} else if (cmd.system_as_root) {
|
||||
init = make_unique<SARInit>(argv, &cmd);
|
||||
} else {
|
||||
decompress_ramdisk();
|
||||
if (access("/sbin/recovery", F_OK) == 0)
|
||||
init = make_unique<RecoveryInit>(argv, &cmd);
|
||||
else
|
||||
init = make_unique<LegacyInit>(argv, &cmd);
|
||||
}
|
||||
|
||||
// Run the main routine
|
||||
init.start();
|
||||
init->start();
|
||||
}
|
||||
|
@@ -11,22 +11,21 @@ struct raw_data {
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
class MagiskInit {
|
||||
private:
|
||||
cmdline cmd{};
|
||||
class BaseInit {
|
||||
protected:
|
||||
cmdline *cmd;
|
||||
raw_data self{};
|
||||
raw_data config{};
|
||||
int root = -1;
|
||||
char **argv;
|
||||
int root = -1;
|
||||
bool load_sepol = false;
|
||||
bool mnt_system = false;
|
||||
bool mnt_vendor = false;
|
||||
bool mnt_product = false;
|
||||
bool mnt_odm = false;
|
||||
|
||||
void load_kernel_info();
|
||||
void preset();
|
||||
void early_mount();
|
||||
virtual void preset() {};
|
||||
virtual void early_mount() {}
|
||||
void setup_rootfs();
|
||||
bool read_dt_fstab(const char *name, char *partname, char *fstype);
|
||||
bool patch_sepolicy();
|
||||
@@ -34,9 +33,25 @@ private:
|
||||
void re_exec_init();
|
||||
|
||||
public:
|
||||
explicit MagiskInit(char *argv[]) : argv(argv) {}
|
||||
void start();
|
||||
void test();
|
||||
BaseInit(char *argv[], cmdline *cmd) : cmd(cmd), argv(argv) {}
|
||||
virtual ~BaseInit() = default;
|
||||
virtual void start();
|
||||
};
|
||||
|
||||
class LegacyInit : public BaseInit {
|
||||
protected:
|
||||
void preset() override;
|
||||
void early_mount() override;
|
||||
public:
|
||||
LegacyInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {};
|
||||
};
|
||||
|
||||
class SARInit : public BaseInit {
|
||||
protected:
|
||||
void preset() override;
|
||||
void early_mount() override;
|
||||
public:
|
||||
SARInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {};
|
||||
};
|
||||
|
||||
static inline bool is_lnk(const char *name) {
|
||||
@@ -46,4 +61,5 @@ static inline bool is_lnk(const char *name) {
|
||||
return S_ISLNK(st.st_mode);
|
||||
}
|
||||
|
||||
void load_kernel_info(cmdline *cmd);
|
||||
int dump_magisk(const char *path, mode_t mode);
|
||||
|
@@ -37,10 +37,10 @@ constexpr const char wrapper[] =
|
||||
"exec /sbin/magisk.bin \"$0\" \"$@\"\n"
|
||||
;
|
||||
|
||||
void MagiskInit::setup_rootfs() {
|
||||
void BaseInit::setup_rootfs() {
|
||||
bool patch_init = patch_sepolicy();
|
||||
|
||||
if (cmd.system_as_root) {
|
||||
if (cmd->system_as_root) {
|
||||
// Clone rootfs
|
||||
LOGD("Clone root dir from system to rootfs\n");
|
||||
int system_root = xopen("/system_root", O_RDONLY | O_CLOEXEC);
|
||||
@@ -173,7 +173,7 @@ void MagiskInit::setup_rootfs() {
|
||||
close(sbin);
|
||||
}
|
||||
|
||||
bool MagiskInit::patch_sepolicy() {
|
||||
bool BaseInit::patch_sepolicy() {
|
||||
bool patch_init = false;
|
||||
|
||||
if (access(SPLIT_PLAT_CIL, R_OK) == 0) {
|
||||
|
@@ -12,6 +12,8 @@
|
||||
#include "magiskboot.h"
|
||||
#include "compress.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static void usage(char *arg0) {
|
||||
fprintf(stderr,
|
||||
FULL_VER(MagiskBoot) " - Boot Image Modification Tool\n"
|
||||
@@ -114,10 +116,11 @@ int main(int argc, char *argv[]) {
|
||||
usage(argv[0]);
|
||||
|
||||
// Skip '--' for backwards compatibility
|
||||
if (strncmp(argv[1], "--", 2) == 0)
|
||||
argv[1] += 2;
|
||||
string_view action(argv[1]);
|
||||
if (str_starts(action, "--"))
|
||||
action = argv[1] + 2;
|
||||
|
||||
if (strcmp(argv[1], "cleanup") == 0) {
|
||||
if (action == "cleanup") {
|
||||
fprintf(stderr, "Cleaning up...\n");
|
||||
unlink(HEADER_FILE);
|
||||
unlink(KERNEL_FILE);
|
||||
@@ -127,7 +130,7 @@ int main(int argc, char *argv[]) {
|
||||
unlink(EXTRA_FILE);
|
||||
unlink(RECV_DTBO_FILE);
|
||||
unlink(DTB_FILE);
|
||||
} else if (argc > 2 && strcmp(argv[1], "sha1") == 0) {
|
||||
} else if (argc > 2 && action == "sha1") {
|
||||
uint8_t sha1[SHA_DIGEST_SIZE];
|
||||
void *buf;
|
||||
size_t size;
|
||||
@@ -137,34 +140,35 @@ int main(int argc, char *argv[]) {
|
||||
printf("%02x", i);
|
||||
printf("\n");
|
||||
munmap(buf, size);
|
||||
} else if (argc > 2 && strcmp(argv[1], "unpack") == 0) {
|
||||
if (strcmp(argv[2], "-h") == 0) {
|
||||
} else if (argc > 2 && action == "unpack") {
|
||||
if (argv[2] == "-h"sv) {
|
||||
if (argc == 3)
|
||||
usage(argv[0]);
|
||||
return unpack(argv[3], true);
|
||||
} else {
|
||||
return unpack(argv[2]);
|
||||
}
|
||||
} else if (argc > 2 && strcmp(argv[1], "repack") == 0) {
|
||||
if (strcmp(argv[2], "-n") == 0) {
|
||||
if (argc == 4)
|
||||
} else if (argc > 2 && action == "repack") {
|
||||
if (argv[2] == "-n"sv) {
|
||||
if (argc == 3)
|
||||
usage(argv[0]);
|
||||
repack(argv[3], argv[4] ? argv[4] : NEW_BOOT, true);
|
||||
} else {
|
||||
repack(argv[2], argv[3] ? argv[3] : NEW_BOOT);
|
||||
}
|
||||
} else if (argc > 2 && strcmp(argv[1], "decompress") == 0) {
|
||||
} else if (argc > 2 && action == "decompress") {
|
||||
decompress(argv[2], argv[3]);
|
||||
} else if (argc > 2 && strncmp(argv[1], "compress", 8) == 0) {
|
||||
compress(argv[1][8] == '=' ? &argv[1][9] : "gzip", argv[2], argv[3]);
|
||||
} else if (argc > 4 && strcmp(argv[1], "hexpatch") == 0) {
|
||||
} else if (argc > 2 && str_starts(action, "compress")) {
|
||||
compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]);
|
||||
} else if (argc > 4 && action == "hexpatch") {
|
||||
return hexpatch(argv[2], argv[3], argv[4]);
|
||||
} else if (argc > 2 && strcmp(argv[1], "cpio") == 0) {
|
||||
if (cpio_commands(argc - 2, argv + 2)) usage(argv[0]);
|
||||
} else if (argc > 2 && strncmp(argv[1], "dtb", 3) == 0) {
|
||||
if (argv[1][3] != '-')
|
||||
} else if (argc > 2 && action == "cpio"sv) {
|
||||
if (cpio_commands(argc - 2, argv + 2))
|
||||
usage(argv[0]);
|
||||
if (dtb_commands(&argv[1][4], argc - 2, argv + 2))
|
||||
} else if (argc > 2 && str_starts(action, "dtb")) {
|
||||
if (action[3] != '-')
|
||||
usage(argv[0]);
|
||||
if (dtb_commands(&action[4], argc - 2, argv + 2))
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
|
Reference in New Issue
Block a user