Skip to content

Commit b42efbb

Browse files
committed
Simplify main.jar copy logic by copying it via run_server
Signed-off-by: Muntashir Al-Islam <muntashirakon@riseup.net>
1 parent f8d3126 commit b42efbb

4 files changed

Lines changed: 106 additions & 71 deletions

File tree

app/src/main/cpp/run_server.c

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,74 +72,116 @@ int copy_file(const char *src, const char *dst) {
7272
int main(int argc, char *argv[]) {
7373
if (argc < 8) {
7474
fprintf(stderr,
75-
"USAGE: %s <port> <token> <jar_name> <AppID> <user_id> <bgrun(1|0)> <debug(1|0)> [extra_args...]\n",
75+
"USAGE: %s <port> <token> <am_jar_name> <main_jar_name> <app_id> <user_id> <debug(1|0)> [extra_args...]\n",
7676
argv[0]);
7777
return 1;
7878
}
7979

8080
const char *port = argv[1];
8181
const char *token = argv[2];
82-
const char *jar_name = argv[3];
83-
const char *app_id = argv[4];
84-
const char *user_id = argv[5];
85-
const char *bgrun = argv[6];
82+
const char *am_jar_name = argv[3];
83+
const char *main_jar_name = argv[4];
84+
const char *app_id = argv[5];
85+
const char *user_id = argv[6];
8686
const char *debug = argv[7];
87+
const char *bgrun = "1";
8788

8889
// Validate Paths
89-
if (!is_safe_string(jar_name) || !is_safe_string(app_id) || !is_safe_string(user_id)) {
90+
if (!is_safe_string(am_jar_name) || !is_safe_string(main_jar_name) || !is_safe_string(app_id) ||
91+
!is_safe_string(user_id)) {
9092
fprintf(stderr, "Error! Invalid characters in arguments.\n");
9193
return 1;
9294
}
9395

9496
// Validate debug and bgrun
95-
if ((strcmp(bgrun, "0") != 0 && strcmp(bgrun, "1") != 0) ||
96-
(strcmp(debug, "0") != 0 && strcmp(debug, "1") != 0)) {
97-
fprintf(stderr, "Error! bgrun and debug must be either 0 or 1.\n");
97+
if ((strcmp(debug, "0") != 0 && strcmp(debug, "1") != 0)) {
98+
fprintf(stderr, "Error! debug must be either 0 or 1.\n");
9899
return 1;
99100
}
100101

101102
// /data/local/tmp/am.jar
102103
char exec_jar_path[512];
103-
if (snprintf(exec_jar_path, sizeof(exec_jar_path), "%s/%s", TMP_PATH, jar_name) >=
104+
if (snprintf(exec_jar_path, sizeof(exec_jar_path), "%s/%s", TMP_PATH, am_jar_name) >=
104105
sizeof(exec_jar_path)) {
105106
fprintf(stderr, "Error! Buffer overflow on exec_jar_path.\n");
106107
return 1;
107108
}
108109

110+
// /data/local/tmp/main.jar
111+
char main_jar_path[512];
112+
if (snprintf(main_jar_path, sizeof(main_jar_path), "%s/%s", TMP_PATH, main_jar_name) >=
113+
sizeof(main_jar_path)) {
114+
fprintf(stderr, "Error! Buffer overflow on main_jar_path.\n");
115+
return 1;
116+
}
117+
109118
// Prioritized list of fallback source paths
110-
char fallbacks[4][512];
111-
snprintf(fallbacks[0], sizeof(fallbacks[0]), "/sdcard/Android/data/%s/cache/%s", app_id,
112-
jar_name);
113-
snprintf(fallbacks[1], sizeof(fallbacks[1]), "/storage/emulated/%s/Android/data/%s/cache/%s",
114-
user_id, app_id, jar_name);
115-
snprintf(fallbacks[2], sizeof(fallbacks[2]), "/sdcard/AppManager/%s", jar_name);
116-
snprintf(fallbacks[3], sizeof(fallbacks[3]), "/storage/emulated/%s/AppManager/%s", user_id,
117-
jar_name);
119+
char am_jar_fallbacks[4][512];
120+
snprintf(am_jar_fallbacks[0], sizeof(am_jar_fallbacks[0]), "/sdcard/Android/data/%s/cache/%s",
121+
app_id,
122+
am_jar_name);
123+
snprintf(am_jar_fallbacks[1], sizeof(am_jar_fallbacks[1]),
124+
"/storage/emulated/%s/Android/data/%s/cache/%s",
125+
user_id, app_id, am_jar_name);
126+
snprintf(am_jar_fallbacks[2], sizeof(am_jar_fallbacks[2]), "/sdcard/AppManager/%s",
127+
am_jar_name);
128+
snprintf(am_jar_fallbacks[3], sizeof(am_jar_fallbacks[3]), "/storage/emulated/%s/AppManager/%s",
129+
user_id,
130+
am_jar_name);
131+
132+
char main_jar_fallbacks[4][512];
133+
snprintf(main_jar_fallbacks[0], sizeof(main_jar_fallbacks[0]), "/sdcard/Android/data/%s/cache/%s",
134+
app_id,
135+
main_jar_name);
136+
snprintf(main_jar_fallbacks[1], sizeof(main_jar_fallbacks[1]),
137+
"/storage/emulated/%s/Android/data/%s/cache/%s",
138+
user_id, app_id, main_jar_name);
139+
snprintf(main_jar_fallbacks[2], sizeof(main_jar_fallbacks[2]), "/sdcard/AppManager/%s",
140+
main_jar_name);
141+
snprintf(main_jar_fallbacks[3], sizeof(main_jar_fallbacks[3]), "/storage/emulated/%s/AppManager/%s",
142+
user_id,
143+
main_jar_name);
118144

119145
uid_t uid = getuid();
120146
gid_t gid = getgid();
121147
printf("Starting %s as %d:%d...\n", SERVER_NAME, uid, gid);
122148

123149
// Copy am.jar as /data/local/tmp/am.jar
124-
const char *resolved_jar_path = NULL;
150+
const char *resolved_am_jar_path = NULL;
125151
for (int i = 0; i < 4; i++) {
126-
if (copy_file(fallbacks[i], exec_jar_path) == 0) {
127-
resolved_jar_path = fallbacks[i];
152+
if (copy_file(am_jar_fallbacks[i], exec_jar_path) == 0) {
153+
resolved_am_jar_path = am_jar_fallbacks[i];
128154
break;
129155
}
130156
}
131-
132-
if (resolved_jar_path == NULL) {
133-
fprintf(stderr, "Error! %s could not be found or copied.\n", jar_name);
157+
if (resolved_am_jar_path == NULL) {
158+
fprintf(stderr, "Error! %s could not be found or copied.\n", am_jar_name);
134159
return 1;
135160
}
136-
137161
// Fix ownership
138162
if (chown(exec_jar_path, uid, gid) != 0) {
139163
fprintf(stderr, "Warning: chown failed: %s\n", strerror(errno));
140164
// Although it failed, still proceed
141165
}
142166

167+
// Copy main.jar as /data/local/tmp/main.jar
168+
const char *resolved_main_jar_path = NULL;
169+
for (int i = 0; i < 4; i++) {
170+
if (copy_file(main_jar_fallbacks[i], main_jar_path) == 0) {
171+
resolved_main_jar_path = main_jar_fallbacks[i];
172+
break;
173+
}
174+
}
175+
if (resolved_main_jar_path == NULL) {
176+
fprintf(stderr, "Error! %s could not be found or copied.\n", main_jar_name);
177+
return 1;
178+
}
179+
// Fix ownership
180+
if (chown(main_jar_path, uid, gid) != 0) {
181+
fprintf(stderr, "Warning: chown failed: %s\n", strerror(errno));
182+
// Although it failed, still proceed
183+
}
184+
143185
// Build argument for am.jar
144186
char args_buf[2048];
145187
if (snprintf(args_buf, sizeof(args_buf), "path:%s,token:%s,app:%s,bgrun:%s,debug:%s",
@@ -149,7 +191,7 @@ int main(int argc, char *argv[]) {
149191
return 1;
150192
}
151193

152-
printf("Resolved Jar path: %s\n", resolved_jar_path);
194+
printf("Resolved Jar path: %s\n", resolved_am_jar_path);
153195
printf("Args: %s\n", args_buf);
154196

155197
// Execute app_process
@@ -217,6 +259,7 @@ int main(int argc, char *argv[]) {
217259

218260
// Cleanup
219261
unlink(exec_jar_path);
262+
unlink(main_jar_path);
220263
free(exec_argv);
221264
exit(1);
222265
}

app/src/main/java/io/github/muntashirakon/AppManager/ipc/RootServiceManager.java

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@
5252

5353
import io.github.muntashirakon.AppManager.BuildConfig;
5454
import io.github.muntashirakon.AppManager.compat.ManifestCompat;
55+
import io.github.muntashirakon.AppManager.server.common.Constants;
5556
import io.github.muntashirakon.AppManager.server.common.IRootServiceManager;
57+
import io.github.muntashirakon.AppManager.servermanager.ServerConfig;
5658
import io.github.muntashirakon.AppManager.settings.Ops;
5759
import io.github.muntashirakon.AppManager.utils.ContextUtils;
5860
import io.github.muntashirakon.AppManager.utils.FileUtils;
59-
import io.github.muntashirakon.AppManager.utils.PackageUtils;
6061

6162
/**
6263
* Runs in the non-root (client) process.
@@ -167,27 +168,13 @@ private Shell.Task startRootProcess(ComponentName name, String action) {
167168
Log.e(TAG, JVMTI_ERROR);
168169
}
169170

170-
String mainJarName = "main.jar";
171-
Context ctx = ContextUtils.getContext();
172-
Context de = ContextUtils.getDeContext(ctx);
173-
File mainJar;
174-
try {
175-
mainJar = new File(FileUtils.getExternalCachePath(de), mainJarName);
176-
} catch (IOException e) {
177-
throw new IllegalStateException("External directory unavailable.", e);
178-
}
179-
File stagingMainJar = new File(PACKAGE_STAGING_DIRECTORY, mainJarName);
180-
// Dump main.jar as trampoline
181-
try (InputStream in = context.getResources().getAssets().open("main.jar");
182-
OutputStream out = new FileOutputStream(mainJar)) {
183-
Utils.pump(in, out);
184-
}
185-
FileUtils.chmod644(mainJar);
171+
ServerConfig.init(context);
172+
File extMainJar = new File(FileUtils.getExternalCachePath(context), Constants.MAIN_JAR_NAME);
173+
File stagingMainJar = new File(PACKAGE_STAGING_DIRECTORY, Constants.MAIN_JAR_NAME);
186174

187175
StringBuilder env = new StringBuilder();
188176
String params = getParams(env);
189-
190-
String cmd = getRunnerScript(env, mainJar, stagingMainJar, name, action, params);
177+
String cmd = getRunnerScript(env, extMainJar, stagingMainJar, name, action, params);
191178
Log.d(TAG, cmd);
192179
// Write command to stdin
193180
byte[] bytes = cmd.getBytes(StandardCharsets.UTF_8);
@@ -235,36 +222,28 @@ private String getRunnerScript(@NonNull StringBuilder env,
235222
// We cannot readlink /proc/self/exe on old kernels
236223
@SuppressLint("RestrictedApi")
237224
String execFile = "/system/bin/app_process" + (Utils.isProcess64Bit() ? "64" : "32");
238-
String packageStagingCommand;
239225
env.append(CLASSPATH_ENV).append("=");
240226
if (Ops.hasRoot()) {
241227
// Avoid using the package staging directory
242228
env.append(mainJar);
243-
packageStagingCommand = "";
244229
} else if (!Ops.isSystem()) {
245230
// Use package staging directory
231+
// Already copied by the server
246232
env.append(stagingMainJar);
247-
packageStagingCommand = PackageUtils.ensurePackageStagingDirectoryCommand() +
248-
// Copy to main.jar to package staging directory
249-
String.format(Locale.ROOT, " && cp %s %s && ", mainJar, PACKAGE_STAGING_DIRECTORY) +
250-
// Change permission of the main.jar
251-
String.format(Locale.ROOT, "chmod 755 %s && chown shell:shell %s && ", stagingMainJar, stagingMainJar);
252233
} else {
253234
// System can't use package staging directory
254235
env.append(mainJar);
255-
packageStagingCommand = "";
256236
}
257237
env.append(" ");
258-
return (packageStagingCommand +
259-
String.format(Locale.ROOT, "(%s %s %s /system/bin %s %s '%s' %d %s 2>&1)&",
260-
env, // Environments
261-
execFile, // Executable
262-
debugParams, // Debug parameters
263-
getNiceNameArg(action), // Process name
264-
IPCMAIN_CLASSNAME, // Java command
265-
serviceName.flattenToString(), // args[0]
266-
Process.myUid(), // args[1]
267-
action)); // args[2]
238+
return String.format(Locale.ROOT, "(%s %s %s /system/bin %s %s '%s' %d %s 2>&1)&",
239+
env, // Environments
240+
execFile, // Executable
241+
debugParams, // Debug parameters
242+
getNiceNameArg(action), // Process name
243+
IPCMAIN_CLASSNAME, // Java command
244+
serviceName.flattenToString(), // args[0]
245+
Process.myUid(), // args[1]
246+
action); // args[2]
268247
}
269248

270249
@NonNull

app/src/main/java/io/github/muntashirakon/AppManager/servermanager/ServerConfig.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,26 @@ public final class ServerConfig {
4444
public static void init(@NonNull Context context) throws IOException {
4545
// Setup paths
4646
boolean force = BuildConfig.DEBUG;
47-
File externalCachePath = FileUtils.getExternalCachePath(context);
48-
File externalCacheJar = new File(externalCachePath, Constants.JAR_NAME);
49-
AssetsUtils.copyFile(context, Constants.JAR_NAME, externalCacheJar, force);
47+
try {
48+
File externalCachePath = FileUtils.getExternalCachePath(context);
49+
File externalCacheAmJar = new File(externalCachePath, Constants.JAR_NAME);
50+
File externalCacheMainJar = new File(externalCachePath, Constants.MAIN_JAR_NAME);
51+
AssetsUtils.copyFile(context, Constants.JAR_NAME, externalCacheAmJar, force);
52+
AssetsUtils.copyFile(context, Constants.MAIN_JAR_NAME, externalCacheMainJar, force);
53+
FileUtils.chmod644(externalCacheAmJar);
54+
FileUtils.chmod644(externalCacheMainJar);
55+
} catch (Exception e) {
56+
throw new IllegalStateException("External directory unavailable.", e);
57+
}
5058

5159
try {
5260
File amPath = getAppManagerStoragePath();
5361
File externalAmJar = new File(amPath, Constants.JAR_NAME);
62+
File externalMainJar = new File(amPath, Constants.MAIN_JAR_NAME);
5463
AssetsUtils.copyFile(context, Constants.JAR_NAME, externalAmJar, force);
64+
AssetsUtils.copyFile(context, Constants.MAIN_JAR_NAME, externalMainJar, force);
65+
FileUtils.chmod644(externalAmJar);
66+
FileUtils.chmod644(externalMainJar);
5567
} catch (Exception e) {
5668
e.printStackTrace();
5769
}
@@ -77,20 +89,20 @@ public static String getServerRunnerCommand() throws IndexOutOfBoundsException {
7789
if (executable.exists()) {
7890
int port = getLocalServerPort();
7991
String token = getLocalToken();
80-
String jarName = Constants.JAR_NAME;
92+
String amJarName = Constants.JAR_NAME;
93+
String mainJarName = Constants.MAIN_JAR_NAME;
8194
String appId = BuildConfig.APPLICATION_ID;
8295
int currentUserId = UserHandleHidden.myUserId();
83-
int bgrun = 1;
8496
int debug = BuildConfig.DEBUG ? 1 : 0;
8597

86-
return String.format(Locale.ROOT, "%s %d %s %s %s %d %d %d",
98+
return String.format(Locale.ROOT, "%s %d %s %s %s %s %d %d",
8799
executable.getAbsolutePath(),
88100
port,
89101
token,
90-
jarName,
102+
amJarName,
103+
mainJarName,
91104
appId,
92105
currentUserId,
93-
bgrun,
94106
debug
95107
);
96108
}

libserver/src/main/java/io/github/muntashirakon/AppManager/server/common/Constants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
public class Constants {
66
public static final String SERVER_NAME = "am_local_server";
77
public static final String JAR_NAME = "am.jar";
8+
public static final String MAIN_JAR_NAME = "main.jar";
89
}

0 commit comments

Comments
 (0)