protected boolean returnPath() { File tmpDir = new File("/data/local/tmp"); if (!tmpDir.exists()) { doExec(new String[] {"mkdir /data/local/tmp"}); } try { InternalVariables.path = new HashSet<String>(); // Try to read from the file. LineNumberReader lnr = null; doExec( new String[] { "dd if=/init.rc of=/data/local/tmp/init.rc", "chmod 0777 /data/local/tmp/init.rc" }); lnr = new LineNumberReader(new FileReader("/data/local/tmp/init.rc")); String line; while ((line = lnr.readLine()) != null) { RootTools.log(line); if (line.contains("export PATH")) { int tmp = line.indexOf("/"); InternalVariables.path = new HashSet<String>(Arrays.asList(line.substring(tmp).split(":"))); return true; } } return false; } catch (Exception e) { if (RootTools.debugMode) { RootTools.log("Error: " + e.getMessage()); e.printStackTrace(); } return false; } }
/** * Sends several shell command as su (attempts to) * * @param commands array of commands to send to the shell * @param sleepTime time to sleep between each command, delay. * @param result injected result object that implements the Result class * @return a <code>LinkedList</code> containing each line that was returned by the shell after * executing or while trying to execute the given commands. You must iterate over this list, * it does not allow random access, so no specifying an index of an item you want, not like * you're going to know that anyways. * @throws InterruptedException * @throws IOException * @throws TimeoutException */ synchronized List<String> sendShell( String[] commands, int sleepTime, Result result, boolean useRoot, int timeout) throws IOException, RootToolsException, TimeoutException { RootTools.log( "Sending " + commands.length + " shell command" + (commands.length > 1 ? "s" : "")); Worker worker = new Worker(this, commands, sleepTime, result, useRoot); worker.start(); try { if (timeout == -1) { timeout = 300000; } worker.join(timeout); // small pause, let things catch up Thread.sleep(RootTools.shellDelay); if (worker.exit != -911) return worker.finalResponse; else throw new TimeoutException(); } catch (InterruptedException ex) { worker.interrupt(); Thread.currentThread().interrupt(); throw new TimeoutException(); } }
public boolean checkRoot() { boolean result = true; // No need to do more shell calls if we already did the checks if (CHECKED_ROOT && !ROOT_AVAILABLE) // We already checked root and it wasn't available return false; if (!ROOT_AVAILABLE) { if (!RootTools.isRootAvailable()) { // TODO: Make a new dialog class that explains root access RootTools.log("Root access isn't available"); result = false; } else if (!RootTools.isAccessGiven()) { RootTools.log("Root access denied by user"); result = false; } else { ROOT_AVAILABLE = true; } } CHECKED_ROOT = true; return result; }
protected ArrayList<Mount> getMounts() throws FileNotFoundException, IOException { LineNumberReader lnr = null; try { lnr = new LineNumberReader(new FileReader("/proc/mounts")); String line; ArrayList<Mount> mounts = new ArrayList<Mount>(); while ((line = lnr.readLine()) != null) { RootTools.log(line); String[] fields = line.split(" "); mounts.add( new Mount( new File(fields[0]), // device new File(fields[1]), // mountPoint fields[2], // fstype fields[3] // flags )); } return mounts; } finally { // no need to do anything here. } }
public void run() { DataOutputStream os = null; InputStreamReader osRes = null; InputStreamReader osErr = null; try { if (executer.process == null) { Runtime.getRuntime().gc(); if (RootTools.customShell.equals("")) { executer.process = Runtime.getRuntime().exec(useRoot ? "su" : "sh"); RootTools.log(useRoot ? "Using Root" : "Using sh"); } else { executer.process = Runtime.getRuntime().exec(RootTools.customShell); RootTools.log("Using custom shell: " + RootTools.customShell); } if (null != executer.result) { executer.result.setProcess(executer.process); } } os = new DataOutputStream(executer.process.getOutputStream()); osRes = new InputStreamReader(executer.process.getInputStream()); osErr = new InputStreamReader(executer.process.getErrorStream()); BufferedReader reader = new BufferedReader(osRes); BufferedReader reader_error = new BufferedReader(osErr); List<String> response = null; if (null == executer.result) { response = new LinkedList<String>(); } try { // Doing Stuff ;) for (String single : commands) { RootTools.log("Shell command: " + single); os.writeBytes(single + "\n"); os.flush(); Thread.sleep(sleepTime); } os.writeBytes("exit \n"); os.flush(); String line = reader.readLine(); String line_error = reader_error.readLine(); while (line != null) { if (null == executer.result) { response.add(line); } else { executer.result.process(line); } RootTools.log("input stream: " + line); line = reader.readLine(); } RootTools.log("Done reading input stream"); while (line_error != null) { if (null == executer.result) { response.add(line_error); } else { executer.result.processError(line_error); } RootTools.log("error stream: " + line_error); line_error = reader_error.readLine(); } RootTools.log("Done reading error stream"); } catch (Exception ex) { if (RootTools.debugMode) { RootTools.log("Error: " + ex.getMessage()); } if (null != executer.result) { executer.result.onFailure(ex); } } finally { RootTools.log("In finally block"); if (executer.process != null) { RootTools.log("Getting Exit"); finalResponse = response; exit = -1; exit = executer.process.waitFor(); RootTools.log("Exit done..."); RootTools.lastExitCode = exit; if (null != executer.result) { executer.result.onComplete(exit); } else { response.add(Integer.toString(exit)); } } } } catch (InterruptedException ignore) { return; } catch (Exception e) { if (RootTools.debugMode) { e.printStackTrace(); RootTools.log("Error: " + e.getMessage()); } } finally { try { if (os != null) { os.writeBytes("exit \n"); os.flush(); os.close(); os = null; } if (osRes != null) { osRes.close(); osRes = null; } if (osErr != null) { osErr.close(); osErr = null; } } catch (Exception ignore) { } executer.closeShell(); } }
/** * This will take a path, which can contain the file name as well, and attempt to remount the * underlying partition. * * <p>For example, passing in the following string: * "/system/bin/some/directory/that/really/would/never/exist" will result in /system ultimately * being remounted. However, keep in mind that the longer the path you supply, the more work this * has to do, and the slower it will run. * * @param file file path * @param mountType mount type: pass in RO (Read only) or RW (Read Write) * @return a <code>boolean</code> which indicates whether or not the partition has been remounted * as specified. */ protected boolean remount(String file, String mountType) { // if the path has a trailing slash get rid of it. if (file.endsWith("/") && !file.equals("/")) { file = file.substring(0, file.lastIndexOf("/")); } // Make sure that what we are trying to remount is in the mount list. boolean foundMount = false; while (!foundMount) { try { for (Mount mount : RootTools.getMounts()) { RootTools.log(mount.getMountPoint().toString()); if (file.equals(mount.getMountPoint().toString())) { foundMount = true; break; } } } catch (Exception e) { if (RootTools.debugMode) { e.printStackTrace(); } return false; } if (!foundMount) { try { file = (new File(file).getParent()).toString(); } catch (Exception e) { e.printStackTrace(); return false; } } } Mount mountPoint = findMountPointRecursive(file); RootTools.log( InternalVariables.TAG, "Remounting " + mountPoint.getMountPoint().getAbsolutePath() + " as " + mountType.toLowerCase()); final boolean isMountMode = mountPoint.getFlags().contains(mountType.toLowerCase()); if (!isMountMode) { // grab an instance of the internal class try { CommandCapture command = new CommandCapture( 0, "busybox mount -o remount," + mountType.toLowerCase() + " " + mountPoint.getDevice().getAbsolutePath() + " " + mountPoint.getMountPoint().getAbsolutePath(), "toolbox mount -o remount," + mountType.toLowerCase() + " " + mountPoint.getDevice().getAbsolutePath() + " " + mountPoint.getMountPoint().getAbsolutePath(), "mount -o remount," + mountType.toLowerCase() + " " + mountPoint.getDevice().getAbsolutePath() + " " + mountPoint.getMountPoint().getAbsolutePath(), "/system/bin/toolbox mount -o remount," + mountType.toLowerCase() + " " + mountPoint.getDevice().getAbsolutePath() + " " + mountPoint.getMountPoint().getAbsolutePath()); Shell.startRootShell().add(command); command.waitForFinish(); } catch (Exception e) { } mountPoint = findMountPointRecursive(file); } Log.i(InternalVariables.TAG, mountPoint.getFlags() + " AND " + mountType.toLowerCase()); if (mountPoint.getFlags().contains(mountType.toLowerCase())) { RootTools.log(mountPoint.getFlags().toString()); return true; } else { RootTools.log(mountPoint.getFlags().toString()); return false; } }
protected void doExec(String[] commands) { Process process = null; DataOutputStream os = null; InputStreamReader osRes = null; try { process = Runtime.getRuntime().exec("su"); os = new DataOutputStream(process.getOutputStream()); osRes = new InputStreamReader(process.getInputStream()); BufferedReader reader = new BufferedReader(osRes); // Doing Stuff ;) for (String single : commands) { os.writeBytes(single + "\n"); os.flush(); } os.writeBytes("exit \n"); os.flush(); String line = reader.readLine(); while (line != null) { if (commands[0].equals("id")) { Set<String> ID = new HashSet<String>(Arrays.asList(line.split(" "))); for (String id : ID) { if (id.toLowerCase().contains("uid=0")) { InternalVariables.accessGiven = true; Log.i(InternalVariables.TAG, "Access Given"); break; } } if (!InternalVariables.accessGiven) { Log.i(InternalVariables.TAG, "Access Denied?"); } } if (commands[0].equals("df") && line.contains(InternalVariables.getSpaceFor)) { InternalVariables.space = line.split(" "); } RootTools.log(line); line = reader.readLine(); } process.waitFor(); } catch (Exception e) { if (RootTools.debugMode) { RootTools.log("Error: " + e.getMessage()); e.printStackTrace(); } } finally { try { if (os != null) { os.close(); } if (osRes != null) { osRes.close(); } process.destroy(); } catch (Exception e) { if (RootTools.debugMode) { RootTools.log("Error: " + e.getMessage()); e.printStackTrace(); } } } }