[core] Rewrite with NIO2 API (#1016)
This commit is contained in:
parent
d57617656f
commit
7c706a31d4
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||
action.accept(file);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue