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

View File

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