[core] Rewrite with NIO2 API (#1016)

This commit is contained in:
vvb2060 2021-08-26 21:29:52 +08:00 committed by GitHub
parent d57617656f
commit 7c706a31d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 73 deletions

View File

@ -16,6 +16,7 @@ import java.nio.file.FileVisitResult;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.OpenOption; import java.nio.file.OpenOption;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
@ -27,13 +28,13 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
class ConfigFileManager { class ConfigFileManager {
static final File basePath = new File("/data/adb/lspd"); static final Path basePath = Paths.get("/data/adb/lspd");
static final File managerApkPath = new File(basePath, "manager.apk"); static final File managerApkPath = basePath.resolve("manager.apk").toFile();
private static final File lockPath = new File(basePath, "lock"); private static final Path lockPath = basePath.resolve("lock");
private static final File configDirPath = new File(basePath, "config"); private static final Path configDirPath = basePath.resolve("config");
static final File dbPath = new File(configDirPath, "modules_config.db"); static final File dbPath = configDirPath.resolve("modules_config.db").toFile();
private static final File logDirPath = new File(basePath, "log"); private static final Path logDirPath = basePath.resolve("log");
private static final File oldLogDirPath = new File(basePath, "log.old"); private static final Path oldLogDirPath = basePath.resolve("log.old");
private static final DateTimeFormatter formatter = private static final DateTimeFormatter formatter =
DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(Utils.getZoneId()); DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(Utils.getZoneId());
@SuppressWarnings("FieldCanBeLocal") @SuppressWarnings("FieldCanBeLocal")
@ -41,17 +42,17 @@ class ConfigFileManager {
static { static {
try { try {
Files.createDirectories(basePath.toPath()); Files.createDirectories(basePath);
SELinux.setFileContext(basePath.getPath(), "u:object_r:system_file:s0"); SELinux.setFileContext(basePath.toString(), "u:object_r:system_file:s0");
Files.createDirectories(configDirPath.toPath()); Files.createDirectories(configDirPath);
Files.createDirectories(logDirPath.toPath()); Files.createDirectories(logDirPath);
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }
} }
static void deleteFolderIfExists(Path target) throws IOException { static void deleteFolderIfExists(Path target) throws IOException {
if (!Files.exists(target)) return; if (Files.notExists(target)) return;
Files.walkFileTree(target, new SimpleFileVisitor<>() { Files.walkFileTree(target, new SimpleFileVisitor<>() {
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
@ -73,16 +74,13 @@ class ConfigFileManager {
}); });
} }
private static void moveFolderIfExists(Path source, Path target) throws IOException {
if (!Files.exists(source)) return;
deleteFolderIfExists(target);
Files.move(source, target);
}
static void moveLogDir() { static void moveLogDir() {
try { try {
moveFolderIfExists(logDirPath.toPath(), oldLogDirPath.toPath()); if (Files.exists(logDirPath)) {
Files.createDirectories(logDirPath.toPath()); deleteFolderIfExists(oldLogDirPath);
Files.move(logDirPath, oldLogDirPath);
}
Files.createDirectories(logDirPath);
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }
@ -93,18 +91,18 @@ class ConfigFileManager {
} }
static File getNewVerboseLogPath() { static File getNewVerboseLogPath() {
return new File(logDirPath, getNewLogFileName("verbose")); return logDirPath.resolve(getNewLogFileName("verbose")).toFile();
} }
static File getNewModulesLogPath() { static File getNewModulesLogPath() {
return new File(logDirPath, getNewLogFileName("modules")); return logDirPath.resolve(getNewLogFileName("modules")).toFile();
} }
static Map<String, ParcelFileDescriptor> getLogs() { static Map<String, ParcelFileDescriptor> getLogs() {
var map = new LinkedHashMap<String, ParcelFileDescriptor>(); var map = new LinkedHashMap<String, ParcelFileDescriptor>();
try { try {
putFds(map, logDirPath.toPath()); putFds(map, logDirPath);
putFds(map, oldLogDirPath.toPath()); putFds(map, oldLogDirPath);
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "getLogs", e); Log.e(TAG, "getLogs", e);
} }
@ -122,37 +120,39 @@ class ConfigFileManager {
}); });
} }
private static String readText(File file) throws IOException { private static String readText(Path file) throws IOException {
return new String(Files.readAllBytes(file.toPath())).trim(); return new String(Files.readAllBytes(file)).trim();
} }
// TODO: Remove after next release // TODO: Remove after next release
@SuppressWarnings("ResultOfMethodCallIgnored")
static void migrateOldConfig(ConfigManager configManager) { static void migrateOldConfig(ConfigManager configManager) {
var miscPath = new File(basePath, "misc_path"); var miscPath = basePath.resolve("misc_path");
var enableResources = new File(configDirPath, "enable_resources"); var enableResources = configDirPath.resolve("enable_resources");
var manager = new File(configDirPath, "manager"); var manager = configDirPath.resolve("manager");
var verboseLog = new File(configDirPath, "verbose_log"); var verboseLog = configDirPath.resolve("verbose_log");
if (miscPath.exists()) { if (Files.exists(miscPath)) {
try { try {
var s = "/data/misc/" + readText(miscPath); var s = "/data/misc/" + readText(miscPath);
configManager.updateModulePrefs("lspd", 0, "config", "misc_path", s); configManager.updateModulePrefs("lspd", 0, "config", "misc_path", s);
miscPath.delete(); Files.delete(miscPath);
} catch (IOException ignored) { } catch (IOException ignored) {
} }
} }
if (enableResources.exists()) { if (Files.exists(enableResources)) {
try { try {
var s = readText(enableResources); var s = readText(enableResources);
var i = Integer.parseInt(s); var i = Integer.parseInt(s);
configManager.updateModulePrefs("lspd", 0, "config", "enable_resources", i == 1); configManager.updateModulePrefs("lspd", 0, "config", "enable_resources", i == 1);
enableResources.delete(); Files.delete(enableResources);
} catch (IOException ignored) { } catch (IOException ignored) {
} }
} }
manager.delete(); try {
verboseLog.delete(); Files.deleteIfExists(manager);
Files.deleteIfExists(verboseLog);
} catch (IOException ignored) {
}
} }
static boolean tryLock() { static boolean tryLock() {
@ -163,7 +163,7 @@ class ConfigFileManager {
var permissions = PosixFilePermissions.asFileAttribute(p); var permissions = PosixFilePermissions.asFileAttribute(p);
try { try {
var lockChannel = FileChannel.open(lockPath.toPath(), openOptions, permissions); var lockChannel = FileChannel.open(lockPath, openOptions, permissions);
locker = new FileLocker(lockChannel); locker = new FileLocker(lockChannel);
return locker.isValid(); return locker.isValid();
} catch (Throwable e) { } catch (Throwable e) {

View File

@ -62,8 +62,12 @@ import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.file.FileVisitResult;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -76,6 +80,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
public class ConfigManager { public class ConfigManager {
@ -224,8 +229,9 @@ public class ConfigManager {
miscPath = string; miscPath = string;
} }
try { try {
Files.createDirectories(Paths.get(miscPath)); Path p = Paths.get(miscPath);
recursivelyContext(new File(miscPath), "u:object_r:magisk_file:s0"); Files.createDirectories(p);
walkFileTree(p, f -> SELinux.setFileContext(f.toString(), "u:object_r:magisk_file:s0"));
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }
@ -746,9 +752,9 @@ public class ConfigManager {
return true; return true;
} }
private boolean removeModuleScopeWithoutCache(Application module) { private void removeModuleScopeWithoutCache(Application module) {
int mid = getModuleId(module.packageName); int mid = getModuleId(module.packageName);
if (mid == -1) return false; if (mid == -1) return;
try { try {
db.beginTransaction(); db.beginTransaction();
db.delete("scope", "mid = ? and user_id = ?", new String[]{String.valueOf(mid), String.valueOf(module.userId)}); db.delete("scope", "mid = ? and user_id = ?", new String[]{String.valueOf(mid), String.valueOf(module.userId)});
@ -758,13 +764,16 @@ public class ConfigManager {
} }
try { try {
removeModulePrefs(module.userId, module.packageName); removeModulePrefs(module.userId, module.packageName);
return true;
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, "removeModulePrefs", e); Log.w(TAG, "removeModulePrefs", e);
return false;
} }
} }
private void removeAppWithoutCache(Application app) {
db.delete("scope", "app_pkg_name = ? AND user_id=?",
new String[]{app.packageName, String.valueOf(app.userId)});
}
public boolean disableModule(String packageName) { public boolean disableModule(String packageName) {
int mid = getModuleId(packageName); int mid = getModuleId(packageName);
if (mid == -1) return false; if (mid == -1) return false;
@ -810,11 +819,6 @@ public class ConfigManager {
cacheScopes(); cacheScopes();
} }
private boolean removeAppWithoutCache(Application app) {
int count = db.delete("scope", "app_pkg_name = ? AND user_id=?", new String[]{app.packageName, String.valueOf(app.userId)});
return count >= 1;
}
public void setResourceHook(boolean resourceHook) { public void setResourceHook(boolean resourceHook) {
updateModulePrefs("lspd", 0, "config", "enable_resources", resourceHook); updateModulePrefs("lspd", 0, "config", "enable_resources", resourceHook);
this.resourceHook = resourceHook; this.resourceHook = resourceHook;
@ -905,35 +909,37 @@ public class ConfigManager {
return module != null && module.appId == uid % PER_USER_RANGE; return module != null && module.appId == uid % PER_USER_RANGE;
} }
private void recursivelyChown(File file, int uid, int gid) throws ErrnoException { private void walkFileTree(Path dir, Consumer<Path> action) throws IOException {
Os.chown(file.toString(), uid, gid); if (Files.notExists(dir)) return;
if (file.isDirectory()) { Files.walkFileTree(dir, new SimpleFileVisitor<>() {
for (File subFile : file.listFiles()) { @Override
recursivelyChown(subFile, uid, gid); public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
} action.accept(dir);
} return FileVisitResult.CONTINUE;
} }
private void recursivelyContext(File file, String context) { @Override
SELinux.setFileContext(file.getPath(), context); public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (file.isDirectory()) { action.accept(file);
for (File subFile : file.listFiles()) { return FileVisitResult.CONTINUE;
recursivelyContext(subFile, context);
}
} }
});
} }
public boolean ensureModulePrefsPermission(int uid, String packageName) { public void ensureModulePrefsPermission(int uid, String packageName) {
if (packageName == null) return false; if (packageName == null) return;
File path = new File(getPrefsPath(packageName, uid)); var path = Paths.get(getPrefsPath(packageName, uid));
try { try {
if (path.exists() && !path.isDirectory()) path.delete(); Files.createDirectories(path);
if (!path.exists()) Files.createDirectories(path.toPath()); walkFileTree(path, p -> {
recursivelyChown(path, uid, 1000); try {
return true; Os.chown(p.toString(), uid, 1000);
} catch (IOException | ErrnoException e) { } catch (ErrnoException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
});
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
return false;
} }
} }