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();
    ensure_path_mounted(LAST_LOG_FILE);
    rotate_last_logs(10);
    get_args(&argc, &argv);

    const char *send_intent = NULL;
    const char *update_package = NULL;
    int wipe_data = 0, wipe_cache = 0, show_text = 0;
    bool just_exit = false;
    bool shutdown_after = false;

    int arg;
    while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
        switch (arg) {
        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 'g': {
            if (stage == NULL || *stage == '\0') {
                char buffer[20] = "1/";
                strncat(buffer, optarg, sizeof(buffer)-3);
                stage = strdup(buffer);
            }
            break;
        }
        case 'p': shutdown_after = true; break;
        case '?':
            LOGE("Invalid command argument\n");
            continue;
        }
    }

    if (locale == NULL) {
        load_locale_from_cache();
    }
    printf("locale is [%s]\n", locale);
    printf("stage is [%s]\n", stage, stage);

    Device* device = make_device();
    ui = device->GetUI();
    gCurrentUI = ui;

    ui->SetLocale(locale);
    ui->Init();

    int st_cur, st_max;
    if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) {
        ui->SetStage(st_cur, st_max);
    }

    ui->SetBackground(RecoveryUI::NONE);
    if (show_text) ui->ShowText(true);

    struct selinux_opt seopts[] = {
      { SELABEL_OPT_PATH, "/file_contexts" }
    };

    sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);

    if (!sehandle) {
        ui->Print("Warning: No file_contexts\n");
    }

    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);
    property_get("ro.build.display.id", recovery_version, "");
    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");

            // If this is an eng or userdebug build, then automatically
            // turn the text display on if the script fails so the error
            // message is visible.
            char buffer[PROPERTY_VALUE_MAX+1];
            property_get("ro.build.fingerprint", buffer, "");
            if (strstr(buffer, ":userdebug/") || strstr(buffer, ":eng/")) {
                ui->ShowText(true);
            }
        }
    } 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) {
        copy_logs();
        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);
    if (shutdown_after) {
        ui->Print("Shutting down...\n");
        property_set(ANDROID_RB_PROPERTY, "shutdown,");
    } else {
        ui->Print("Rebooting...\n");
        property_set(ANDROID_RB_PROPERTY, "reboot,");
    }
    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);

    char* command = argv[0];
    char* stripped = strrchr(argv[0], '/');
    if (stripped)
        command = stripped + 1;

    if (strcmp(command, "recovery") != 0)
    {
        struct recovery_cmd cmd = get_command(command);
        if (cmd.name)
            return cmd.main_func(argc, argv);

#ifdef BOARD_RECOVERY_HANDLES_MOUNT
        if (!strcmp(command, "mount") && argc == 2)
        {
            load_volume_table();
            return ensure_path_mounted(argv[1]);
        }
#endif
        if (!strcmp(command, "setup_adbd")) {
            load_volume_table();
            setup_adbd();
            return 0;
        }
        if (!strcmp(command, "start")) {
            property_set("ctl.start", argv[1]);
            return 0;
        }
        if (!strcmp(command, "stop")) {
            property_set("ctl.stop", argv[1]);
            return 0;
        }
        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\n", ctime(&start));

    device_ui_init(&ui_parameters);
    ui_init();
    ui_print(EXPAND(RECOVERY_VERSION)"\n");
	ui_print("Builder: "EXPAND(RECOVERY_BUILDER)"\n");
	ui_print("Date: "EXPAND(RECOVERY_BUILD_TIME)"\n");
	ui_print("weibo:@nx-baby\n");
	__system("/sbin/postrecoveryboot.sh");

//#ifdef BOARD_RECOVERY_SWIPE
//#ifndef BOARD_TOUCH_RECOVERY
    //display directions for swipe controls
    ui_print("Swipe up/down to change selections.\n");
    ui_print("Swipe to the right for enter.\n");
    ui_print("Swipe to the left for back.\n");
//#endif
//#endif

    load_volume_table();
    process_volumes();
    vold_init();
    setup_legacy_storage_paths();
#ifdef QCOM_HARDWARE
    parse_t_daemon_data_files();
	apply_time_zone();
#endif
    LOGI("Processing arguments.\n");
    ensure_path_mounted(LAST_LOG_FILE);
    rotate_last_logs(10);
    get_args(&argc, &argv);

    const char *send_intent = NULL;
    const char *update_package = NULL;
    int wipe_data = 0, wipe_cache = 0;
    int sideload = 0;
    int headless = 0;
    int shutdown_after = 0;

    LOGI("Checking arguments.\n");
    int arg;
    while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
        switch (arg) {
        case 's': send_intent = optarg; break;
        case 'u':
            if (update_package == NULL)
                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 'p': shutdown_after = 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) {
            copy_logs();
            ui_print("Installation aborted.\n");
        } else if (!strcmp(TARGET_DEVICE, "A0001")) { //hack for a0001 ota
            if (strstr(update_package, "/.OTA/"))
                send_intent = "0";
        }
    } else if (wipe_data) {
        if (device_wipe_data()) status = INSTALL_ERROR;
        preserve_data_media(0);
        if (erase_volume("/data")) status = INSTALL_ERROR;
        preserve_data_media(1);
        if (has_datadata() && erase_volume("/datadata")) status = INSTALL_ERROR;
        if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
        if (status != INSTALL_SUCCESS) {
            copy_logs();
            ui_print("Data wipe failed.\n");
        }
    } else if (wipe_cache) {
        if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
        if (status != INSTALL_SUCCESS) {
            copy_logs();
            ui_print("Cache wipe failed.\n");
        }
    } 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;
        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");
        }
    }

    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);
        }
    }

    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();
    }

    // We reach here when in main menu we choose reboot main system or for some wipe commands on start
    // 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);
    if (shutdown_after) {
        ui_print("Shutting down...\n");
        reboot_main_system(ANDROID_RB_POWEROFF, 0, 0);
    } else {
        ui_print("Rebooting...\n");
        reboot_main_system(ANDROID_RB_RESTART, 0, 0);
    }
    return EXIT_SUCCESS;
}
int
main(int argc, char **argv) {
    time_t start = time(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;
    }

    // Handle alternative invocations
    char* command = argv[0];
    char* stripped = strrchr(argv[0], '/');
    if (stripped)
        command = stripped + 1;

    if (strcmp(command, "recovery") != 0) {
        struct recovery_cmd cmd = get_command(command);
        if (cmd.name)
            return cmd.main_func(argc, argv);

#ifdef BOARD_RECOVERY_HANDLES_MOUNT
        if (!strcmp(command, "mount") && argc == 2)
        {
            load_volume_table();
            return ensure_path_mounted(argv[1]);
        }
#endif
        if (!strcmp(command, "setup_adbd")) {
            load_volume_table();
            setup_adbd();
            return 0;
        }
        if (strstr(argv[0], "start")) {
            property_set("ctl.start", argv[1]);
            return 0;
        }
        if (strstr(argv[0], "stop")) {
            property_set("ctl.stop", argv[1]);
            return 0;
        }
        return busybox_driver(argc, argv);
    }

    // devices can run specific tasks on recovery start
    __system("/sbin/postrecoveryboot.sh");

    // Clear umask for packages that copy files out to /tmp and then over
    // to /system without properly setting all permissions (eg. gapps).
    umask(0);

    // 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));

    load_volume_table();
    setup_data_media(1);
    vold_client_start(&v_callbacks, 0);
    vold_set_automount(1);
    setup_legacy_storage_paths();
    ensure_path_mounted(LAST_LOG_FILE);
    rotate_last_logs(10);
    get_args(&argc, &argv);

    const char *send_intent = NULL;
    const char *update_package = NULL;
    int wipe_data = 0, wipe_cache = 0, wipe_media = 0, show_text = 0, sideload = 0;
    bool just_exit = false;
    bool shutdown_after = false;

    printf("Checking arguments.\n");
    int arg;
    while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
        switch (arg) {
        case 's': send_intent = optarg; break;
        case 'u': update_package = optarg; break;
        case 'w': wipe_data = wipe_cache = 1; break;
        case 'm': wipe_media = 1; break;
        case 'c': wipe_cache = 1; break;
        case 't': show_text = 1; break;
        case 'x': just_exit = true; break;
        case 'a': sideload = 1; break;
        case 'p': shutdown_after = true; break;
        case 'g': {
            if (stage == NULL || *stage == '\0') {
                char buffer[20] = "1/";
                strncat(buffer, optarg, sizeof(buffer)-3);
                stage = strdup(buffer);
            }
            break;
        }
        case '?':
            LOGE("Invalid command argument\n");
            continue;
        }
    }

    printf("stage is [%s]\n", stage);

    device_ui_init(&ui_parameters);
    ui_init();
    ui_print(EXPAND(RECOVERY_MOD_VERSION_BUILD) "\n");
    ui_print("ClockworkMod " EXPAND(CWM_BASE_VERSION) "\n");
    LOGI("Device target: " EXPAND(TARGET_COMMON_NAME) "\n");
