static void send_error_packet(int to_peer, int err, const char* msg) { size_t msg_size = strlen(msg); if (msg_size > UINT16_MAX) msg_size = UINT16_MAX; struct xfer_msg m = { .type = XFER_MSG_ERROR, .u.error.err = err, .u.error.msg_size = msg_size, }; send_xfer_msg(to_peer, &m); write_all(to_peer, msg, msg_size); } int xfer_stub_main(const struct cmd_xfer_stub_info* info) { struct xfer_ctx ctx = { .from_peer = STDIN_FILENO, .to_peer = STDOUT_FILENO, .info = info, }; struct errinfo ei = { .want_msg = true }; if (catch_error(do_xfer, &ctx, &ei)) { send_error_packet(ctx.to_peer, ei.err, ei.msg); return 1; } return 0; } #if FBADB_MAIN int xfer_handle_command( const struct start_peer_info* spi, const struct cmd_xfer_stub_info* local, const struct cmd_xfer_stub_info* remote) { struct child* peer = start_peer( spi, make_args_cmd_xfer_stub( CMD_ARG_NAME | CMD_ARG_FORWARDED, remote)); struct xfer_ctx ctx = { .from_peer = peer->fd[1]->fd, .to_peer = peer->fd[0]->fd, .info = local, }; do_xfer(&ctx); return child_status_to_exit_code(child_wait(peer)); }
static void compile_dex_with_dexopt(const char* dex_file_name, const char* odex_file_name) { SCOPED_RESLIST(rl); int dex_file = xopen(dex_file_name, O_RDONLY, 0); const char* odex_temp_filename = xaprintf( "%s.tmp.%s", odex_file_name, gen_hex_random(ENOUGH_ENTROPY)); cleanup_commit(cleanup_allocate(), cleanup_tmpfile, odex_temp_filename); int odex_temp_file = xopen(odex_temp_filename, O_RDWR | O_CREAT | O_EXCL, 0644); allow_inherit(dex_file); allow_inherit(odex_temp_file); struct child_start_info csi = { .io[0] = CHILD_IO_DEV_NULL, .io[1] = CHILD_IO_PIPE, .io[2] = CHILD_IO_DUP_TO_STDOUT, .exename = "dexopt", .argv = ARGV( "dexopt", "--zip", xaprintf("%d", dex_file), xaprintf("%d", odex_temp_file), dex_file_name, "v=ao=fm=y"), }; struct child* dexopt = child_start(&csi); struct growable_buffer output = slurp_fd_buf(dexopt->fd[1]->fd); int status = child_status_to_exit_code(child_wait(dexopt)); if (status != 0) die(EINVAL, "dexopt failed: %s", massage_output_buf(output)); xrename(odex_temp_filename, odex_file_name); } static void compile_dex(const char* dex_file_name, const char* odex_file_name) { if (api_level() < 21) compile_dex_with_dexopt(dex_file_name, odex_file_name); } int rdex_main(const struct cmd_rdex_info* info) { const char* dex_file_name = info->dexfile; struct stat dex_stat = xstat(dex_file_name); const char* odex_file_name = make_odex_name(dex_file_name); bool need_recompile = true; struct stat odex_stat; if (stat(odex_file_name, &odex_stat) == 0 && dex_stat.st_mtime <= odex_stat.st_mtime) { need_recompile = false; } (void) need_recompile; (void) odex_file_name; (void) compile_dex; if (need_recompile) compile_dex(dex_file_name, odex_file_name); if (setenv("CLASSPATH", dex_file_name, 1) == -1) die_errno("setenv"); if (info->classname[0] == '-') die(EINVAL, "class name cannot begin with '-'"); execvp("app_process", (char* const*) ARGV_CONCAT( ARGV("app_process", xdirname(dex_file_name), info->classname), info->args ?: empty_argv)); die_errno("execvp(\"app_process\", ..."); }