mirror of
https://github.com/termux/termux-app
synced 2024-06-17 22:57:08 +00:00
139 lines
5.2 KiB
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);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|