int main(int argc, char **argv) { time_t start = time(NULL); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); // If this binary is started with the single argument "--adbd", // instead of being the normal recovery binary, it turns into kind // of a stripped-down version of adbd that only supports the // 'sideload' command. Note this must be a real argument, not // anything in the command file or bootloader control block; the // only way recovery should be run with this argument is when it // starts a copy of itself from the apply_from_adb() function. if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { adb_main(); return 0; } printf("Starting recovery on %s", ctime(&start)); load_volume_table(); get_args(&argc, &argv); int previous_runs = 0; const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0, show_text = 0; bool just_exit = false; int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 'p': previous_runs = atoi(optarg); break; case 's': send_intent = optarg; break; case 'u': update_package = optarg; break; case 'w': wipe_data = wipe_cache = 1; break; case 'c': wipe_cache = 1; break; case 't': show_text = 1; break; case 'x': just_exit = true; break; case 'l': locale = optarg; break; case '?': LOGE("Invalid command argument\n"); continue; } } if (locale == NULL) { load_locale_from_cache(); } printf("locale is [%s]\n", locale); Device* device = make_device(); ui = device->GetUI(); ui->Init(); ui->SetLocale(locale); ui->SetBackground(RecoveryUI::NONE); if (show_text) ui->ShowText(true); #ifdef HAVE_SELINUX struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { fprintf(stderr, "Warning: No file_contexts\n"); ui->Print("Warning: No file_contexts\n"); } #endif device->StartRecovery(); printf("Command:"); for (arg = 0; arg < argc; arg++) { printf(" \"%s\"", argv[arg]); } printf("\n"); if (update_package) { // For backwards compatibility on the cache partition only, if // we're given an old 'root' path "CACHE:foo", change it to // "/cache/foo". if (strncmp(update_package, "CACHE:", 6) == 0) { int len = strlen(update_package) + 10; char* modified_path = (char*)malloc(len); strlcpy(modified_path, "/cache/", len); strlcat(modified_path, update_package+6, len); printf("(replacing path \"%s\" with \"%s\")\n", update_package, modified_path); update_package = modified_path; } } printf("\n"); property_list(print_property, NULL); printf("\n"); int status = INSTALL_SUCCESS; if (update_package != NULL) { status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE); if (status == INSTALL_SUCCESS && wipe_cache) { if (erase_volume("/cache")) { LOGE("Cache wipe (requested by package) failed."); } } if (status != INSTALL_SUCCESS) ui->Print("Installation aborted.\n"); } else if (wipe_data) { if (device->WipeData()) status = INSTALL_ERROR; if (erase_volume("/data")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui->Print("Data wipe failed.\n"); } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n"); } else if (!just_exit) { status = INSTALL_NONE; // No command specified ui->SetBackground(RecoveryUI::NO_COMMAND); } if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) { ui->SetBackground(RecoveryUI::ERROR); } if (status != INSTALL_SUCCESS || ui->IsTextVisible()) { prompt_and_wait(device, status); } // Otherwise, get ready to boot the main system... finish_recovery(send_intent); ui->Print("Rebooting...\n"); android_reboot(ANDROID_RB_RESTART, 0, 0); return EXIT_SUCCESS; }
int main(int argc, char **argv) { if (argc == 2 && strcmp(argv[1], "adbd") == 0) { adb_main(); return 0; } // Recovery needs to install world-readable files, so clear umask // set by init umask(0); if (strcmp(basename(argv[0]), "recovery") != 0) { if (strstr(argv[0], "minizip") != NULL) return minizip_main(argc, argv); if (strstr(argv[0], "dedupe") != NULL) return dedupe_main(argc, argv); if (strstr(argv[0], "flash_image") != NULL) return flash_image_main(argc, argv); if (strstr(argv[0], "volume") != NULL) return volume_main(argc, argv); if (strstr(argv[0], "edify") != NULL) return edify_main(argc, argv); if (strstr(argv[0], "dump_image") != NULL) return dump_image_main(argc, argv); if (strstr(argv[0], "erase_image") != NULL) return erase_image_main(argc, argv); if (strstr(argv[0], "mkyaffs2image") != NULL) return mkyaffs2image_main(argc, argv); if (strstr(argv[0], "make_ext4fs") != NULL) return make_ext4fs_main(argc, argv); if (strstr(argv[0], "unyaffs") != NULL) return unyaffs_main(argc, argv); if (strstr(argv[0], "nandroid")) return nandroid_main(argc, argv); if (strstr(argv[0], "bu") == argv[0] + strlen(argv[0]) - 2) return bu_main(argc, argv); if (strstr(argv[0], "reboot")) return reboot_main(argc, argv); #ifdef BOARD_RECOVERY_HANDLES_MOUNT if (strstr(argv[0], "mount") && argc == 2 && !strstr(argv[0], "umount")) { load_volume_table(); return ensure_path_mounted(argv[1]); } #endif if (strstr(argv[0], "poweroff")){ return reboot_main(argc, argv); } if (strstr(argv[0], "setprop")) return setprop_main(argc, argv); if (strstr(argv[0], "getprop")) return getprop_main(argc, argv); return busybox_driver(argc, argv); } __system("/sbin/postrecoveryboot.sh"); int is_user_initiated_recovery = 0; time_t start = time(NULL); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); printf("Starting recovery on %s", ctime(&start)); device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_VERSION)"\n"); load_volume_table(); process_volumes(); LOGI("Processing arguments.\n"); get_args(&argc, &argv); int previous_runs = 0; const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0; int sideload = 0; int headless = 0; LOGI("Checking arguments.\n"); int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 'p': previous_runs = atoi(optarg); break; case 's': send_intent = optarg; break; case 'u': update_package = optarg; break; case 'w': #ifndef BOARD_RECOVERY_ALWAYS_WIPES wipe_data = wipe_cache = 1; #endif break; case 'h': ui_set_background(BACKGROUND_ICON_CID); ui_show_text(0); headless = 1; break; case 'c': wipe_cache = 1; break; case 't': ui_show_text(1); break; case 'l': sideload = 1; break; case '?': LOGE("Invalid command argument\n"); continue; } } struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { fprintf(stderr, "Warning: No file_contexts\n"); // ui_print("Warning: No file_contexts\n"); } LOGI("device_recovery_start()\n"); device_recovery_start(); printf("Command:"); for (arg = 0; arg < argc; arg++) { printf(" \"%s\"", argv[arg]); } printf("\n"); if (update_package) { // For backwards compatibility on the cache partition only, if // we're given an old 'root' path "CACHE:foo", change it to // "/cache/foo". if (strncmp(update_package, "CACHE:", 6) == 0) { int len = strlen(update_package) + 10; char* modified_path = malloc(len); strlcpy(modified_path, "/cache/", len); strlcat(modified_path, update_package+6, len); printf("(replacing path \"%s\" with \"%s\")\n", update_package, modified_path); update_package = modified_path; } } printf("\n"); property_list(print_property, NULL); printf("\n"); int status = INSTALL_SUCCESS; if (update_package != NULL) { status = install_package(update_package); if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n"); } else if (wipe_data) { if (device_wipe_data()) status = INSTALL_ERROR; ignore_data_media_workaround(1); if (erase_volume("/data")) status = INSTALL_ERROR; ignore_data_media_workaround(0); if (has_datadata() && erase_volume("/datadata")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n"); } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Cache wipe failed.\n"); } else if (sideload) { signature_check_enabled = 0; if (!headless) ui_set_show_text(1); if (0 == apply_from_adb()) { status = INSTALL_SUCCESS; ui_set_show_text(0); } } else { LOGI("Checking for extendedcommand...\n"); status = INSTALL_ERROR; // No command specified // we are starting up in user initiated recovery here // let's set up some default options signature_check_enabled = 0; script_assert_enabled = 0; is_user_initiated_recovery = 1; if (!headless) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_CLOCKWORK); } if (extendedcommand_file_exists()) { LOGI("Running extendedcommand...\n"); int ret; if (0 == (ret = run_and_remove_extendedcommand())) { status = INSTALL_SUCCESS; ui_set_show_text(0); } else { handle_failure(ret); } } else { LOGI("Skipping execution of extendedcommand, file not found...\n"); } } setup_adbd(); if (headless) { headless_wait(); } if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_ERROR); } else if (status != INSTALL_SUCCESS || ui_text_visible()) { prompt_and_wait(); } verify_root_and_recovery(); // If there is a radio image pending, reboot now to install it. maybe_install_firmware_update(send_intent); // Otherwise, get ready to boot the main system... finish_recovery(send_intent); sync(); if(!poweroff) { ui_print("Rebooting...\n"); android_reboot(ANDROID_RB_RESTART, 0, 0); } else { ui_print("Shutting down...\n"); android_reboot(ANDROID_RB_POWEROFF, 0, 0); } return EXIT_SUCCESS; }
int main(int argc, char **argv) { // Recovery needs to install world-readable files, so clear umask // set by init umask(0); Log_Offset = 0; // Set up temporary log file (/tmp/recovery.log) freopen(TMP_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TMP_LOG_FILE, "a", stderr); setbuf(stderr, NULL); signal(SIGPIPE, SIG_IGN); // Handle ADB sideload if (argc == 3 && strcmp(argv[1], "--adbd") == 0) { property_set("ctl.stop", "adbd"); adb_main(argv[2]); return 0; } #ifdef RECOVERY_SDCARD_ON_DATA datamedia = true; #endif char crash_prop_val[PROPERTY_VALUE_MAX]; int crash_counter; property_get("twrp.crash_counter", crash_prop_val, "-1"); crash_counter = atoi(crash_prop_val) + 1; snprintf(crash_prop_val, sizeof(crash_prop_val), "%d", crash_counter); property_set("twrp.crash_counter", crash_prop_val); property_set("ro.twrp.boot", "1"); property_set("ro.twrp.version", TW_VERSION_STR); time_t StartupTime = time(NULL); printf("Starting TWRP %s on %s (pid %d)\n", TW_VERSION_STR, ctime(&StartupTime), getpid()); #ifdef HAVE_SELINUX printf("Setting SELinux to permissive\n"); TWFunc::write_file("/sys/fs/selinux/enforce", "0"); TWFunc::write_file("/file_contexts", "\n\n# MultiROM folders\n" "/data/media/multirom(/.*)? <<none>>\n" "/data/media/0/multirom(/.*)? <<none>>\n" "/realdata/media/multirom(/.*)? <<none>>\n" "/realdata/media/0/multirom(/.*)? <<none>>\n" "/sdcard/multirom(/.*)? <<none>>\n" "/mnt/mrom(/.*)? <<none>>\n", "ae"); #endif // MultiROM _might_ have crashed the recovery while the boot device was redirected. // It would be bad to let that as is. MultiROM::failsafeCheckPartition("/tmp/mrom_fakebootpart"); MultiROM::failsafeCheckPartition("/tmp/mrom_fakesyspart"); // Load default values to set DataManager constants and handle ifdefs DataManager::SetDefaultValues(); printf("Starting the UI..."); gui_init(); printf("=> Linking mtab\n"); symlink("/proc/mounts", "/etc/mtab"); if (TWFunc::Path_Exists("/etc/twrp.fstab")) { if (TWFunc::Path_Exists("/etc/recovery.fstab")) { printf("Renaming regular /etc/recovery.fstab -> /etc/recovery.fstab.bak\n"); rename("/etc/recovery.fstab", "/etc/recovery.fstab.bak"); } printf("Moving /etc/twrp.fstab -> /etc/recovery.fstab\n"); rename("/etc/twrp.fstab", "/etc/recovery.fstab"); } printf("=> Processing recovery.fstab\n"); if (!PartitionManager.Process_Fstab("/etc/recovery.fstab", 1)) { LOGERR("Failing out of recovery due to problem with recovery.fstab.\n"); return -1; } PartitionManager.Output_Partition_Logging(); DataManager::SetValue(TW_MROM_REC_VERSION_VAR, MultiROM::getRecoveryVersion()); printf("MultiROM Recovery version: %s\n", DataManager::GetStrValue(TW_MROM_REC_VERSION_VAR).c_str()); // Load up all the resources gui_loadResources(); #ifdef HAVE_SELINUX if (TWFunc::Path_Exists("/prebuilt_file_contexts")) { if (TWFunc::Path_Exists("/file_contexts")) { printf("Renaming regular /file_contexts -> /file_contexts.bak\n"); rename("/file_contexts", "/file_contexts.bak"); } printf("Moving /prebuilt_file_contexts -> /file_contexts\n"); rename("/prebuilt_file_contexts", "/file_contexts"); } struct selinux_opt selinux_options[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; selinux_handle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1); if (!selinux_handle) printf("No file contexts for SELinux\n"); else printf("SELinux contexts loaded from /file_contexts\n"); { // Check to ensure SELinux can be supported by the kernel char *contexts = NULL; if (PartitionManager.Mount_By_Path("/cache", true) && TWFunc::Path_Exists("/cache/recovery")) { lgetfilecon("/cache/recovery", &contexts); if (!contexts) { lsetfilecon("/cache/recovery", "test"); lgetfilecon("/cache/recovery", &contexts); } } else { LOGINFO("Could not check /cache/recovery SELinux contexts, using /sbin/teamwin instead which may be inaccurate.\n"); lgetfilecon("/sbin/teamwin", &contexts); } if (!contexts) { gui_print_color("warning", "Kernel does not have support for reading SELinux contexts.\n"); } else { free(contexts); gui_print("Full SELinux support is present.\n"); } } #else gui_print_color("warning", "No SELinux support (no libselinux).\n"); #endif PartitionManager.Mount_By_Path("/cache", true); string Zip_File, Reboot_Value; bool Cache_Wipe = false, Factory_Reset = false, Perform_Backup = false, Shutdown = false; { TWPartition* misc = PartitionManager.Find_Partition_By_Path("/misc"); if (misc != NULL) { if (misc->Current_File_System == "emmc") { set_device_type('e'); set_device_name(misc->Actual_Block_Device.c_str()); } else if (misc->Current_File_System == "mtd") { set_device_type('m'); set_device_name(misc->MTD_Name.c_str()); } else { LOGERR("Unknown file system for /misc\n"); } } get_args(&argc, &argv); int index, index2, len; char* argptr; char* ptr; printf("Startup Commands: "); for (index = 1; index < argc; index++) { argptr = argv[index]; printf(" '%s'", argv[index]); len = strlen(argv[index]); if (*argptr == '-') {argptr++; len--;} if (*argptr == '-') {argptr++; len--;} if (*argptr == 'u') { ptr = argptr; index2 = 0; while (*ptr != '=' && *ptr != '\n') ptr++; // skip the = before grabbing Zip_File while (*ptr == '=') ptr++; if (*ptr) { Zip_File = ptr; } else LOGERR("argument error specifying zip file\n"); } else if (*argptr == 'w') { if (len == 9) Factory_Reset = true; else if (len == 10) Cache_Wipe = true; } else if (*argptr == 'n') { Perform_Backup = true; } else if (*argptr == 'p') { Shutdown = true; } else if (*argptr == 's') { ptr = argptr; index2 = 0; while (*ptr != '=' && *ptr != '\n') ptr++; if (*ptr) { Reboot_Value = *ptr; } } } printf("\n"); } if(crash_counter == 0) { property_list(Print_Prop, NULL); printf("\n"); } else { printf("twrp.crash_counter=%d\n", crash_counter); } // Check for and run startup script if script exists TWFunc::check_and_run_script("/sbin/runatboot.sh", "boot"); TWFunc::check_and_run_script("/sbin/postrecoveryboot.sh", "boot"); #ifdef TW_INCLUDE_INJECTTWRP // Back up TWRP Ramdisk if needed: TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot"); LOGINFO("Backing up TWRP ramdisk...\n"); if (Boot == NULL || Boot->Current_File_System != "emmc") TWFunc::Exec_Cmd("injecttwrp --backup /tmp/backup_recovery_ramdisk.img"); else { string injectcmd = "injecttwrp --backup /tmp/backup_recovery_ramdisk.img bd=" + Boot->Actual_Block_Device; TWFunc::Exec_Cmd(injectcmd); } LOGINFO("Backup of TWRP ramdisk done.\n"); #endif bool Keep_Going = true; if (Perform_Backup) { DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)"); if (!OpenRecoveryScript::Insert_ORS_Command("backup BSDCAE\n")) Keep_Going = false; } if (Keep_Going && !Zip_File.empty()) { string ORSCommand = "install " + Zip_File; if (!OpenRecoveryScript::Insert_ORS_Command(ORSCommand)) Keep_Going = false; } if (Keep_Going) { if (Factory_Reset) { if (!OpenRecoveryScript::Insert_ORS_Command("wipe data\n")) Keep_Going = false; } else if (Cache_Wipe) { if (!OpenRecoveryScript::Insert_ORS_Command("wipe cache\n")) Keep_Going = false; } } TWFunc::Update_Log_File(); // Offer to decrypt if the device is encrypted if (DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0) { LOGINFO("Is encrypted, do decrypt page first\n"); if (gui_startPage("decrypt", 1, 1) != 0) { LOGERR("Failed to start decrypt GUI page.\n"); } else { // Check for and load custom theme if present gui_loadCustomResources(); } } else if (datamedia) { if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) { LOGINFO("Failed to get default contexts and file mode for storage files.\n"); } else { LOGINFO("Got default contexts and file mode for storage files.\n"); } } // Read the settings file #ifdef TW_HAS_MTP // We unmount partitions sometimes during early boot which may override // the default of MTP being enabled by auto toggling MTP off. This // will force it back to enabled then get overridden by the settings // file, assuming that an entry for tw_mtp_enabled is set. DataManager::SetValue("tw_mtp_enabled", 1); #endif DataManager::ReadSettingsFile(); gui_rotate(DataManager::GetIntValue(TW_ROTATION)); // Fixup the RTC clock on devices which require it if(crash_counter == 0) TWFunc::Fixup_Time_On_Boot(); // Run any outstanding OpenRecoveryScript if(DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0) { if ((TWFunc::Path_Exists(SCRIPT_FILE_TMP) || TWFunc::Path_Exists(SCRIPT_FILE_CACHE))) OpenRecoveryScript::Run_OpenRecoveryScript(); else MultiROM::executeCacheScripts(); } #if 0 #ifdef TW_HAS_MTP // Enable MTP? char mtp_crash_check[PROPERTY_VALUE_MAX]; property_get("mtp.crash_check", mtp_crash_check, "0"); if (strcmp(mtp_crash_check, "0") == 0) { property_set("mtp.crash_check", "1"); if (DataManager::GetIntValue("tw_mtp_enabled") == 1 && ((DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0 && DataManager::GetIntValue(TW_IS_DECRYPTED) != 0) || DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0)) { LOGINFO("Enabling MTP during startup\n"); if (!PartitionManager.Enable_MTP()) PartitionManager.Disable_MTP(); else gui_print("MTP Enabled\n"); } else { PartitionManager.Disable_MTP(); } property_set("mtp.crash_check", "0"); } else { gui_print_color("warning", "MTP Crashed, not starting MTP on boot.\n"); DataManager::SetValue("tw_mtp_enabled", 0); PartitionManager.Disable_MTP(); } #else PartitionManager.Disable_MTP(); #endif #endif // Launch the main GUI gui_start(); // Disable flashing of stock recovery TWFunc::Disable_Stock_Recovery_Replace(); // Check for su to see if the device is rooted or not if (PartitionManager.Mount_By_Path("/system", false)) { if (TWFunc::Path_Exists("/supersu/su") && !TWFunc::Path_Exists("/system/bin/su") && !TWFunc::Path_Exists("/system/xbin/su") && !TWFunc::Path_Exists("/system/bin/.ext/.su")) { // Device doesn't have su installed DataManager::SetValue("tw_busy", 1); if (gui_startPage("installsu", 1, 1) != 0) { LOGERR("Failed to start SuperSU install page.\n"); } } sync(); PartitionManager.UnMount_By_Path("/system", false); } // Reboot TWFunc::Update_Intent_File(Reboot_Value); TWFunc::Update_Log_File(); gui_print("Rebooting...\n"); string Reboot_Arg; DataManager::GetValue("tw_reboot_arg", Reboot_Arg); if (Reboot_Arg == "recovery") TWFunc::tw_reboot(rb_recovery); else if (Reboot_Arg == "poweroff") TWFunc::tw_reboot(rb_poweroff); else if (Reboot_Arg == "bootloader") TWFunc::tw_reboot(rb_bootloader); else if (Reboot_Arg == "download") TWFunc::tw_reboot(rb_download); else TWFunc::tw_reboot(rb_system); return 0; }
int adb_commandline(int argc, char **argv) { char buf[4096]; int no_daemon = 0; int is_daemon = 0; int is_server = 0; int persist = 0; int r; int quote; transport_type ttype = kTransportAny; char* serial = NULL; char* server_port_str = NULL; /* If defined, this should be an absolute path to * the directory containing all of the various system images * for a particular product. If not defined, and the adb * command requires this information, then the user must * specify the path using "-p". */ gProductOutPath = getenv("ANDROID_PRODUCT_OUT"); if (gProductOutPath == NULL || gProductOutPath[0] == '\0') { gProductOutPath = NULL; } // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint serial = getenv("ANDROID_SERIAL"); /* Validate and assign the server port */ server_port_str = getenv("ANDROID_ADB_SERVER_PORT"); int server_port = DEFAULT_ADB_PORT; if (server_port_str && strlen(server_port_str) > 0) { server_port = (int) strtol(server_port_str, NULL, 0); if (server_port <= 0) { fprintf(stderr, "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n", server_port_str); return usage(); } } /* modifiers and flags */ while(argc > 0) { if(!strcmp(argv[0],"server")) { is_server = 1; } else if(!strcmp(argv[0],"nodaemon")) { no_daemon = 1; } else if (!strcmp(argv[0], "fork-server")) { /* this is a special flag used only when the ADB client launches the ADB Server */ is_daemon = 1; } else if(!strcmp(argv[0],"persist")) { persist = 1; } else if(!strncmp(argv[0], "-p", 2)) { const char *product = NULL; if (argv[0][2] == '\0') { if (argc < 2) return usage(); product = argv[1]; argc--; argv++; } else { product = argv[0] + 2; } gProductOutPath = find_product_out_path(product); if (gProductOutPath == NULL) { fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product); return usage(); } } else if (argv[0][0]=='-' && argv[0][1]=='s') { if (isdigit(argv[0][2])) { serial = argv[0] + 2; } else { if(argc < 2 || argv[0][2] != '\0') return usage(); serial = argv[1]; argc--; argv++; } } else if (!strcmp(argv[0],"-d")) { ttype = kTransportUsb; } else if (!strcmp(argv[0],"-e")) { ttype = kTransportLocal; } else { /* out of recognized modifiers and flags */ break; } argc--; argv++; } adb_set_transport(ttype, serial); adb_set_tcp_specifics(server_port); if (is_server) { if (no_daemon || is_daemon) { r = adb_main(is_daemon, server_port); } else { r = launch_server(server_port); } if(r) { fprintf(stderr,"* could not start server *\n"); } return r; } top: if(argc == 0) { return usage(); } /* adb_connect() commands */ if(!strcmp(argv[0], "devices")) { char *tmp; char *listopt; if (argc < 2) listopt = ""; else if (argc == 2 && !strcmp(argv[1], "-l")) listopt = argv[1]; else { fprintf(stderr, "Usage: adb devices [-l]\n"); return 1; } snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt); tmp = adb_query(buf); if(tmp) { printf("List of devices attached \n"); printf("%s\n", tmp); return 0; } else { return 1; } } if(!strcmp(argv[0], "connect")) { char *tmp; if (argc != 2) { fprintf(stderr, "Usage: adb connect <host>[:<port>]\n"); return 1; } snprintf(buf, sizeof buf, "host:connect:%s", argv[1]); tmp = adb_query(buf); if(tmp) { printf("%s\n", tmp); return 0; } else { return 1; } } if(!strcmp(argv[0], "disconnect")) { char *tmp; if (argc > 2) { fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n"); return 1; } if (argc == 2) { snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]); } else { snprintf(buf, sizeof buf, "host:disconnect:"); } tmp = adb_query(buf); if(tmp) { printf("%s\n", tmp); return 0; } else { return 1; } } if (!strcmp(argv[0], "emu")) { return adb_send_emulator_command(argc, argv); } if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) { int r; int fd; char h = (argv[0][0] == 'h'); if (h) { printf("\x1b[41;33m"); fflush(stdout); } if(argc < 2) { D("starting interactive shell\n"); r = interactive_shell(); if (h) { printf("\x1b[0m"); fflush(stdout); } return r; } snprintf(buf, sizeof buf, "shell:%s", argv[1]); argc -= 2; argv += 2; while(argc-- > 0) { strcat(buf, " "); /* quote empty strings and strings with spaces */ quote = (**argv == 0 || strchr(*argv, ' ')); if (quote) strcat(buf, "\""); strcat(buf, *argv++); if (quote) strcat(buf, "\""); } for(;;) { D("interactive shell loop. buff=%s\n", buf); fd = adb_connect(buf); if(fd >= 0) { D("about to read_and_dump(fd=%d)\n", fd); read_and_dump(fd); D("read_and_dump() done.\n"); adb_close(fd); r = 0; } else { fprintf(stderr,"error: %s\n", adb_error()); r = -1; } if(persist) { fprintf(stderr,"\n- waiting for device -\n"); adb_sleep_ms(1000); do_cmd(ttype, serial, "wait-for-device", 0); } else { if (h) { printf("\x1b[0m"); fflush(stdout); } D("interactive shell loop. return r=%d\n", r); return r; } } } if(!strcmp(argv[0], "kill-server")) { int fd; fd = _adb_connect("host:kill"); if(fd == -1) { fprintf(stderr,"* server not running *\n"); return 1; } return 0; } if(!strcmp(argv[0], "sideload")) { if(argc != 2) return usage(); if(adb_download("sideload", argv[1], 1)) { return 1; } else { return 0; } } if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot") || !strcmp(argv[0], "reboot-bootloader") || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb") || !strcmp(argv[0], "root")) { char command[100]; if (!strcmp(argv[0], "reboot-bootloader")) snprintf(command, sizeof(command), "reboot:bootloader"); else if (argc > 1) snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]); else snprintf(command, sizeof(command), "%s:", argv[0]); int fd = adb_connect(command); if(fd >= 0) { read_and_dump(fd); adb_close(fd); return 0; } fprintf(stderr,"error: %s\n", adb_error()); return 1; } if(!strcmp(argv[0], "bugreport")) { if (argc != 1) return usage(); do_cmd(ttype, serial, "shell", "bugreport", 0); return 0; } /* adb_command() wrapper commands */ if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) { char* service = argv[0]; if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) { if (ttype == kTransportUsb) { service = "wait-for-usb"; } else if (ttype == kTransportLocal) { service = "wait-for-local"; } else { service = "wait-for-any"; } } format_host_command(buf, sizeof buf, service, ttype, serial); if (adb_command(buf)) { D("failure: %s *\n",adb_error()); fprintf(stderr,"error: %s\n", adb_error()); return 1; } /* Allow a command to be run after wait-for-device, * e.g. 'adb wait-for-device shell'. */ if(argc > 1) { argc--; argv++; goto top; } return 0; } if(!strcmp(argv[0], "forward")) { if(argc != 3) return usage(); if (serial) { snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]); } else if (ttype == kTransportUsb) { snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]); } else if (ttype == kTransportLocal) { snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]); } else { snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]); } if(adb_command(buf)) { fprintf(stderr,"error: %s\n", adb_error()); return 1; } return 0; } /* do_sync_*() commands */ if(!strcmp(argv[0], "ls")) { if(argc != 2) return usage(); return do_sync_ls(argv[1]); } if(!strcmp(argv[0], "push")) { if(argc != 3) return usage(); return do_sync_push(argv[1], argv[2], 0 /* no verify APK */); } if(!strcmp(argv[0], "pull")) { if (argc == 2) { return do_sync_pull(argv[1], "."); } else if (argc == 3) { return do_sync_pull(argv[1], argv[2]); } else { return usage(); } } if(!strcmp(argv[0], "install")) { if (argc < 2) return usage(); return install_app(ttype, serial, argc, argv); } if(!strcmp(argv[0], "uninstall")) { if (argc < 2) return usage(); return uninstall_app(ttype, serial, argc, argv); } if(!strcmp(argv[0], "sync")) { char *srcarg, *android_srcpath, *data_srcpath; int listonly = 0; int ret; if(argc < 2) { /* No local path was specified. */ srcarg = NULL; } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) { listonly = 1; if (argc == 3) { srcarg = argv[2]; } else { srcarg = NULL; } } else if(argc == 2) { /* A local path or "android"/"data" arg was specified. */ srcarg = argv[1]; } else { return usage(); } ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath); if(ret != 0) return usage(); if(android_srcpath != NULL) ret = do_sync_sync(android_srcpath, "/system", listonly); if(ret == 0 && data_srcpath != NULL) ret = do_sync_sync(data_srcpath, "/data", listonly); free(android_srcpath); free(data_srcpath); return ret; } /* passthrough commands */ if(!strcmp(argv[0],"get-state") || !strcmp(argv[0],"get-serialno") || !strcmp(argv[0],"get-devpath")) { char *tmp; format_host_command(buf, sizeof buf, argv[0], ttype, serial); tmp = adb_query(buf); if(tmp) { printf("%s\n", tmp); return 0; } else { return 1; } } /* other commands */ if(!strcmp(argv[0],"status-window")) { status_window(ttype, serial); return 0; } if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) { return logcat(ttype, serial, argc, argv); } if(!strcmp(argv[0],"ppp")) { return ppp(argc, argv); } if (!strcmp(argv[0], "start-server")) { return adb_connect("host:start-server"); } if (!strcmp(argv[0], "backup")) { return backup(argc, argv); } if (!strcmp(argv[0], "restore")) { return restore(argc, argv); } if (!strcmp(argv[0], "jdwp")) { int fd = adb_connect("jdwp"); if (fd >= 0) { read_and_dump(fd); adb_close(fd); return 0; } else { fprintf(stderr, "error: %s\n", adb_error()); return -1; } } /* "adb /?" is a common idiom under Windows */ if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) { help(); return 0; } if(!strcmp(argv[0], "version")) { version(stdout); return 0; } usage(); return 1; }