279 lines
12 KiB
Diff
279 lines
12 KiB
Diff
|
From b58a6014d8a49bd17af182ea05862d8bb205959b Mon Sep 17 00:00:00 2001
|
||
|
From: relan <email@hidden>
|
||
|
Date: Sun, 15 Oct 2017 21:52:28 +0300
|
||
|
Subject: [PATCH] Add FileUtil class
|
||
|
|
||
|
Exact copy of android.os.FileUtils functions (from AOSP 7.1.2), only Slog
|
||
|
is replaced with Log.
|
||
|
|
||
|
Use the new FileUtil class to delete directories
|
||
|
|
||
|
Stop using reflection.
|
||
|
|
||
|
Add FileUtils.setPermissions() methods
|
||
|
|
||
|
Those functions can set different permissions for owner and everyone else.
|
||
|
For example FileUtils.setPermissions(path, 7, 1) will mean Unix mode 0711:
|
||
|
read, write, execute for owner; only execute for group and others.
|
||
|
|
||
|
There is no need to set group permissions specifically. When a new app is
|
||
|
being installed, Android creates a new Unix user and group for it. Since
|
||
|
groups aren't shared, they don't actually participate in access rights
|
||
|
checking: when we access our file, "owner" permissions are in effect; when
|
||
|
another app accesses our file, "other" permissions are used.
|
||
|
|
||
|
Use the new FileUtil.setPermissions() methods
|
||
|
|
||
|
---
|
||
|
app/build.gradle | 1 -
|
||
|
.../robv/android/xposed/installer/XposedApp.java | 28 ++++-----
|
||
|
.../installer/installation/FlashDirectly.java | 2 +-
|
||
|
.../android/xposed/installer/util/AssetUtil.java | 13 ++--
|
||
|
.../android/xposed/installer/util/FileUtil.java | 69 +++++++++++++++++++++
|
||
|
.../android/xposed/installer/util/ModuleUtil.java | 5 +-
|
||
|
7 files changed, 90 insertions(+), 28 deletions(-)
|
||
|
delete mode 100644 app/libs/AndroidHiddenAPI.jar
|
||
|
create mode 100644 app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java
|
||
|
|
||
|
diff --git a/app/build.gradle b/app/build.gradle
|
||
|
index d3d07e7..fad9889 100644
|
||
|
--- a/app/build.gradle
|
||
|
+++ b/app/build.gradle
|
||
|
@@ -33,5 +33,4 @@ dependencies {
|
||
|
implementation 'eu.chainfire:libsuperuser:1.0.0.201608240809'
|
||
|
implementation 'com.squareup.picasso:picasso:2.5.2'
|
||
|
implementation 'de.psdev.licensesdialog:licensesdialog:1.8.1'
|
||
|
- compileOnly fileTree(dir: 'libs', include: ['*.jar'])
|
||
|
}
|
||
|
diff --git a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java
|
||
|
index abb8211..1fe78c1 100644
|
||
|
--- a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java
|
||
|
+++ b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java
|
||
|
@@ -11,7 +11,6 @@ import android.net.Uri;
|
||
|
import android.os.Build;
|
||
|
import android.os.Bundle;
|
||
|
import android.os.Environment;
|
||
|
-import android.os.FileUtils;
|
||
|
import android.os.Handler;
|
||
|
import android.preference.PreferenceManager;
|
||
|
import android.support.v4.content.FileProvider;
|
||
|
@@ -20,10 +19,10 @@ import android.util.Log;
|
||
|
import java.io.File;
|
||
|
import java.io.FileInputStream;
|
||
|
import java.io.IOException;
|
||
|
-import java.lang.reflect.Method;
|
||
|
|
||
|
import de.robv.android.xposed.installer.util.AssetUtil;
|
||
|
import de.robv.android.xposed.installer.util.DownloadsUtil;
|
||
|
+import de.robv.android.xposed.installer.util.FileUtil;
|
||
|
import de.robv.android.xposed.installer.util.InstallZipUtil;
|
||
|
import de.robv.android.xposed.installer.util.InstallZipUtil.XposedProp;
|
||
|
import de.robv.android.xposed.installer.util.NotificationUtil;
|
||
|
@@ -124,26 +123,21 @@ public class XposedApp extends Application implements ActivityLifecycleCallbacks
|
||
|
}
|
||
|
|
||
|
private void createDirectories() {
|
||
|
- FileUtils.setPermissions(BASE_DIR, 00711, -1, -1);
|
||
|
- mkdirAndChmod("conf", 00771);
|
||
|
- mkdirAndChmod("log", 00777);
|
||
|
+ FileUtil.setPermissions(BASE_DIR, 7, 1);
|
||
|
+ mkdirAndChmod("conf", 7, 1);
|
||
|
+ mkdirAndChmod("log", 7, 7);
|
||
|
|
||
|
if (Build.VERSION.SDK_INT >= 24) {
|
||
|
- try {
|
||
|
- Method deleteDir = FileUtils.class.getDeclaredMethod("deleteContentsAndDir", File.class);
|
||
|
- deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "bin"));
|
||
|
- deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "conf"));
|
||
|
- deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "log"));
|
||
|
- } catch (ReflectiveOperationException e) {
|
||
|
- Log.w(XposedApp.TAG, "Failed to delete obsolete directories", e);
|
||
|
- }
|
||
|
+ FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "bin"));
|
||
|
+ FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "conf"));
|
||
|
+ FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "log"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- private void mkdirAndChmod(String dir, int permissions) {
|
||
|
- dir = BASE_DIR + dir;
|
||
|
- new File(dir).mkdir();
|
||
|
- FileUtils.setPermissions(dir, permissions, -1, -1);
|
||
|
+ private void mkdirAndChmod(String name, int owner, int other) {
|
||
|
+ File dir = new File(BASE_DIR + name);
|
||
|
+ dir.mkdir();
|
||
|
+ FileUtil.setPermissions(dir, owner, other);
|
||
|
}
|
||
|
|
||
|
public void reloadXposedProp() {
|
||
|
diff --git a/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java b/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java
|
||
|
index e230d3f..fad7f66 100644
|
||
|
--- a/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java
|
||
|
+++ b/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java
|
||
|
@@ -46,7 +46,7 @@ public class FlashDirectly extends Flashable {
|
||
|
ZipEntry entry = zip.getEntry("META-INF/com/google/android/update-binary");
|
||
|
File updateBinaryFile = new File(XposedApp.getInstance().getCacheDir(), "update-binary");
|
||
|
try {
|
||
|
- AssetUtil.writeStreamToFile(zip.getInputStream(entry), updateBinaryFile, 0700);
|
||
|
+ AssetUtil.writeStreamToFile(zip.getInputStream(entry), updateBinaryFile, 7, 0);
|
||
|
} catch (IOException e) {
|
||
|
Log.e(XposedApp.TAG, "Could not extract update-binary", e);
|
||
|
triggerError(callback, FlashCallback.ERROR_INVALID_ZIP);
|
||
|
diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java
|
||
|
index 63b2bc8..5b71de5 100644
|
||
|
--- a/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java
|
||
|
+++ b/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java
|
||
|
@@ -2,7 +2,6 @@ package de.robv.android.xposed.installer.util;
|
||
|
|
||
|
import android.content.res.AssetManager;
|
||
|
import android.os.Build;
|
||
|
-import android.os.FileUtils;
|
||
|
import android.util.Log;
|
||
|
|
||
|
import java.io.File;
|
||
|
@@ -26,12 +25,13 @@ public class AssetUtil {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- public static File writeAssetToFile(AssetManager assets, String assetName, File targetFile, int mode) {
|
||
|
+ public static File writeAssetToFile(AssetManager assets, String assetName,
|
||
|
+ File targetFile, int owner, int other) {
|
||
|
try {
|
||
|
if (assets == null)
|
||
|
assets = XposedApp.getInstance().getAssets();
|
||
|
InputStream in = assets.open(assetName);
|
||
|
- writeStreamToFile(in, targetFile, mode);;
|
||
|
+ writeStreamToFile(in, targetFile, owner, other);
|
||
|
return targetFile;
|
||
|
} catch (IOException e) {
|
||
|
Log.e(XposedApp.TAG, "could not extract asset", e);
|
||
|
@@ -42,7 +42,8 @@ public class AssetUtil {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- public static void writeStreamToFile(InputStream in, File targetFile, int mode) throws IOException {
|
||
|
+ public static void writeStreamToFile(InputStream in, File targetFile,
|
||
|
+ int owner, int other) throws IOException {
|
||
|
FileOutputStream out = new FileOutputStream(targetFile);
|
||
|
|
||
|
byte[] buffer = new byte[1024];
|
||
|
@@ -53,7 +54,7 @@ public class AssetUtil {
|
||
|
in.close();
|
||
|
out.close();
|
||
|
|
||
|
- FileUtils.setPermissions(targetFile.getAbsolutePath(), mode, -1, -1);
|
||
|
+ FileUtil.setPermissions(targetFile.getAbsolutePath(), owner, other);
|
||
|
}
|
||
|
|
||
|
public synchronized static void extractBusybox() {
|
||
|
@@ -61,7 +62,7 @@ public class AssetUtil {
|
||
|
return;
|
||
|
|
||
|
AssetManager assets = null;
|
||
|
- writeAssetToFile(assets, getBinariesFolder() + "busybox-xposed", BUSYBOX_FILE, 00700);
|
||
|
+ writeAssetToFile(assets, getBinariesFolder() + "busybox-xposed", BUSYBOX_FILE, 7, 0);
|
||
|
}
|
||
|
|
||
|
public synchronized static void removeBusybox() {
|
||
|
diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java
|
||
|
new file mode 100644
|
||
|
index 0000000..aacb87f
|
||
|
--- /dev/null
|
||
|
+++ b/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java
|
||
|
@@ -0,0 +1,69 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2006 The Android Open Source Project
|
||
|
+ *
|
||
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
+ * you may not use this file except in compliance with the License.
|
||
|
+ * You may obtain a copy of the License at
|
||
|
+ *
|
||
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||
|
+ *
|
||
|
+ * Unless required by applicable law or agreed to in writing, software
|
||
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
+ * See the License for the specific language governing permissions and
|
||
|
+ * limitations under the License.
|
||
|
+ */
|
||
|
+
|
||
|
+package de.robv.android.xposed.installer.util;
|
||
|
+
|
||
|
+import android.util.Log;
|
||
|
+
|
||
|
+import java.io.File;
|
||
|
+
|
||
|
+import de.robv.android.xposed.installer.XposedApp;
|
||
|
+
|
||
|
+public class FileUtil {
|
||
|
+ public static boolean setPermissions(String path, int owner, int other) {
|
||
|
+ return setPermissions(new File(path), owner, other);
|
||
|
+ }
|
||
|
+
|
||
|
+ public static boolean setPermissions(File path, int owner, int other) {
|
||
|
+ if (!setPermissions(path, other, false) || !setPermissions(path, owner, true)) {
|
||
|
+ Log.w(XposedApp.TAG, "Failed to set permissions " +
|
||
|
+ owner + "/" + other + " for " + path.getPath());
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ return true;
|
||
|
+ }
|
||
|
+
|
||
|
+ private static boolean setPermissions(File path, int perm, boolean ownerOnly) {
|
||
|
+ return path.setReadable((perm & 4) != 0, ownerOnly)
|
||
|
+ && path.setWritable((perm & 2) != 0, ownerOnly)
|
||
|
+ && path.setExecutable((perm & 1) != 0, ownerOnly);
|
||
|
+ }
|
||
|
+
|
||
|
+ public static boolean deleteContentsAndDir(File dir) {
|
||
|
+ if (deleteContents(dir)) {
|
||
|
+ return dir.delete();
|
||
|
+ } else {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ public static boolean deleteContents(File dir) {
|
||
|
+ File[] files = dir.listFiles();
|
||
|
+ boolean success = true;
|
||
|
+ if (files != null) {
|
||
|
+ for (File file : files) {
|
||
|
+ if (file.isDirectory()) {
|
||
|
+ success &= deleteContents(file);
|
||
|
+ }
|
||
|
+ if (!file.delete()) {
|
||
|
+ Log.w(XposedApp.TAG, "Failed to delete " + file);
|
||
|
+ success = false;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return success;
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java
|
||
|
index 9aa8e1d..e38788b 100644
|
||
|
--- a/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java
|
||
|
+++ b/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java
|
||
|
@@ -9,7 +9,6 @@ import android.content.pm.PackageManager;
|
||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||
|
import android.content.pm.ResolveInfo;
|
||
|
import android.graphics.drawable.Drawable;
|
||
|
-import android.os.FileUtils;
|
||
|
import android.util.Log;
|
||
|
import android.widget.Toast;
|
||
|
|
||
|
@@ -223,8 +222,8 @@ public final class ModuleUtil {
|
||
|
modulesList.close();
|
||
|
enabledModulesList.close();
|
||
|
|
||
|
- FileUtils.setPermissions(MODULES_LIST_FILE, 00664, -1, -1);
|
||
|
- FileUtils.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 00664, -1, -1);
|
||
|
+ FileUtil.setPermissions(MODULES_LIST_FILE, 6, 4);
|
||
|
+ FileUtil.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 6, 4);
|
||
|
|
||
|
if (showToast)
|
||
|
showToast(R.string.xposed_module_list_updated);
|
||
|
--
|
||
|
2.14.1
|
||
|
|