#ifdef PHILZ_TOUCH_RECOVERY
    print_libtouch_version(0);
#endif

    int st_cur, st_max;
    if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) {
        ui_SetStage(st_cur, st_max);
    }
    // ui_SetStage(5, 8); // debug

    if (show_text) ui_ShowText(true);

    struct selinux_opt seopts[] = {
      { SELABEL_OPT_PATH, "/file_contexts" }
    };

    sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);

    if (!sehandle) {
        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 = (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.\n");
            }
        }
        if (status != INSTALL_SUCCESS) {
            ui_print("Installation aborted.\n");

            // If this is an eng or userdebug build, then automatically
            // turn the text display on if the script fails so the error
            // message is visible.
            char buffer[PROPERTY_VALUE_MAX+1];
            property_get("ro.build.fingerprint", buffer, "");
            if (strstr(buffer, ":userdebug/") || strstr(buffer, ":eng/")) {
                ui_ShowText(true);
            }
        }
    } else if (wipe_data) {
        if (device_wipe_data()) status = INSTALL_ERROR;
        if (erase_volume("/data")) status = INSTALL_ERROR;
        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 (wipe_media) {
        if (is_data_media() && erase_volume("/data/media")) status = INSTALL_ERROR;
        if (status != INSTALL_SUCCESS) ui_print("Media wipe failed.\n");
    } else if (sideload) {
        status = enter_sideload_mode(status);
    } else if (!just_exit) {
        // let's check recovery start up scripts (openrecoveryscript and ROM Manager extendedcommands)
        status = INSTALL_NONE; // No command specified, it is a normal recovery boot unless we find a boot script to run

        LOGI("Checking for extendedcommand & OpenRecoveryScript...\n");

        // we need show_text to show boot scripts log
        bool text_visible = ui_IsTextVisible();
        ui_SetShowText(true);
        if (0 == check_boot_script_file(EXTENDEDCOMMAND_SCRIPT)) {
            LOGI("Running extendedcommand...\n");
            status = INSTALL_ERROR;
            if (0 == run_and_remove_extendedcommand())
                status = INSTALL_SUCCESS;
        }

        if (0 == check_boot_script_file(ORS_BOOT_SCRIPT_FILE)) {
            LOGI("Running openrecoveryscript....\n");
            status = INSTALL_ERROR;
            if (0 == run_ors_boot_script())
                status = INSTALL_SUCCESS;
        }

        ui_SetShowText(text_visible);
    }

    if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) {
        copy_logs();
        // ui_set_background(BACKGROUND_ICON_ERROR); // will be set in prompt_and_wait() after recovery lock check
        handle_failure();
    }
    if (status != INSTALL_SUCCESS || ui_IsTextVisible()) {
        ui_SetShowText(true);
#ifdef PHILZ_TOUCH_RECOVERY
        check_recovery_lock();
#endif
        prompt_and_wait(status);
    }

    // We reach here when in main menu we choose reboot main system or on success install of boot scripts and recovery commands
    finish_recovery(send_intent);
    if (shutdown_after) {
        ui_print("Shutting down...\n");
        reboot_main_system(ANDROID_RB_POWEROFF, 0, 0);
    } else {
        ui_print("Rebooting...\n");
        reboot_main_system(ANDROID_RB_RESTART, 0, 0);
    }
    return EXIT_SUCCESS;
}
Example #4
0
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);

    char* command = argv[0];
    char* stripped = strrchr(argv[0], '/');
    if (stripped)
        command = stripped + 1;

    if (strcmp(command, "recovery") != 0)
    {
        struct recovery_cmd cmd = get_command(command);
        if (cmd.name)
            return cmd.main_func(argc, argv);

#ifdef BOARD_RECOVERY_HANDLES_MOUNT
        if (!strcmp(command, "mount") && argc == 2)
        {
            load_volume_table();
            return ensure_path_mounted(argv[1]);
        }
#endif
        if (!strcmp(command, "setup_adbd")) {
            load_volume_table();
            setup_adbd();
            return 0;
        }
        if (!strcmp(command, "start")) {
            property_set("ctl.start", argv[1]);
            return 0;
        }
        if (!strcmp(command, "stop")) {
            property_set("ctl.stop", argv[1]);
            return 0;
        }
        /* Make sure stdout is not fully buffered, we don't want to
         * have issues when calling busybox commands */
        setlinebuf(stdout);
        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\n", ctime(&start));

    device_ui_init(&ui_parameters);
    ui_init();
    ui_print(EXPAND(RECOVERY_VERSION)"\n");

#ifdef BOARD_RECOVERY_SWIPE
#ifndef BOARD_TOUCH_RECOVERY
    //display directions for swipe controls
    ui_print("Swipe up/down to change selections.\n");
    ui_print("Swipe to the right for enter.\n");
    ui_print("Swipe to the left for back.\n");
#endif
#endif

    load_volume_table();
    process_volumes();
    vold_client_start(&v_callbacks, 0);
    vold_set_automount(1);
    setup_legacy_storage_paths();
    LOGI("Processing arguments.\n");
    ensure_path_mounted(LAST_LOG_FILE);
    rotate_last_logs(10);
    get_args(&argc, &argv);

    int previous_runs = 0;
    const char *send_intent = NULL;
    const char *update_package = NULL;
    const char *update_ubuntu_package = NULL;
    const char *user_data_update_package = NULL;
    int wipe_data = 0, wipe_cache = 0;
    int sideload = 0;
    int headless = 0;

    try_autodeploy(AUTODEPLOY_PACKAGE_FILE);
    try_autodeploy(AUTODEPLOY_PACKAGE_FILE_MULTI);

    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 'd': user_data_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 'v': update_ubuntu_package = UBUNTU_UPDATE_SCRIPT; 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) {
            copy_logs();
            ui_print("Installation aborted.\n");
        }
    } else if (update_ubuntu_package != NULL) {
        LOGI("Performing Ubuntu update");
        ui_set_background(BACKGROUND_ICON_INSTALLING);
        ui_show_indeterminate_progress();
        ui_print("Installing Ubuntu update.\n");
        char tmp[PATH_MAX];
        sprintf(tmp, "%s %s", UBUNTU_UPDATE_SCRIPT, UBUNTU_COMMAND_FILE );
        __system(tmp);
        LOGI("Ubuntu update complete");
        ui_print("Ubuntu update complete.\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) {
            copy_logs();
            ui_print("Data wipe failed.\n");
        }
    } else if (wipe_cache) {
        if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
        if (status != INSTALL_SUCCESS) {
            copy_logs();
            ui_print("Cache wipe failed.\n");
        }
    } 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_UBUNTU);
        }

        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");
        }
    }

    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);
        }
    }

    if (headless) {
        headless_wait();
    }

    if (user_data_update_package != NULL) {
        status = install_package(user_data_update_package);
        if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n");
    }

    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();
    }

    // We reach here when in main menu we choose reboot main system or for some wipe commands on start
    // 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);
    ui_print("Rebooting...\n");
    reboot_main_system(ANDROID_RB_RESTART, 0, 0);

    return EXIT_SUCCESS;
}