Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
c68e37a8
Commit
c68e37a8
authored
Aug 22, 2016
by
dvdandroid
Committed by
topjohnwu
Aug 22, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use libsuperuser lib
parent
e66496ea
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
11 additions
and
2045 deletions
+11
-2045
build.gradle
app/build.gradle
+2
-1
MainActivity.java
app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.java
+0
-1
Utils.java
app/src/main/java/com/topjohnwu/magisk/ui/utils/Utils.java
+8
-16
.gitignore
lib/RootCommands/.gitignore
+0
-2
build.gradle
lib/RootCommands/build.gradle
+0
-20
AndroidManifest.xml
lib/RootCommands/src/main/AndroidManifest.xml
+0
-6
Mount.java
.../main/java/org/sufficientlysecure/rootcommands/Mount.java
+0
-58
Remounter.java
...n/java/org/sufficientlysecure/rootcommands/Remounter.java
+0
-189
RootCommands.java
...ava/org/sufficientlysecure/rootcommands/RootCommands.java
+0
-49
Shell.java
.../main/java/org/sufficientlysecure/rootcommands/Shell.java
+0
-348
SystemCommands.java
...a/org/sufficientlysecure/rootcommands/SystemCommands.java
+0
-120
Toolbox.java
...ain/java/org/sufficientlysecure/rootcommands/Toolbox.java
+0
-772
Command.java
.../org/sufficientlysecure/rootcommands/command/Command.java
+0
-170
ExecutableCommand.java
...cientlysecure/rootcommands/command/ExecutableCommand.java
+0
-65
SimpleCommand.java
...ufficientlysecure/rootcommands/command/SimpleCommand.java
+0
-43
SimpleExecutableCommand.java
...ysecure/rootcommands/command/SimpleExecutableCommand.java
+0
-45
BrokenBusyboxException.java
...entlysecure/rootcommands/util/BrokenBusyboxException.java
+0
-32
Utils.java
.../java/org/sufficientlysecure/rootcommands/util/Utils.java
+0
-107
settings.gradle
settings.gradle
+1
-1
No files found.
app/build.gradle
View file @
c68e37a8
...
...
@@ -22,10 +22,11 @@ android {
dependencies
{
compile
fileTree
(
include:
[
'*.jar'
],
dir:
'libs'
)
compile
project
(
':lib:RootCommands'
)
compile
'com.android.support:recyclerview-v7:24.2.0'
compile
'com.android.support:cardview-v7:24.2.0'
compile
'com.android.support:design:24.2.0'
compile
'eu.chainfire:libsuperuser:1.0.0.201607041850'
compile
'com.jakewharton:butterknife:8.2.1'
apt
'com.jakewharton:butterknife-compiler:8.2.1'
}
app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.java
View file @
c68e37a8
...
...
@@ -60,7 +60,6 @@ public class MainActivity extends Activity {
magiskVersion
.
setText
(
getString
(
R
.
string
.
magisk_version
,
executeCommand
(
"getprop magisk.version"
)));
selinuxStatus
.
setText
(
selinux
);
assert
selinux
!=
null
;
if
(
selinux
.
equals
(
"Enforcing"
))
{
selinuxStatus
.
setTextColor
(
Color
.
GREEN
);
selinuxToggle
.
setChecked
(
true
);
...
...
app/src/main/java/com/topjohnwu/magisk/ui/utils/Utils.java
View file @
c68e37a8
package
com
.
topjohnwu
.
magisk
.
ui
.
utils
;
import
org.sufficientlysecure.rootcommands.Shell
;
import
org.sufficientlysecure.rootcommands.command.SimpleCommand
;
import
java.util.List
;
import
java.io.IOException
;
import
java.util.concurrent.TimeoutException
;
import
eu.chainfire.libsuperuser.Shell
;
public
class
Utils
{
public
static
String
executeCommand
(
String
...
commands
)
{
try
{
Shell
shell
=
Shell
.
startRootShell
();
SimpleCommand
command
=
new
SimpleCommand
(
commands
);
shell
.
add
(
command
).
waitForFinish
();
List
<
String
>
result
=
Shell
.
SU
.
run
(
commands
);
String
output
=
command
.
getOutput
();
output
=
output
.
replaceAll
(
"\n"
,
""
);
shell
.
close
();
return
output
;
}
catch
(
IOException
|
TimeoutException
e
)
{
return
""
;
StringBuilder
builder
=
new
StringBuilder
();
for
(
String
s
:
result
)
{
builder
.
append
(
s
);
}
return
builder
.
toString
();
}
}
lib/RootCommands/.gitignore
deleted
100644 → 0
View file @
e66496ea
build/
*.iml
\ No newline at end of file
lib/RootCommands/build.gradle
deleted
100644 → 0
View file @
e66496ea
apply
plugin:
'com.android.library'
buildscript
{
repositories
{
mavenCentral
()
}
dependencies
{
classpath
'com.android.tools.build:gradle:2.1.3'
}
}
android
{
compileSdkVersion
24
buildToolsVersion
"24.0.1"
defaultConfig
{
minSdkVersion
7
targetSdkVersion
24
}
}
lib/RootCommands/src/main/AndroidManifest.xml
deleted
100644 → 0
View file @
e66496ea
<?xml version="1.0" encoding="utf-8"?>
<manifest
package=
"org.sufficientlysecure.rootcommands"
>
<application/>
</manifest>
\ No newline at end of file
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Mount.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (c) 2012 Stephen Erickson, Chris Ravenscroft, Adam Shanks (RootTools)
*
* 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
org
.
sufficientlysecure
.
rootcommands
;
import
java.io.File
;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.Set
;
public
class
Mount
{
protected
final
File
mDevice
;
protected
final
File
mMountPoint
;
protected
final
String
mType
;
protected
final
Set
<
String
>
mFlags
;
Mount
(
File
device
,
File
path
,
String
type
,
String
flagsStr
)
{
mDevice
=
device
;
mMountPoint
=
path
;
mType
=
type
;
mFlags
=
new
HashSet
<
String
>(
Arrays
.
asList
(
flagsStr
.
split
(
","
)));
}
public
File
getDevice
()
{
return
mDevice
;
}
public
File
getMountPoint
()
{
return
mMountPoint
;
}
public
String
getType
()
{
return
mType
;
}
public
Set
<
String
>
getFlags
()
{
return
mFlags
;
}
@Override
public
String
toString
()
{
return
String
.
format
(
"%s on %s type %s %s"
,
mDevice
,
mMountPoint
,
mType
,
mFlags
);
}
}
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Remounter.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (c) 2012 Stephen Erickson, Chris Ravenscroft, Adam Shanks (RootTools)
*
* 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
org
.
sufficientlysecure
.
rootcommands
;
import
android.util.Log
;
import
org.sufficientlysecure.rootcommands.command.SimpleCommand
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.IOException
;
import
java.io.LineNumberReader
;
import
java.util.ArrayList
;
import
java.util.Locale
;
//no modifier, this means it is package-private. Only our internal classes can use this.
class
Remounter
{
private
Shell
shell
;
public
Remounter
(
Shell
shell
)
{
super
();
this
.
shell
=
shell
;
}
/**
* This will return an ArrayList of the class Mount. The class mount contains the following
* property's: device mountPoint type flags
* <p>
* These will provide you with any information you need to work with the mount points.
*
* @return <code>ArrayList<Mount></code> an ArrayList of the class Mount.
* @throws Exception if we cannot return the mount points.
*/
protected
static
ArrayList
<
Mount
>
getMounts
()
throws
Exception
{
final
String
tempFile
=
"/data/local/RootToolsMounts"
;
// copy /proc/mounts to tempfile. Directly reading it does not work on 4.3
Shell
shell
=
Shell
.
startRootShell
();
Toolbox
tb
=
new
Toolbox
(
shell
);
tb
.
copyFile
(
"/proc/mounts"
,
tempFile
,
false
,
false
);
tb
.
setFilePermissions
(
tempFile
,
"777"
);
shell
.
close
();
LineNumberReader
lnr
=
null
;
lnr
=
new
LineNumberReader
(
new
FileReader
(
tempFile
));
String
line
;
ArrayList
<
Mount
>
mounts
=
new
ArrayList
<
Mount
>();
while
((
line
=
lnr
.
readLine
())
!=
null
)
{
Log
.
d
(
RootCommands
.
TAG
,
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
));
}
lnr
.
close
();
return
mounts
;
}
/**
* 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
:
getMounts
())
{
Log
.
d
(
RootCommands
.
TAG
,
mount
.
getMountPoint
().
toString
());
if
(
file
.
equals
(
mount
.
getMountPoint
().
toString
()))
{
foundMount
=
true
;
break
;
}
}
}
catch
(
Exception
e
)
{
Log
.
e
(
RootCommands
.
TAG
,
"Exception"
,
e
);
return
false
;
}
if
(!
foundMount
)
{
try
{
file
=
(
new
File
(
file
).
getParent
()).
toString
();
}
catch
(
Exception
e
)
{
Log
.
e
(
RootCommands
.
TAG
,
"Exception"
,
e
);
return
false
;
}
}
}
Mount
mountPoint
=
findMountPointRecursive
(
file
);
Log
.
d
(
RootCommands
.
TAG
,
"Remounting "
+
mountPoint
.
getMountPoint
().
getAbsolutePath
()
+
" as "
+
mountType
.
toLowerCase
(
Locale
.
US
));
final
boolean
isMountMode
=
mountPoint
.
getFlags
().
contains
(
mountType
.
toLowerCase
(
Locale
.
US
));
if
(!
isMountMode
)
{
// grab an instance of the internal class
try
{
SimpleCommand
command
=
new
SimpleCommand
(
"busybox mount -o remount,"
+
mountType
.
toLowerCase
(
Locale
.
US
)
+
" "
+
mountPoint
.
getDevice
().
getAbsolutePath
()
+
" "
+
mountPoint
.
getMountPoint
().
getAbsolutePath
(),
"toolbox mount -o remount,"
+
mountType
.
toLowerCase
(
Locale
.
US
)
+
" "
+
mountPoint
.
getDevice
().
getAbsolutePath
()
+
" "
+
mountPoint
.
getMountPoint
().
getAbsolutePath
(),
"mount -o remount,"
+
mountType
.
toLowerCase
(
Locale
.
US
)
+
" "
+
mountPoint
.
getDevice
().
getAbsolutePath
()
+
" "
+
mountPoint
.
getMountPoint
().
getAbsolutePath
(),
"/system/bin/toolbox mount -o remount,"
+
mountType
.
toLowerCase
(
Locale
.
US
)
+
" "
+
mountPoint
.
getDevice
().
getAbsolutePath
()
+
" "
+
mountPoint
.
getMountPoint
().
getAbsolutePath
());
// execute on shell
shell
.
add
(
command
).
waitForFinish
();
}
catch
(
Exception
e
)
{
}
mountPoint
=
findMountPointRecursive
(
file
);
}
if
(
mountPoint
!=
null
)
{
Log
.
d
(
RootCommands
.
TAG
,
mountPoint
.
getFlags
()
+
" AND "
+
mountType
.
toLowerCase
(
Locale
.
US
));
if
(
mountPoint
.
getFlags
().
contains
(
mountType
.
toLowerCase
(
Locale
.
US
)))
{
Log
.
d
(
RootCommands
.
TAG
,
mountPoint
.
getFlags
().
toString
());
return
true
;
}
else
{
Log
.
d
(
RootCommands
.
TAG
,
mountPoint
.
getFlags
().
toString
());
}
}
else
{
Log
.
d
(
RootCommands
.
TAG
,
"mountPoint is null"
);
}
return
false
;
}
private
Mount
findMountPointRecursive
(
String
file
)
{
try
{
ArrayList
<
Mount
>
mounts
=
getMounts
();
for
(
File
path
=
new
File
(
file
);
path
!=
null
;
)
{
for
(
Mount
mount
:
mounts
)
{
if
(
mount
.
getMountPoint
().
equals
(
path
))
{
return
mount
;
}
}
}
return
null
;
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
e
);
}
catch
(
Exception
e
)
{
Log
.
e
(
RootCommands
.
TAG
,
"Exception"
,
e
);
}
return
null
;
}
}
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/RootCommands.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
org
.
sufficientlysecure
.
rootcommands
;
import
android.util.Log
;
public
class
RootCommands
{
public
static
final
String
TAG
=
"RootCommands"
;
public
static
boolean
DEBUG
=
false
;
public
static
int
DEFAULT_TIMEOUT
=
10000
;
/**
* General method to check if user has su binary and accepts root access for this program!
*
* @return true if everything worked
*/
public
static
boolean
rootAccessGiven
()
{
boolean
rootAccess
=
false
;
try
{
Shell
rootShell
=
Shell
.
startRootShell
();
Toolbox
tb
=
new
Toolbox
(
rootShell
);
if
(
tb
.
isRootAccessGiven
())
{
rootAccess
=
true
;
}
rootShell
.
close
();
}
catch
(
Exception
e
)
{
Log
.
e
(
TAG
,
"Problem while checking for root access!"
,
e
);
}
return
rootAccess
;
}
}
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Shell.java
deleted
100644 → 0
View file @
e66496ea
This diff is collapsed.
Click to expand it.
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/SystemCommands.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
org
.
sufficientlysecure
.
rootcommands
;
import
android.annotation.TargetApi
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.location.LocationManager
;
import
android.os.PowerManager
;
import
android.provider.Settings
;
/**
* This methods work when the apk is installed as a system app (under /system/app)
*/
public
class
SystemCommands
{
Context
context
;
public
SystemCommands
(
Context
context
)
{
super
();
this
.
context
=
context
;
}
/**
* Get GPS status
*/
public
boolean
getGPS
()
{
return
((
LocationManager
)
context
.
getSystemService
(
Context
.
LOCATION_SERVICE
))
.
isProviderEnabled
(
LocationManager
.
GPS_PROVIDER
);
}
/**
* Enable/Disable GPS
*
* @param value
*/
@TargetApi
(
8
)
public
void
setGPS
(
boolean
value
)
{
ContentResolver
localContentResolver
=
context
.
getContentResolver
();
Settings
.
Secure
.
setLocationProviderEnabled
(
localContentResolver
,
LocationManager
.
GPS_PROVIDER
,
value
);
}
/**
* TODO: Not ready yet
*/
@TargetApi
(
8
)
public
void
reboot
()
{
PowerManager
pm
=
(
PowerManager
)
context
.
getSystemService
(
Context
.
POWER_SERVICE
);
pm
.
reboot
(
"recovery"
);
pm
.
reboot
(
null
);
// not working:
// reboot(null);
}
/**
* Reboot the device immediately, passing 'reason' (may be null) to the underlying __reboot
* system call. Should not return.
*
* Taken from com.android.server.PowerManagerService.reboot
*/
// public void reboot(String reason) {
//
// // final String finalReason = reason;
// Runnable runnable = new Runnable() {
// public void run() {
// synchronized (this) {
// // ShutdownThread.reboot(mContext, finalReason, false);
// try {
// Class<?> clazz = Class.forName("com.android.internal.app.ShutdownThread");
//
// // if (mReboot) {
// Method method = clazz.getMethod("reboot", Context.class, String.class,
// Boolean.TYPE);
// method.invoke(null, context, null, false);
//
// // if (mReboot) {
// // Method method = clazz.getMethod("reboot", Context.class, String.class,
// // Boolean.TYPE);
// // method.invoke(null, mContext, mReason, mConfirm);
// // } else {
// // Method method = clazz.getMethod("shutdown", Context.class, Boolean.TYPE);
// // method.invoke(null, mContext, mConfirm);
// // }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
// }
// };
// // ShutdownThread must run on a looper capable of displaying the UI.
// mHandler.post(runnable);
//
// // PowerManager.reboot() is documented not to return so just wait for the inevitable.
// // synchronized (runnable) {
// // while (true) {
// // try {
// // runnable.wait();
// // } catch (InterruptedException e) {
// // }
// // }
// // }
// }
}
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/Toolbox.java
deleted
100644 → 0
View file @
e66496ea
This diff is collapsed.
Click to expand it.
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/Command.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (c) 2012 Stephen Erickson, Chris Ravenscroft, Adam Shanks, Jeremy Lakeman (RootTools)
*
* 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
org
.
sufficientlysecure
.
rootcommands
.
command
;
import
android.util.Log
;
import
org.sufficientlysecure.rootcommands.RootCommands
;
import
org.sufficientlysecure.rootcommands.Shell
;
import
org.sufficientlysecure.rootcommands.util.BrokenBusyboxException
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.util.concurrent.TimeoutException
;
public
abstract
class
Command
{
final
String
command
[];
boolean
finished
=
false
;
boolean
brokenBusyboxDetected
=
false
;
int
exitCode
;
int
id
;
int
timeout
=
RootCommands
.
DEFAULT_TIMEOUT
;
Shell
shell
=
null
;
public
Command
(
String
...
command
)
{
this
.
command
=
command
;
}
public
Command
(
int
timeout
,
String
...
command
)
{
this
.
command
=
command
;
this
.
timeout
=
timeout
;
}
/**
* This is called from Shell after adding it
*
* @param shell
* @param id
*/
public
void
addedToShell
(
Shell
shell
,
int
id
)
{
this
.
shell
=
shell
;
this
.
id
=
id
;
}
/**
* Gets command string executed on the shell
*
* @return
*/
public
String
getCommand
()
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
command
.
length
;
i
++)
{
// redirect stderr to stdout
sb
.
append
(
command
[
i
]
+
" 2>&1"
);
sb
.
append
(
'\n'
);
}
Log
.
d
(
RootCommands
.
TAG
,
"Sending command(s): "
+
sb
.
toString
());
return
sb
.
toString
();
}
public
void
writeCommand
(
OutputStream
out
)
throws
IOException
{
out
.
write
(
getCommand
().
getBytes
());
}
public
void
processOutput
(
String
line
)
{
Log
.
d
(
RootCommands
.
TAG
,
"ID: "
+
id
+
", Output: "
+
line
);
/*
* Try to detect broken toolbox/busybox binaries (see
* https://code.google.com/p/busybox-android/issues/detail?id=1)
*
* It is giving "Value too large for defined data type" on certain file operations (e.g. ls
* and chown) in certain directories (e.g. /data/data)
*/
if
(
line
.
contains
(
"Value too large for defined data type"
))
{
Log
.
e
(
RootCommands
.
TAG
,
"Busybox is broken with high probability due to line: "
+
line
);
brokenBusyboxDetected
=
true
;
}
// now execute specific output parsing
output
(
id
,
line
);
}
public
abstract
void
output
(
int
id
,
String
line
);
public
void
processAfterExecution
(
int
exitCode
)
{
Log
.
d
(
RootCommands
.
TAG
,
"ID: "
+
id
+
", ExitCode: "
+
exitCode
);
afterExecution
(
id
,
exitCode
);
}
public
abstract
void
afterExecution
(
int
id
,
int
exitCode
);
public
void
commandFinished
(
int
id
)
{
Log
.
d
(
RootCommands
.
TAG
,
"Command "
+
id
+
" finished."
);
}
public
void
setExitCode
(
int
code
)
{
synchronized
(
this
)
{
exitCode
=
code
;
finished
=
true
;
commandFinished
(
id
);
this
.
notifyAll
();
}
}
/**
* Close the shell
*
* @param reason
*/
public
void
terminate
(
String
reason
)
{
try
{
shell
.
close
();
Log
.
d
(
RootCommands
.
TAG
,
"Terminating the shell."
);
terminated
(
reason
);
}
catch
(
IOException
e
)
{
}
}
public
void
terminated
(
String
reason
)
{
setExitCode
(-
1
);
Log
.
d
(
RootCommands
.
TAG
,
"Command "
+
id
+
" did not finish, because of "
+
reason
);
}
/**
* Waits for this command to finish and forwards exitCode into afterExecution method
*
* @throws TimeoutException
* @throws BrokenBusyboxException
*/
public
void
waitForFinish
()
throws
TimeoutException
,
BrokenBusyboxException
{
synchronized
(
this
)
{
while
(!
finished
)
{
try
{
this
.
wait
(
timeout
);
}
catch
(
InterruptedException
e
)
{
Log
.
e
(
RootCommands
.
TAG
,
"InterruptedException in waitForFinish()"
,
e
);
}
if
(!
finished
)
{
finished
=
true
;
terminate
(
"Timeout"
);
throw
new
TimeoutException
(
"Timeout has occurred."
);
}
}
if
(
brokenBusyboxDetected
)
{
throw
new
BrokenBusyboxException
();
}
processAfterExecution
(
exitCode
);
}
}
}
\ No newline at end of file
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/ExecutableCommand.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
org
.
sufficientlysecure
.
rootcommands
.
command
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.os.Build
;
import
java.io.File
;
public
abstract
class
ExecutableCommand
extends
Command
{
public
static
final
String
EXECUTABLE_PREFIX
=
"lib"
;
public
static
final
String
EXECUTABLE_SUFFIX
=
"_exec.so"
;
/**
* This class provides a way to use your own binaries!
* <p>
* Include your own executables, renamed from * to lib*_exec.so, in your libs folder under the
* architecture directories. Now they will be deployed by Android the same way libraries are
* deployed!
* <p>
* See README for more information how to use your own executables!
*
* @param context
* @param executableName
* @param parameters
*/
public
ExecutableCommand
(
Context
context
,
String
executableName
,
String
parameters
)
{
super
(
getLibDirectory
(
context
)
+
File
.
separator
+
EXECUTABLE_PREFIX
+
executableName
+
EXECUTABLE_SUFFIX
+
" "
+
parameters
);
}
/**
* Get full path to lib directory of app
*
* @return dir as String
*/
@SuppressLint
(
"NewApi"
)
private
static
String
getLibDirectory
(
Context
context
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
9
)
{
return
context
.
getApplicationInfo
().
nativeLibraryDir
;
}
else
{
return
context
.
getApplicationInfo
().
dataDir
+
File
.
separator
+
"lib"
;
}
}
public
abstract
void
output
(
int
id
,
String
line
);
public
abstract
void
afterExecution
(
int
id
,
int
exitCode
);
}
\ No newline at end of file
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleCommand.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
org
.
sufficientlysecure
.
rootcommands
.
command
;
public
class
SimpleCommand
extends
Command
{
private
StringBuilder
sb
=
new
StringBuilder
();
public
SimpleCommand
(
String
...
command
)
{
super
(
command
);
}
@Override
public
void
output
(
int
id
,
String
line
)
{
sb
.
append
(
line
).
append
(
'\n'
);
}
@Override
public
void
afterExecution
(
int
id
,
int
exitCode
)
{
}
public
String
getOutput
()
{
return
sb
.
toString
();
}
public
int
getExitCode
()
{
return
exitCode
;
}
}
\ No newline at end of file
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/command/SimpleExecutableCommand.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
org
.
sufficientlysecure
.
rootcommands
.
command
;
import
android.content.Context
;
public
class
SimpleExecutableCommand
extends
ExecutableCommand
{
private
StringBuilder
sb
=
new
StringBuilder
();
public
SimpleExecutableCommand
(
Context
context
,
String
executableName
,
String
parameters
)
{
super
(
context
,
executableName
,
parameters
);
}
@Override
public
void
output
(
int
id
,
String
line
)
{
sb
.
append
(
line
).
append
(
'\n'
);
}
@Override
public
void
afterExecution
(
int
id
,
int
exitCode
)
{
}
public
String
getOutput
()
{
return
sb
.
toString
();
}
public
int
getExitCode
()
{
return
exitCode
;
}
}
\ No newline at end of file
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/BrokenBusyboxException.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
org
.
sufficientlysecure
.
rootcommands
.
util
;
import
java.io.IOException
;
public
class
BrokenBusyboxException
extends
IOException
{
private
static
final
long
serialVersionUID
=
8337358201589488409L
;
public
BrokenBusyboxException
()
{
super
();
}
public
BrokenBusyboxException
(
String
detailMessage
)
{
super
(
detailMessage
);
}
}
lib/RootCommands/src/main/java/org/sufficientlysecure/rootcommands/util/Utils.java
deleted
100644 → 0
View file @
e66496ea
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (c) 2012 Michael Elsdörfer (Android Autostarts)
* Copyright (c) 2012 Stephen Erickson, Chris Ravenscroft, Adam Shanks (RootTools)
*
* 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
org
.
sufficientlysecure
.
rootcommands
.
util
;
import
android.util.Log
;
import
org.sufficientlysecure.rootcommands.RootCommands
;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Map
;
public
class
Utils
{
/*
* The emulator and ADP1 device both have a su binary in /system/xbin/su, but it doesn't allow
* apps to use it (su app_29 $ su su: uid 10029 not allowed to su).
*
* Cyanogen used to have su in /system/bin/su, in newer versions it's a symlink to
* /system/xbin/su.
*
* The Archos tablet has it in /data/bin/su, since they don't have write access to /system yet.
*/
static
final
String
[]
BinaryPlaces
=
{
"/data/bin/"
,
"/system/bin/"
,
"/system/xbin/"
,
"/sbin/"
,
"/data/local/xbin/"
,
"/data/local/bin/"
,
"/system/sd/xbin/"
,
"/system/bin/failsafe/"
,
"/data/local/"
};
/**
* Determine the path of the su executable.
* <p>
* Code from https://github.com/miracle2k/android-autostarts, use under Apache License was
* agreed by Michael Elsdörfer
*/
public
static
String
getSuPath
()
{
for
(
String
p
:
BinaryPlaces
)
{
File
su
=
new
File
(
p
+
"su"
);
if
(
su
.
exists
())
{
Log
.
d
(
RootCommands
.
TAG
,
"su found at: "
+
p
);
return
su
.
getAbsolutePath
();
}
else
{
Log
.
v
(
RootCommands
.
TAG
,
"No su in: "
+
p
);
}
}
Log
.
d
(
RootCommands
.
TAG
,
"No su found in a well-known location, "
+
"will just use \"su\"."
);
return
"su"
;
}
/**
* This code is adapted from java.lang.ProcessBuilder.start().
* <p>
* The problem is that Android doesn't allow us to modify the map returned by
* ProcessBuilder.environment(), even though the docstring indicates that it should. This is
* because it simply returns the SystemEnvironment object that System.getenv() gives us. The
* relevant portion in the source code is marked as "// android changed", so presumably it's not
* the case in the original version of the Apache Harmony project.
* <p>
* Note that simply passing the environment variables we want to Process.exec won't be good
* enough, since that would override the environment we inherited completely.
* <p>
* We needed to be able to set a CLASSPATH environment variable for our new process in order to
* use the "app_process" command directly. Note: "app_process" takes arguments passed on to the
* Dalvik VM as well; this might be an alternative way to set the class path.
* <p>
* Code from https://github.com/miracle2k/android-autostarts, use under Apache License was
* agreed by Michael Elsdörfer
*/
public
static
Process
runWithEnv
(
String
command
,
ArrayList
<
String
>
customAddedEnv
,
String
baseDirectory
)
throws
IOException
{
Map
<
String
,
String
>
environment
=
System
.
getenv
();
String
[]
envArray
=
new
String
[
environment
.
size
()
+
(
customAddedEnv
!=
null
?
customAddedEnv
.
size
()
:
0
)];
int
i
=
0
;
for
(
Map
.
Entry
<
String
,
String
>
entry
:
environment
.
entrySet
())
{
envArray
[
i
++]
=
entry
.
getKey
()
+
"="
+
entry
.
getValue
();
}
if
(
customAddedEnv
!=
null
)
{
for
(
String
entry
:
customAddedEnv
)
{
envArray
[
i
++]
=
entry
;
}
}
Process
process
;
if
(
baseDirectory
==
null
)
{
process
=
Runtime
.
getRuntime
().
exec
(
command
,
envArray
,
null
);
}
else
{
process
=
Runtime
.
getRuntime
().
exec
(
command
,
envArray
,
new
File
(
baseDirectory
));
}
return
process
;
}
}
settings.gradle
View file @
c68e37a8
include
':app'
,
':lib:RootCommands'
\ No newline at end of file
include
':app'
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment