return success ? 0 : -1;
}
+bool delete_odex(const char *apk_path, const char *instruction_set, const char *oat_dir) {
+ // Delete the oat/odex file.
+ char out_path[PKG_PATH_MAX];
+ if (!create_oat_out_path(apk_path, instruction_set, oat_dir, out_path)) {
+ return false;
+ }
+
+ // In case of a permission failure report the issue. Otherwise just print a warning.
+ auto unlink_and_check = [](const char* path) -> bool {
+ int result = unlink(path);
+ if (result != 0) {
+ if (errno == EACCES || errno == EPERM) {
+ PLOG(ERROR) << "Could not unlink " << path;
+ return false;
+ }
+ PLOG(WARNING) << "Could not unlink " << path;
+ }
+ return true;
+ };
+
+ // Delete the oat/odex file.
+ bool return_value_oat = unlink_and_check(out_path);
+
+ // Derive and delete the app image.
+ bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
+
+ // Report success.
+ return return_value_oat && return_value_art;
+}
+
} // namespace installd
} // namespace android
// Move a B version over to the A location. Only works for oat_dir != nullptr.
int move_ab(const char *apk_path, const char *instruction_set, const char* oat_dir);
+// Delete odex files generated by dexopt.
+bool delete_odex(const char *apk_path, const char *instruction_set, const char *oat_dir);
+
} // namespace installd
} // namespace android
return move_ab(arg[0], arg[1], arg[2]);
}
+static int do_delete_odex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+ // apk_path, instruction_set, oat_dir
+ return delete_odex(arg[0], arg[1], arg[2]) ? 0 : -1;
+}
+
struct cmdinfo {
const char *name;
unsigned numargs;
{ "move_ab", 3, do_move_ab },
{ "merge_profiles", 2, do_merge_profiles },
{ "dump_profiles", 3, do_dump_profiles },
+ { "delete_odex", 3, do_delete_odex },
};
static int readx(int s, void *_buf, int count)