package com.amaze.filemanager.utils; /** * Created by arpitkh996 on 25-01-2016. */ import com.amaze.filemanager.exceptions.RootNotPermittedException; import com.amaze.filemanager.filesystem.RootHelper; import java.util.ArrayList; import java.util.regex.Pattern; public class RootUtils { public static final String DATA_APP_DIR = "/data/app"; private static final String LS = "ls -lAnH \"%\" --color=never"; private static final String LSDIR = "ls -land \"%\" --color=never"; public static final String SYSTEM_APP_DIR = "/system/app"; private static final Pattern mLsPattern; static { mLsPattern = Pattern.compile(".[rwxsStT-]{9}\\s+.*"); } public static boolean isValid(String str) { return mLsPattern.matcher(str).matches(); } public static boolean isUnixVirtualDirectory(String str) { return str.startsWith("/proc") || str.startsWith("/sys"); } /** * Get a shell based listing * Context is superuser level shell * @param str * @return */ public static ArrayList<String> getDirListingSu(String str) throws RootNotPermittedException { ArrayList<String> arrayLis=RootHelper.runShellCommand(LS.replace("%", str)); return arrayLis; } /** * Change permissions (owner/group/others) of a specified path * @param path * @param octalNotation octal notation of permission * @throws RootNotPermittedException */ public static void chmod(String path, int octalNotation) throws RootNotPermittedException { String mountPoint = mountFileSystemRW(path); String command = "chmod %d \"%s\""; RootHelper.runShellCommand(String.format(command, octalNotation, path)); if (mountPoint!=null) { // we mounted the filesystem as rw, let's mount it back to ro mountFileSystemRO(mountPoint); } } /** * Mount filesystem associated with path for writable access (rw) * Since we don't have the root of filesystem to remount, we need to parse output of * # mount command. * @param path the path on which action to perform * @return String the root of mount point that was ro, and mounted to rw; null otherwise * @throws RootNotPermittedException */ private static String mountFileSystemRW(String path) throws RootNotPermittedException { String command = "mount"; ArrayList<String> output = RootHelper.runShellCommand(command); String mountPoint = "", types = null; for (String line : output) { String[] words = line.split(" "); if (path.contains(words[2])) { // current found point is bigger than last one, hence not a conflicting one // we're finding the best match, this omits for eg. / and /sys when we're actually // looking for /system if (words[2].length() > mountPoint.length()) { mountPoint = words[2]; types = words[5]; } } } if (!mountPoint.equals("") && types!=null) { // we have the mountpoint, check for mount options if already rw if (types.contains("rw")) { // already a rw filesystem return return null; } else if (types.contains("ro")) { // read-only file system, remount as rw String mountCommand = "mount -o rw,remount " + mountPoint; ArrayList<String> mountOutput = RootHelper.runShellCommand(mountCommand); if (mountOutput.size()!=0) { // command failed, and we got a reason echo'ed return null; } else return mountPoint; } } return null; } /** * Mount path for read-only access (ro) * @param path the root of device/filesystem to be mounted as ro * @throws RootNotPermittedException */ private static void mountFileSystemRO(String path) throws RootNotPermittedException { String command = "umount -r \"" + path + "\""; RootHelper.runShellCommand(command); } /** * Copies file using root * @param source * @param destination * @throws RootNotPermittedException */ public static void copy(String source, String destination) throws RootNotPermittedException { // remounting destination as rw String mountPoint = mountFileSystemRW(destination); RootHelper.runShellCommand("cp \"" + source + "\" \"" + destination + "\""); if (mountPoint!=null) { // we mounted the filesystem as rw, let's mount it back to ro mountFileSystemRO(mountPoint); } } /** * Creates an empty directory using root * @param path path to new directory * @param name name of directory * @throws RootNotPermittedException */ public static void mkDir(String path, String name) throws RootNotPermittedException { String mountPoint = mountFileSystemRW(path); RootHelper.runShellCommand("mkdir \"" + path + "/" + name + "\""); if (mountPoint!=null) { // we mounted the filesystem as rw, let's mount it back to ro mountFileSystemRO(mountPoint); } } /** * Creates an empty file using root * @param path path to new file * @throws RootNotPermittedException */ public static void mkFile(String path) throws RootNotPermittedException { String mountPoint = mountFileSystemRW(path); RootHelper.runShellCommand("touch \"" + path +"\""); if (mountPoint!=null) { // we mounted the filesystem as rw, let's mount it back to ro mountFileSystemRO(mountPoint); } } /** * Returns file permissions in octal notation * Method requires busybox * @param path * @return */ private static int getFilePermissions(String path) throws RootNotPermittedException { String line = RootHelper.runShellCommand("stat -c %a \"" + path + "\"").get(0); return Integer.valueOf(line); } /** * Recursively removes a path with it's contents (if any) * @param path * @return boolean whether file was deleted or not * @throws RootNotPermittedException */ public static boolean delete(String path) throws RootNotPermittedException { String mountPoint = mountFileSystemRW(path); ArrayList<String> result = RootHelper.runShellCommand("rm -rf \"" + path + "\""); if (mountPoint!=null) { // we mounted the filesystem as rw, let's mount it back to ro mountFileSystemRO(mountPoint); } return result.size()!=0; } /*public static boolean isBusyboxAvailable() throws RootNotPermittedException { ArrayList<String> output = RootHelper.runShellCommand("busybox"); return output.size()!=0; }*/ /** * Moves file using root * @param path * @param destination * @throws RootNotPermittedException */ public static void move(String path, String destination) throws RootNotPermittedException { // remounting destination as rw String mountPoint = mountFileSystemRW(destination); //mountOwnerRW(mountPath); RootHelper.runShellCommand("mv \"" + path + "\" \"" + destination + "\""); if (mountPoint!=null) { // we mounted the filesystem as rw, let's mount it back to ro mountFileSystemRO(mountPoint); } } /** * Renames file using root * @param oldPath path to file before rename * @param newPath path to file after rename * @throws RootNotPermittedException * @return if rename was successful or not */ public static boolean rename(String oldPath, String newPath) throws RootNotPermittedException { String mountPoint = mountFileSystemRW(oldPath); ArrayList<String> output = RootHelper.runShellCommand("mv \"" + oldPath + "\" \"" + newPath + "\""); if (mountPoint!=null) { // we mounted the filesystem as rw, let's mount it back to ro mountFileSystemRO(mountPoint); } return output.size()==0; } public static void cat(String sourcePath, String destinationPath) throws RootNotPermittedException { String mountPoint = mountFileSystemRW(destinationPath); RootHelper.runShellCommand("cat \"" + sourcePath + "\" > \"" + destinationPath + "\""); if (mountPoint!=null) { // we mounted the filesystem as rw, let's mount it back to ro mountFileSystemRO(mountPoint); } } public static String parsePermission(String permLine) { int owner = 0; int READ = 4; int WRITE = 2; int EXECUTE = 1; if (permLine.charAt(1) == 'r') { owner += READ; } if (permLine.charAt(2) == 'w') { owner += WRITE; } if (permLine.charAt(3) == 'x') { owner += EXECUTE; } int group = 0; if (permLine.charAt(4) == 'r') { group += READ; } if (permLine.charAt(5) == 'w') { group += WRITE; } if (permLine.charAt(6) == 'x') { group += EXECUTE; } int world = 0; if (permLine.charAt(7) == 'r') { world += READ; } if (permLine.charAt(8) == 'w') { world += WRITE; } if (permLine.charAt(9) == 'x') { world += EXECUTE; } String finalValue = owner + "" + group + "" + world; return finalValue; } }