int format_unknown_device(const char *device, const char* path, const char *fs_type) { LOGI("Formatting unknown device.\n"); if (fs_type != NULL && get_flash_type(fs_type) != UNSUPPORTED) return erase_raw_partition(fs_type, device); // if this is SDEXT:, don't worry about it if it does not exist. if (0 == strcmp(path, "/sd-ext")) { struct stat st; Volume *vol = volume_for_path("/sd-ext"); if (vol == NULL || 0 != stat(vol->device, &st)) { ui_print("No app2sd partition found. Skipping format of /sd-ext.\n"); return 0; } } if (NULL != fs_type) { if (strcmp("ext3", fs_type) == 0) { LOGI("Formatting ext3 device.\n"); if (0 != ensure_path_unmounted(path)) { LOGE("Error while unmounting %s.\n", path); return -12; } return format_ext3_device(device); } if (strcmp("ext2", fs_type) == 0) { LOGI("Formatting ext2 device.\n"); if (0 != ensure_path_unmounted(path)) { LOGE("Error while unmounting %s.\n", path); return -12; } return format_ext2_device(device); } } if (0 != ensure_path_mounted(path)) { ui_print("Error mounting %s!\n", path); ui_print("Skipping format...\n"); return 0; } static char tmp[PATH_MAX]; if (strcmp(path, "/data") == 0) { sprintf(tmp, "cd /data ; for f in $(ls -a | grep -v ^media$); do rm -rf $f; done"); __system(tmp); // if the /data/media sdcard has already been migrated for android 4.2, // prevent the migration from happening again by writing the .layout_version struct stat st; if (0 == lstat("/data/media/0", &st)) { char* layout_version = "2"; FILE* f = fopen("/data/.layout_version", "wb"); if (NULL != f) { fwrite(layout_version, 1, 2, f); fclose(f); } else { LOGI("error opening /data/.layout_version for write.\n"); } } else { LOGI("/data/media/0 not found. migration may occur.\n"); } } else { sprintf(tmp, "rm -rf %s/*", path); __system(tmp); sprintf(tmp, "rm -rf %s/.*", path); __system(tmp); } ensure_path_unmounted(path); return 0; }
void show_partition_menu() { static char* headers[] = { "Storage Management", "", NULL }; static MountMenuEntry* mount_menu = NULL; static FormatMenuEntry* format_menu = NULL; typedef char* string; int i, mountable_volumes, formatable_volumes; int num_volumes; Volume* device_volumes; num_volumes = get_num_volumes(); device_volumes = get_device_volumes(); string options[255]; if(!device_volumes) return; mountable_volumes = 0; formatable_volumes = 0; mount_menu = malloc(num_volumes * sizeof(MountMenuEntry)); format_menu = malloc(num_volumes * sizeof(FormatMenuEntry)); for (i = 0; i < num_volumes; ++i) { Volume* v = &device_volumes[i]; if(strcmp("ramdisk", v->fs_type) != 0 && strcmp("mtd", v->fs_type) != 0 && strcmp("emmc", v->fs_type) != 0 && strcmp("bml", v->fs_type) != 0) { if(strcmp("datamedia", v->fs_type) != 0) { sprintf(&mount_menu[mountable_volumes].mount, "Mount %s", v->mount_point); sprintf(&mount_menu[mountable_volumes].unmount, "Unmount %s", v->mount_point); mount_menu[mountable_volumes].v = &device_volumes[i]; ++mountable_volumes; } if (is_safe_to_format(v->mount_point)) { sprintf(&format_menu[formatable_volumes].txt, "Format %s", v->mount_point); format_menu[formatable_volumes].v = &device_volumes[i]; ++formatable_volumes; } } else if (strcmp("ramdisk", v->fs_type) != 0 && strcmp("mtd", v->fs_type) == 0 && is_safe_to_format(v->mount_point)) { sprintf(&format_menu[formatable_volumes].txt, "Format %s", v->mount_point); format_menu[formatable_volumes].v = &device_volumes[i]; ++formatable_volumes; } } static char* confirm_format = "Confirm format?"; static char* confirm = "Yes - Format"; char confirm_string[255]; for (;;) { for (i = 0; i < mountable_volumes; i++) { MountMenuEntry* e = &mount_menu[i]; Volume* v = e->v; if(is_path_mounted(v->mount_point)) options[i] = e->unmount; else options[i] = e->mount; } for (i = 0; i < formatable_volumes; i++) { FormatMenuEntry* e = &format_menu[i]; options[mountable_volumes+i] = e->txt; } if (!is_data_media()) { options[mountable_volumes + formatable_volumes] = "Mount USB Storage"; options[mountable_volumes + formatable_volumes + 1] = "Erase dalvik-cache"; } else { options[mountable_volumes + formatable_volumes] = "Erase dalvik-cache"; options[mountable_volumes + formatable_volumes + 1] = "Format /data and /data/media (/sdcard)"; } if (!can_partition("/sdcard")) { options[mountable_volumes + formatable_volumes + 1 + 1] = NULL; } if (!can_partition("/external_sd")) { options[mountable_volumes + formatable_volumes + 1 + 1 + 1] = NULL; } if (!can_partition("/emmc")) { options[mountable_volumes + formatable_volumes + 1 + 1 + 1 + 1] = NULL; } options[mountable_volumes + formatable_volumes + 1 + 1 + 1 + 1 + 1] = NULL; int chosen_item = get_menu_selection(headers, &options, 0, 0); if (chosen_item == GO_BACK) break; if (chosen_item == (mountable_volumes+formatable_volumes)) { if (!is_data_media()) { show_mount_usb_storage_menu(); } else { if(!confirm_selection("Confirm wipe?", "Yes - Wipe Dalvik Cache")) continue; erase_dalvik_cache(NULL); } } else if (chosen_item == (mountable_volumes+formatable_volumes + 1)) { if (!is_data_media()) { if(!confirm_selection("Confirm wipe?", "Yes - Wipe Dalvik Cache")) continue; erase_dalvik_cache(NULL); } else { if (!confirm_selection("format /data and /data/media (/sdcard)", "Yes - Format")) continue; handle_data_media_format(1); ui_print("Formatting /data...\n"); if (0 != format_volume("/data")) ui_print("Error formatting /data!\n"); else ui_print("Done.\n"); handle_data_media_format(0); } } else if (chosen_item == (mountable_volumes+formatable_volumes + 1 + 1)) { partition_sdcard("/sdcard"); } else if (chosen_item == (mountable_volumes+formatable_volumes + 1 + 1 + 1)) { partition_sdcard("/external_sd"); } else if (chosen_item == (mountable_volumes+formatable_volumes + 1 + 1 + 1 + 1)) { partition_sdcard("/emmc"); } else if (chosen_item < mountable_volumes) { MountMenuEntry* e = &mount_menu[chosen_item]; Volume* v = e->v; if (is_path_mounted(v->mount_point)) { if (0 != ensure_path_unmounted(v->mount_point)) ui_print("Error unmounting %s!\n", v->mount_point); } else { if (0 != ensure_path_mounted(v->mount_point)) ui_print("Error mounting %s!\n", v->mount_point); } } else if (chosen_item < (mountable_volumes + formatable_volumes)) { chosen_item = chosen_item - mountable_volumes; FormatMenuEntry* e = &format_menu[chosen_item]; Volume* v = e->v; sprintf(confirm_string, "%s - %s", v->mount_point, confirm_format); if (!confirm_selection(confirm_string, confirm)) continue; ui_print("Formatting %s...\n", v->mount_point); if (0 != format_volume(v->mount_point)) ui_print("Error formatting %s!\n", v->mount_point); else ui_print("Done.\n"); } } free(mount_menu); free(format_menu); }
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("警告:没有文件内容\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("安装已取消\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分区清空失败\n"); } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Cache分区清空失败\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("正在重启...\n"); android_reboot(ANDROID_RB_RESTART, 0, 0); } else { ui_print("正在关机...\n"); android_reboot(ANDROID_RB_POWEROFF, 0, 0); } return EXIT_SUCCESS; }
static int update_directory(const char* path, const char* unmount_when_done) { ensure_path_mounted(path); const char* MENU_HEADERS[] = { "Choose a package to install:", path, "", NULL }; DIR* d; struct dirent* de; d = opendir(path); if (d == NULL) { LOGE("error opening %s: %s\n", path, strerror(errno)); if (unmount_when_done != NULL) { ensure_path_unmounted(unmount_when_done); } return 0; } char** headers = prepend_title(MENU_HEADERS); int d_size = 0; int d_alloc = 10; char** dirs = malloc(d_alloc * sizeof(char*)); int z_size = 1; int z_alloc = 10; char** zips = malloc(z_alloc * sizeof(char*)); zips[0] = strdup("../"); while ((de = readdir(d)) != NULL) { int name_len = strlen(de->d_name); if (de->d_type == DT_DIR) { // skip "." and ".." entries if (name_len == 1 && de->d_name[0] == '.') continue; if (name_len == 2 && de->d_name[0] == '.' && de->d_name[1] == '.') continue; if (d_size >= d_alloc) { d_alloc *= 2; dirs = realloc(dirs, d_alloc * sizeof(char*)); } dirs[d_size] = malloc(name_len + 2); strcpy(dirs[d_size], de->d_name); dirs[d_size][name_len] = '/'; dirs[d_size][name_len+1] = '\0'; ++d_size; } else if (de->d_type == DT_REG && name_len >= 4 && strncasecmp(de->d_name + (name_len-4), ".zip", 4) == 0) { if (z_size >= z_alloc) { z_alloc *= 2; zips = realloc(zips, z_alloc * sizeof(char*)); } zips[z_size++] = strdup(de->d_name); } } closedir(d); qsort(dirs, d_size, sizeof(char*), compare_string); qsort(zips, z_size, sizeof(char*), compare_string); // append dirs to the zips list if (d_size + z_size + 1 > z_alloc) { z_alloc = d_size + z_size + 1; zips = realloc(zips, z_alloc * sizeof(char*)); } memcpy(zips + z_size, dirs, d_size * sizeof(char*)); free(dirs); z_size += d_size; zips[z_size] = NULL; int result; int chosen_item = 0; do { chosen_item = get_menu_selection(headers, zips, 1, chosen_item); char* item = zips[chosen_item]; int item_len = strlen(item); if (chosen_item == 0) { // item 0 is always "../" // go up but continue browsing (if the caller is update_directory) result = -1; break; } else if (item[item_len-1] == '/') { // recurse down into a subdirectory char new_path[PATH_MAX]; strlcpy(new_path, path, PATH_MAX); strlcat(new_path, "/", PATH_MAX); strlcat(new_path, item, PATH_MAX); new_path[strlen(new_path)-1] = '\0'; // truncate the trailing '/' result = update_directory(new_path, unmount_when_done); if (result >= 0) break; } else { // selected a zip file: attempt to install it, and return // the status to the caller. char new_path[PATH_MAX]; strlcpy(new_path, path, PATH_MAX); strlcat(new_path, "/", PATH_MAX); strlcat(new_path, item, PATH_MAX); ui_print("\n-- 安装 %s ...\n", path); set_sdcard_update_bootloader_message(); char* copy = copy_sideloaded_package(new_path); if (unmount_when_done != NULL) { ensure_path_unmounted(unmount_when_done); } if (copy) { result = install_package(copy); free(copy); } else { result = INSTALL_ERROR; } break; } } while (true); int i; for (i = 0; i < z_size; ++i) free(zips[i]); free(zips); free(headers); if (unmount_when_done != NULL) { ensure_path_unmounted(unmount_when_done); } return result; }
static char* copy_sideloaded_package(const char* original_path) { if (ensure_path_mounted(original_path) != 0) { LOGE("Can't mount %s\n", original_path); return NULL; } if (ensure_path_mounted(SIDELOAD_TEMP_DIR) != 0) { LOGE("Can't mount %s\n", SIDELOAD_TEMP_DIR); return NULL; } if (mkdir(SIDELOAD_TEMP_DIR, 0700) != 0) { if (errno != EEXIST) { LOGE("Can't mkdir %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno)); return NULL; } } // verify that SIDELOAD_TEMP_DIR is exactly what we expect: a // directory, owned by root, readable and writable only by root. struct stat st; if (stat(SIDELOAD_TEMP_DIR, &st) != 0) { LOGE("failed to stat %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno)); return NULL; } if (!S_ISDIR(st.st_mode)) { LOGE("%s isn't a directory\n", SIDELOAD_TEMP_DIR); return NULL; } if ((st.st_mode & 0777) != 0700) { LOGE("%s has perms %o\n", SIDELOAD_TEMP_DIR, st.st_mode); return NULL; } if (st.st_uid != 0) { LOGE("%s owned by %lu; not root\n", SIDELOAD_TEMP_DIR, st.st_uid); return NULL; } char copy_path[PATH_MAX]; strcpy(copy_path, SIDELOAD_TEMP_DIR); strcat(copy_path, "/package.zip"); char* buffer = malloc(BUFSIZ); if (buffer == NULL) { LOGE("Failed to allocate buffer\n"); return NULL; } size_t read; FILE* fin = fopen(original_path, "rb"); if (fin == NULL) { LOGE("Failed to open %s (%s)\n", original_path, strerror(errno)); return NULL; } FILE* fout = fopen(copy_path, "wb"); if (fout == NULL) { LOGE("Failed to open %s (%s)\n", copy_path, strerror(errno)); return NULL; } while ((read = fread(buffer, 1, BUFSIZ, fin)) > 0) { if (fwrite(buffer, 1, read, fout) != read) { LOGE("Short write of %s (%s)\n", copy_path, strerror(errno)); return NULL; } } free(buffer); if (fclose(fout) != 0) { LOGE("Failed to close %s (%s)\n", copy_path, strerror(errno)); return NULL; } if (fclose(fin) != 0) { LOGE("Failed to close %s (%s)\n", original_path, strerror(errno)); return NULL; } // "adb push" is happy to overwrite read-only files when it's // running as root, but we'll try anyway. if (chmod(copy_path, 0400) != 0) { LOGE("Failed to chmod %s (%s)\n", copy_path, strerror(errno)); return NULL; } return strdup(copy_path); }
int main(int argc, char **argv) { if (strcmp(basename(argv[0]), "recovery") != 0) { 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], "unyaffs") != NULL) return unyaffs_main(argc, argv); if (strstr(argv[0], "nandroid")) return nandroid_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); 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)); 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; const char *encrypted_fs_mode = NULL; int wipe_data = 0, wipe_cache = 0; int toggle_secure_fs = 0; encrypted_fs_info encrypted_fs_data; 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 'c': wipe_cache = 1; break; case 'e': encrypted_fs_mode = optarg; toggle_secure_fs = 1; break; case 't': ui_show_text(1); break; case '?': LOGE("Invalid command argument\n"); continue; } } 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 (toggle_secure_fs) { if (strcmp(encrypted_fs_mode,"on") == 0) { encrypted_fs_data.mode = MODE_ENCRYPTED_FS_ENABLED; ui_print("Enabling Encrypted FS.\n"); } else if (strcmp(encrypted_fs_mode,"off") == 0) { encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED; ui_print("Disabling Encrypted FS.\n"); } else { ui_print("Error: invalid Encrypted FS setting.\n"); status = INSTALL_ERROR; } // Recovery strategy: if the data partition is damaged, disable encrypted file systems. // This preventsthe device recycling endlessly in recovery mode. if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) && (read_encrypted_fs_info(&encrypted_fs_data))) { ui_print("Encrypted FS change aborted, resetting to disabled state.\n"); encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED; } if (status != INSTALL_ERROR) { if (erase_volume("/data")) { ui_print("Data wipe failed.\n"); status = INSTALL_ERROR; } else if (erase_volume("/cache")) { ui_print("Cache wipe failed.\n"); status = INSTALL_ERROR; } else if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) && (restore_encrypted_fs_info(&encrypted_fs_data))) { ui_print("Encrypted FS change aborted.\n"); status = INSTALL_ERROR; } else { ui_print("Successfully updated Encrypted FS.\n"); status = INSTALL_SUCCESS; } } } else 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; 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 { 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; 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 (status != INSTALL_SUCCESS && !is_user_initiated_recovery) ui_set_background(BACKGROUND_ICON_ERROR); if (status != INSTALL_SUCCESS || ui_text_visible()) { prompt_and_wait(); } // 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(!poweroff) ui_print("Rebooting...\n"); else ui_print("Shutting down...\n"); sync(); //reboot((!poweroff) ? RB_AUTOBOOT : RB_POWER_OFF); // FOR ROM MANAGER compatibility if(!poweroff) { // reboot into system __system("/sbin/reboot_system"); } else { // shift to normal bootmode and power off __system("/sbin/nbmode"); reboot(RB_POWER_OFF); } return EXIT_SUCCESS; }
int ensure_path_mounted_at_mount_point(const char* path, const char* mount_point) { Volume* v = volume_for_path(path); if (v == NULL) { // no /sdcard? let's assume /data/media if (strstr(path, "/sdcard") == path && is_data_media()) { LOGI("using /data/media, no /sdcard found.\n"); int ret; if (0 != (ret = ensure_path_mounted("/data"))) return ret; setup_data_media(); return 0; } LOGE("unknown volume for path [%s]\n", path); return -1; } if (strcmp(v->fs_type, "ramdisk") == 0) { // the ramdisk is always mounted. return 0; } int result; result = scan_mounted_volumes(); if (result < 0) { LOGE("failed to scan mounted volumes\n"); return -1; } if (NULL == mount_point) mount_point = v->mount_point; const MountedVolume* mv = find_mounted_volume_by_mount_point(mount_point); if (mv) { // volume is already mounted return 0; } mkdir(mount_point, 0755); // in case it doesn't already exist if (strcmp(v->fs_type, "yaffs2") == 0) { // mount an MTD partition as a YAFFS2 filesystem. mtd_scan_partitions(); const MtdPartition* partition; partition = mtd_find_partition_by_name(v->device); if (partition == NULL) { LOGE("failed to find \"%s\" partition to mount at \"%s\"\n", v->device, mount_point); return -1; } return mtd_mount_partition(partition, mount_point, v->fs_type, 0); } else if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "ext3") == 0 || strcmp(v->fs_type, "rfs") == 0 || strcmp(v->fs_type, "vfat") == 0) { if ((result = try_mount(v->device, mount_point, v->fs_type, v->fs_options)) == 0) return 0; if ((result = try_mount(v->device2, mount_point, v->fs_type, v->fs_options)) == 0) return 0; if ((result = try_mount(v->device, mount_point, v->fs_type2, v->fs_options2)) == 0) return 0; if ((result = try_mount(v->device2, mount_point, v->fs_type2, v->fs_options2)) == 0) return 0; return result; } else { // let's try mounting with the mount binary and hope for the best. char mount_cmd[PATH_MAX]; sprintf(mount_cmd, "mount %s", path); return __system(mount_cmd); } LOGE("unknown fs_type \"%s\" for %s\n", v->fs_type, mount_point); return -1; }