termux-app/app/src/updated/java/com/termux/app/TermuxPackageInstaller.java

139 lines
5.2 KiB
Java

package com.termux.app;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Process;
import android.system.Os;
import android.util.Log;
import com.termux.shared.termux.TermuxConstants;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class TermuxPackageInstaller extends BroadcastReceiver {
private static final String LOG_TAG = "termux-package-installer";
@Override
public void onReceive(Context context, Intent intent) {
try {
String packageName = intent.getData().getSchemeSpecificPart();
String action = intent.getAction();
PackageManager packageManager = context.getPackageManager();
if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
ApplicationInfo info = packageManager.getApplicationInfo(packageName, 0);
if (Process.myUid() == info.uid) {
installPackage(context, info);
}
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
if (Process.myUid() == intent.getIntExtra(Intent.EXTRA_UID, -1)) {
uninstallPackage(packageName);
}
}
} catch (Exception e) {
Log.e("termux", "Error in package management: " + e);
}
}
static void installPackage(Context context, ApplicationInfo info) throws Exception {
File filesMappingFile = new File(info.nativeLibraryDir, "libfiles.so");
if (!filesMappingFile.exists()) {
Log.e("termux", "No file mapping at " + filesMappingFile.getAbsolutePath());
return;
}
Log.e("termux", "Installing: " + info.packageName);
BufferedReader reader = new BufferedReader(new FileReader(filesMappingFile));
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split("");
if (parts.length != 2) {
Log.e(LOG_TAG, "Malformed line " + line + " in " + filesMappingFile.getAbsolutePath());
continue;
}
String oldPath = info.nativeLibraryDir + "/" + parts[0];
String newPath = TermuxConstants.TERMUX_PREFIX_DIR_PATH + "/" + parts[1];
TermuxInstaller.ensureDirectoryExists(context, new File(newPath).getParentFile());
Log.e(LOG_TAG, "About to setup link: " + oldPath + "" + newPath);
new File(newPath).delete();
Os.symlink(oldPath, newPath);
}
File symlinksFile = new File(info.nativeLibraryDir, "libsymlinks.so");
if (!symlinksFile.exists()) {
Log.e("termux", "No symlinks mapping at " + symlinksFile.getAbsolutePath());
}
reader = new BufferedReader(new FileReader(symlinksFile));
while ((line = reader.readLine()) != null) {
String[] parts = line.split("");
if (parts.length != 2) {
Log.e(LOG_TAG, "Malformed line " + line + " in " + symlinksFile.getAbsolutePath());
continue;
}
String oldPath = parts[0];
String newPath = TermuxConstants.TERMUX_PREFIX_DIR_PATH + "/" + parts[1];
TermuxInstaller.ensureDirectoryExists(context, new File(newPath).getParentFile());
Log.e(LOG_TAG, "About to setup link: " + oldPath + "" + newPath);
new File(newPath).delete();
Os.symlink(oldPath, newPath);
}
}
private static void uninstallPackage(String packageName) throws IOException {
Log.e(LOG_TAG, "Uninstalling: " + packageName);
// We're currently visiting the whole $PREFIX.
// If we store installed symlinks in installPackage() we could just visit those,
// at the cost of increased complexity and risk for errors.
File prefixDir = new File(TermuxConstants.TERMUX_PREFIX_DIR_PATH);
removeBrokenSymlinks(prefixDir);
}
private static void removeBrokenSymlinks(File parentDir) throws IOException {
File[] children = parentDir.listFiles();
if (children == null) {
return;
}
for (File child : children) {
if (!child.exists()) {
Log.e(LOG_TAG, "Removing broken symlink: " + child.getAbsolutePath());
child.delete();
} else if (child.isDirectory()) {
removeBrokenSymlinks(child);
}
}
}
public static void setupAllInstalledPackages(Context context) {
try {
removeBrokenSymlinks(new File(TermuxConstants.TERMUX_PREFIX_DIR_PATH));
PackageManager packageManager = context.getPackageManager();
for (PackageInfo info : packageManager.getInstalledPackages(0)) {
if ("com.termux".equals(info.sharedUserId)) {
installPackage(context, info.applicationInfo);
}
}
} catch (Exception e) {
Log.e(LOG_TAG, "Error setting up all packages", e);
}
}
}