Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { char* result = NULL; if (argc != 1) { return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); } char *path; if (ReadArgs(state, argv, 1, &path) < 0) { return NULL; } ui_print("Formatting %s...\n", path); if (0 != format_volume(path)) { free(path); return StringValue(strdup("")); } if (strcmp(path, "/data") == 0 && has_datadata()) { ui_print("Formatting /datadata...\n", path); if (0 != format_volume("/datadata")) { free(path); return StringValue(strdup("")); } if (0 != format_volume(get_android_secure_path())) { free(path); return StringValue(strdup("")); } } done: return StringValue(strdup(path)); }
static void wipe_data(int confirm) { if (confirm) { static char** title_headers = NULL; if (title_headers == NULL) { char* headers[] = { "确认是否清除所有数据?", "这一步操作不可挽回.", "", NULL }; title_headers = prepend_title((const char**)headers); } char* items[] = { " 取消", " 确认 -- 删除所有用户数据", // [1] NULL }; int chosen_item = get_menu_selection(title_headers, items, 1, 0); if (chosen_item != 1) { return; } } ui_print("\n-- 格式化 Data...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); erase_volume("/sdcard/.android_secure"); ui_print("格式化 Data 完成.\n"); }
static void wipe_data(int confirm) { if (confirm) { static char** title_headers = NULL; if (title_headers == NULL) { char* headers[] = { "确认清空所有数据?", "", "", NULL }; title_headers = prepend_title((const char**)headers); } char* items[] = { " 是的 - 清空所有数据", //[1] " 取消 - 返回", // [0] NULL }; int chosen_item = get_menu_selection(title_headers, items, 1, 0); if (chosen_item != 0) { return; } } ui_print("\n-- 清空 data...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); erase_volume("/sdcard/.android_secure"); ui_print("所有数据清空完毕.\n"); }
static void wipe_data(int confirm) { if (confirm) { static char** title_headers = NULL; if (title_headers == NULL) { char* headers[] = { "Confirm wipe of all user data?", " THIS CAN NOT BE UNDONE.", "", NULL }; title_headers = prepend_title((const char**)headers); } char* items[] = { " No", " Yes -- delete all user data", // [1] NULL }; int chosen_item = get_menu_selection(title_headers, items, 1, 0); if (chosen_item != 1) { return; } } ui_print("\n-- Wiping data...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sdcard/.android_secure"); ui_print("Data wipe complete.\n"); }
void create_fstab() { struct stat info; __system("touch /etc/mtab"); FILE *file = fopen("/etc/fstab", "w"); if (file == NULL) { LOGW("Unable to create /etc/fstab!\n"); return; } Volume *vol = volume_for_path("/boot"); if (NULL != vol && strcmp(vol->fs_type, "mtd") != 0 && strcmp(vol->fs_type, "emmc") != 0 && strcmp(vol->fs_type, "bml") != 0) write_fstab_root("/boot", file); write_fstab_root("/cache", file); write_fstab_root("/data", file); if (has_datadata()) { write_fstab_root("/datadata", file); } write_fstab_root("/system", file); write_fstab_root("/sdcard", file); #ifdef RECOVERY_HAVE_SD_EXT write_fstab_root("/sd-ext", file); #endif fclose(file); LOGI("Completed outputting fstab.\n"); }
void process_volumes() { create_fstab(); if (is_data_media()) { setup_data_media(); } return; // dead code. if (device_flash_type() != BML) return; ui_print("Checking for ext4 partitions...\n"); int ret = 0; ret = bml_check_volume("/system"); ret |= bml_check_volume("/data"); if (has_datadata()) ret |= bml_check_volume("/datadata"); ret |= bml_check_volume("/cache"); if (ret == 0) { ui_print("Done!\n"); return; } char backup_path[PATH_MAX]; //time_t t = time(NULL); char backup_name[PATH_MAX]; struct timeval tp; gettimeofday(&tp, NULL); sprintf(backup_name, "before-ext4-convert-%d", tp.tv_sec); if (target_sdcard == TARGET_INTERNAL_SDCARD) { sprintf(backup_path, INTERNAL_SDCARD_PATH "/clockworkmod/backup/%s", backup_name); } else { sprintf(backup_path, EXTERNAL_SDCARD_PATH "/clockworkmod/backup/%s", backup_name); } ui_set_show_text(1); ui_print("Filesystems need to be converted to ext4.\n"); ui_print("A backup and restore will now take place.\n"); ui_print("If anything goes wrong, your backup will be\n"); ui_print("named %s. Try restoring it\n", backup_name); ui_print("in case of error.\n"); nandroid_backup(backup_path); nandroid_restore(backup_path, 1, 1, 1, 1, 1, 0); ui_set_show_text(0); }
static void wipe_data(int confirm) { if (confirm && !confirm_selection( "确定清空数据?", "是 - 清空数据")) return; ui_print("\n-- 正在清空Data分区...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); erase_volume("/sdcard/.android_secure"); ui_print("Data分区已清空\n"); }
static void wipe_data(int confirm) { if (confirm && !confirm_selection( "Confirm wipe of all user data?", "Yes - Wipe all user data")) return; ui_print("\n-- Wiping data...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); erase_volume("/sdcard/.android_secure"); ui_print("Data wipe complete.\n"); }
void process_volumes() { create_fstab(); if (is_data_media()) { setup_data_media(); } return; // dead code. if (device_flash_type() != BML) return; ui_print("正在校验 EXT4 分区...\n"); int ret = 0; ret = bml_check_volume("/system"); ret |= bml_check_volume("/data"); if (has_datadata()) ret |= bml_check_volume("/datadata"); ret |= bml_check_volume("/cache"); if (ret == 0) { ui_print("校验完成!\n"); return; } char backup_path[PATH_MAX]; time_t t = time(NULL); char backup_name[PATH_MAX]; struct timeval tp; gettimeofday(&tp, NULL); sprintf(backup_name, "before-ext4-convert-%d", tp.tv_sec); sprintf(backup_path, "/sdcard/clockworkmod/backup/%s", backup_name); ui_set_show_text(1); ui_print("文件系统将会被转换为 EXT4格式.\n"); ui_print("将会进行备份和恢复操作.\n"); ui_print("如果出现错误你可以恢复\n"); ui_print("文件名为%s的备份\n", backup_name); ui_print("在错误的情况下.\n"); nandroid_backup(backup_path); nandroid_restore(backup_path, 1, 1, 1, 1, 1, 0); ui_set_show_text(0); }
static void wipe_data(int confirm) { if (confirm) { static char** title_headers = NULL; if (title_headers == NULL) { char* headers[] = { "确认清空DATA分区?", "该操作将会删除您设备内的个人数据", "注意!该操作无法撤销.", "", NULL }; title_headers = prepend_title((const char**)headers); } char* items[] = { " 否", " 否", " 否", " 否", " 否", " 否", " 否", " 是 -- 清空所有个人数据", // [7] " 否", " 否", " 否", NULL }; int chosen_item = get_menu_selection(title_headers, items, 1, 0); if (chosen_item != 7) { return; } } ui_print("\n-- 正在清空DATA分区...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); erase_volume("/sdcard/.android_secure"); ui_print("DATA分区已清空.\n"); }
static void wipe_data(int confirm) { if (confirm) { static char** title_headers = NULL; if (title_headers == NULL) { char* headers[] = { "你真的要清除数据?", " 这个操作可是不允许撤销的啊 ", "", NULL }; title_headers = prepend_title((const char**)headers); } char* items[] = { " 呀买碟", " 呀买碟", " 呀买碟", " 呀买碟", " 呀买碟", " 呀买碟", " 呀买碟", " 我一定要删除所有用户数据", // [7] " 呀买碟", " 呀买碟", " 呀买碟", NULL }; int chosen_item = get_menu_selection(title_headers, items, 1, 0); if (chosen_item != 7) { return; } } ui_print("\n-- 清除数据中 \n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); erase_volume("/sdcard/.android_secure"); ui_print("已经抹掉数据\n"); }
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { char* result = NULL; if (argc != 1) { return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); } char *path; if (ReadArgs(state, argv, 1, &path) < 0) { return NULL; } ui_print("Formatting %s...\n", path); if (0 != format_volume(path)) { free(path); return StringValue(strdup("")); } if (strcmp(path, "/data") == 0 && has_datadata()) { ui_print("Formatting /datadata...\n", path); if (0 != format_volume("/datadata")) { free(path); return StringValue(strdup("")); } ensure_path_mounted("/sdcard"); ensure_path_mounted("/external_sd"); if( access( "/sdcard/clockworkmod/.is_as_external", F_OK ) != -1) { if (0 != format_volume("/external_sd/.android_secure")) { free(path); return StringValue(strdup("")); } } else { if (0 != format_volume("/sdcard/.android_secure")) { free(path); return StringValue(strdup("")); } } } done: return StringValue(strdup(path)); }
static void wipe_data(int confirm) { if (confirm && !confirm_selection( "确认清除所有数据?", "确认 - 清除所有用户数据")) return; ui_print("\n-- 正在清除数据...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); erase_volume("/sdcard/.android_secure"); if (volume_for_path("/external_sd") != NULL) erase_volume("/external_sd/.android_secure"); else if (volume_for_path("/emmc") != NULL) erase_volume("/emmc/.android_secure"); ui_print("清除数据完成.\n"); }
// remove static to be able to call it from ors menu void wipe_data(int confirm) { const char* headers[] = { "Wipe all user data ?", " data | cache | datadata", " sd-ext| android_secure", "", NULL }; if (confirm && !confirm_with_headers(headers, "Yes - Wipe all user data")) { return; } ui_print("\n-- Wiping data...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); // erase .android_secure from /sdcard or /storage/sdcard0 erase_volume(get_android_secure_path()); // erase .android_secure from any secondary storage char buf[80]; char** extra_paths = get_extra_storage_paths(); int num_extra_volumes = get_num_extra_volumes(); int i; if (extra_paths != NULL) { for(i = 0; i < num_extra_volumes; i++) { sprintf(buf, "%s/.android_secure", extra_paths[i]); erase_volume(buf); } free_string_array(extra_paths); } ui_print("Data wipe complete.\n"); }
static void wipe_data(int confirm) { if (confirm) { static char** title_headers = NULL; if (title_headers == NULL) { char* headers[] = { "Confirm wipe of ALL user data?", "following partitions will be WIPED:", " /data", " /cache", " /sd-ext", " /sdcard/.android_secure", "", " THIS CAN NOT BE UNDONE.", "", NULL }; title_headers = prepend_title((const char**)headers); } char* items[] = { " No", " Yes -- delete ALL user data", // [1] NULL }; int chosen_item = get_menu_selection(title_headers, items, 1, 0); if (chosen_item != 1) { return; } } ui_print("\n-- 正在清空用户数据...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); erase_volume("/sdcard/.android_secure"); ui_print("清空完毕\n"); }
int nandroid_restore(const char* backup_path, int restore_boot, int restore_system, int restore_data, int restore_cache, int restore_sdext, int restore_wimax) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); nandroid_files_total = 0; if (ensure_path_mounted(backup_path) != 0) return print_and_error("挂载分区失败\n"); char tmp[PATH_MAX]; ui_print("检查MD5 校验值...\n"); sprintf(tmp, "cd %s && md5sum -c nandroid.md5", backup_path); if (0 != __system(tmp)) return print_and_error("MD5不合法\n"); int ret; if (restore_boot) { if (NULL != volume_for_path("/boot") && 0 != (ret = nandroid_restore_partition(backup_path, "/boot"))) return ret; if (NULL != volume_for_path("/uboot") && 0 != (ret = nandroid_restore_partition(backup_path, "/uboot"))) return ret; if (NULL != volume_for_path("/recovery") && 0 != (ret = nandroid_restore_partition(backup_path, "/recovery"))) return ret; } struct stat s; Volume *vol = volume_for_path("/wimax"); if (restore_wimax && vol != NULL && 0 == stat(vol->device, &s)) { char serialno[PROPERTY_VALUE_MAX]; serialno[0] = 0; property_get("ro.serialno", serialno, ""); sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); struct stat st; if (0 != stat(tmp, &st)) { ui_print("警告: WiMAX分区存在,但是\n"); ui_print(" 不存在可恢复的WiMAX 镜像.\n"); ui_print(" 亦需要重新做一个备份 \n"); ui_print(" 来保护你的WiMAX keys.\n"); } else { ui_print("恢复之前先清除WiMAX...\n"); if (0 != (ret = format_volume("/wimax"))) return print_and_error("抹掉wimax失败!\n"); ui_print("恢复WiMAX 镜像...\n"); if (0 != (ret = restore_raw_partition(vol->fs_type, vol->device, tmp))) return ret; } } if (restore_system && 0 != (ret = nandroid_restore_partition(backup_path, "/system"))) return ret; if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "/data"))) return ret; if (has_datadata()) { if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "/datadata"))) return ret; } if (restore_data && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/sdcard/.android_secure", 0))) return ret; if (restore_cache && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/cache", 0))) return ret; if (restore_sdext && 0 != (ret = nandroid_restore_partition(backup_path, "/sd-ext"))) return ret; sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\n恢复完成!\n"); return 0; }
int nandroid_backup(const char* backup_path) { nandroid_backup_bitfield = 0; ui_set_background(BACKGROUND_ICON_INSTALLING); refresh_default_backup_handler(); if (ensure_path_mounted(backup_path) != 0) { return print_and_error("无法挂载备份时需要的存储器.\n"); } Volume* volume = volume_for_path(backup_path); if (NULL == volume) return print_and_error("找不到备份需要的存储器.\n"); if (is_data_media_volume_path(volume->mount_point)) volume = volume_for_path("/data"); int ret; struct statfs s; if (NULL != volume) { if (0 != (ret = statfs(volume->mount_point, &s))) return print_and_error("找不到备份路径,因此无法开始.\n"); uint64_t bavail = s.f_bavail; uint64_t bsize = s.f_bsize; uint64_t sdcard_free = bavail * bsize; uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024); ui_print("SD Card space free: %lluMB\n", sdcard_free_mb); if (sdcard_free_mb < 150) ui_print("可能是你的机器空间不足了,继续中...\n"); } char tmp[PATH_MAX]; ensure_directory(backup_path); if (0 != (ret = nandroid_backup_partition(backup_path, "/boot"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/uboot"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/recovery"))) return ret; Volume *vol = volume_for_path("/wimax"); if (vol != NULL && 0 == stat(vol->device, &s)) { char serialno[PROPERTY_VALUE_MAX]; ui_print("正在备份WiMAX...\n"); serialno[0] = 0; property_get("ro.serialno", serialno, ""); sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); ret = backup_raw_partition(vol->fs_type, vol->device, tmp); if (0 != ret) return print_and_error("打包或生成WiMAX镜像失败\n"); } if (0 != (ret = nandroid_backup_partition(backup_path, "/system"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/data"))) return ret; if (has_datadata()) { if (0 != (ret = nandroid_backup_partition(backup_path, "/datadata"))) return ret; } if (is_data_media() || 0 != stat("/sdcard/.android_secure", &s)) { ui_print("没找到 /sdcard/.android_secure. 跳过外部程序备份.\n"); } else { if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/sdcard/.android_secure", 0))) return ret; } if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0))) return ret; vol = volume_for_path("/sd-ext"); if (vol == NULL || 0 != stat(vol->device, &s)) { ui_print("没找到SD-EXT,因此跳过该处备份.\n"); } else { if (0 != ensure_path_mounted("/sd-ext")) ui_print("没法挂载SD-EXT,可能是你的机器不支持该选项,跳过该部分的备份\n"); else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) return ret; } ui_print("生成md5 校验值...\n"); sprintf(tmp, "nandroid-md5.sh %s", backup_path); if (0 != (ret = __system(tmp))) { ui_print("MD5校验值生成失败\n"); return ret; } sprintf(tmp, "cp /tmp/recovery.log %s/recovery.log", backup_path); __system(tmp); sprintf(tmp, "chmod -R 777 %s ; chmod -R u+r,u+w,g+r,g+w,o+r,o+w /sdcard/clockworkmod ; chmod u+x,g+x,o+x /sdcard/clockworkmod/backup ; chmod u+x,g+x,o+x /sdcard/clockworkmod/blobs", backup_path); __system(tmp); sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\n备份完成!\n"); return 0; }
int nandroid_restore(const char* backup_path, int restore_boot, int restore_system, int restore_data, int restore_cache, int restore_sdext, int restore_wimax) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); yaffs_files_total = 0; if (ensure_path_mounted("/sdcard") != 0) return print_and_error("Can't mount /sdcard\n"); char tmp[PATH_MAX]; ui_print("Checking MD5 sums...\n"); sprintf(tmp, "cd %s && md5sum -c nandroid.md5", backup_path); if (0 != __system(tmp)) return print_and_error("MD5 mismatch!\n"); int ret; if (restore_boot && NULL != volume_for_path("/boot") && 0 != (ret = nandroid_restore_partition(backup_path, "/boot"))) return ret; struct stat s; Volume *vol = volume_for_path("/wimax"); if (restore_wimax && vol != NULL && 0 == stat(vol->device, &s)) { char serialno[PROPERTY_VALUE_MAX]; serialno[0] = 0; property_get("ro.serialno", serialno, ""); sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); struct stat st; if (0 != stat(tmp, &st)) { ui_print("WARNING: WiMAX partition exists, but nandroid\n"); ui_print(" backup does not contain WiMAX image.\n"); ui_print(" You should create a new backup to\n"); ui_print(" protect your WiMAX keys.\n"); } else { ui_print("Erasing WiMAX before restore...\n"); if (0 != (ret = format_volume("/wimax"))) return print_and_error("Error while formatting wimax!\n"); ui_print("Restoring WiMAX image...\n"); if (0 != (ret = restore_raw_partition(vol->fs_type, vol->device, tmp))) return ret; } } if (restore_system && 0 != (ret = nandroid_restore_partition(backup_path, "/system"))) return ret; if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "/data"))) return ret; if (has_datadata()) { if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "/datadata"))) return ret; } if (restore_data && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/sdcard/.android_secure", 0))) return ret; if (restore_cache && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/cache", 0))) return ret; #ifdef RECOVERY_HAVE_SD_EXT if (restore_sdext && 0 != (ret = nandroid_restore_partition(backup_path, "/sd-ext"))) return ret; #endif sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nRestore complete!\n"); return 0; }
int nandroid_backup(const char* backup_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); if (ensure_path_mounted("/sdcard") != 0) return print_and_error("Can't mount /sdcard\n"); int ret; struct statfs s; if (0 != (ret = statfs("/sdcard", &s))) return print_and_error("Unable to stat /sdcard\n"); uint64_t bavail = s.f_bavail; uint64_t bsize = s.f_bsize; uint64_t sdcard_free = bavail * bsize; uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024); ui_print("SD Card space free: %lluMB\n", sdcard_free_mb); if (sdcard_free_mb < 150) ui_print("There may not be enough free space to complete backup... continuing...\n"); char tmp[PATH_MAX]; sprintf(tmp, "mkdir -p %s", backup_path); __system(tmp); if (0 != (ret = nandroid_backup_partition(backup_path, "/boot"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/recovery"))) return ret; Volume *vol = volume_for_path("/wimax"); if (vol != NULL && 0 == stat(vol->device, &s)) { char serialno[PROPERTY_VALUE_MAX]; ui_print("Backing up WiMAX...\n"); serialno[0] = 0; property_get("ro.serialno", serialno, ""); sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); ret = backup_raw_partition(vol->fs_type, vol->device, tmp); if (0 != ret) return print_and_error("Error while dumping WiMAX image!\n"); } if (0 != (ret = nandroid_backup_partition(backup_path, "/system"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/data"))) return ret; if (has_datadata()) { if (0 != (ret = nandroid_backup_partition(backup_path, "/datadata"))) return ret; } if (0 != stat("/sdcard/.android_secure", &s)) { ui_print("No /sdcard/.android_secure found. Skipping backup of applications on external storage.\n"); } else { if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/sdcard/.android_secure", 0))) return ret; } if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0))) return ret; #ifdef RECOVERY_HAVE_SD_EXT vol = volume_for_path("/sd-ext"); if (vol == NULL || 0 != stat(vol->device, &s)) { ui_print("No sd-ext found. Skipping backup of sd-ext.\n"); } else { if (0 != ensure_path_mounted("/sd-ext")) ui_print("Could not mount sd-ext. sd-ext backup may not be supported on this device. Skipping backup of sd-ext.\n"); else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) return ret; } #endif ui_print("Generating md5 sum...\n"); sprintf(tmp, "nandroid-md5.sh %s", backup_path); if (0 != (ret = __system(tmp))) { ui_print("Error while generating md5 sum!\n"); return ret; } sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 0; }
int nandroid_backup(const char* backup_path) { nandroid_backup_bitfield = 0; ui_set_background(BACKGROUND_ICON_INSTALLING); refresh_default_backup_handler(); if (ensure_path_mounted(backup_path) != 0) { return print_and_error("Can't mount backup path.\n"); } Volume* volume = volume_for_path(backup_path); if (NULL == volume) return print_and_error("Unable to find volume for backup path.\n"); if (is_data_media_volume_path(volume->mount_point)) volume = volume_for_path("/data"); int ret; struct statfs s; if (NULL != volume) { if (0 != (ret = statfs(volume->mount_point, &s))) return print_and_error("Unable to stat backup path.\n"); uint64_t bavail = s.f_bavail; uint64_t bsize = s.f_bsize; uint64_t sdcard_free = bavail * bsize; uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024); ui_print("SD Card space free: %lluMB\n", sdcard_free_mb); if (sdcard_free_mb < 150) ui_print("There may not be enough free space to complete backup... continuing...\n"); } char tmp[PATH_MAX]; ensure_directory(backup_path); if (0 != (ret = nandroid_backup_partition(backup_path, "/boot"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/recovery"))) return ret; Volume *vol = volume_for_path("/wimax"); if (vol != NULL && 0 == stat(vol->device, &s)) { char serialno[PROPERTY_VALUE_MAX]; ui_print("Backing up WiMAX...\n"); serialno[0] = 0; property_get("ro.serialno", serialno, ""); sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); ret = backup_raw_partition(vol->fs_type, vol->device, tmp); if (0 != ret) return print_and_error("Error while dumping WiMAX image!\n"); } if (0 != (ret = nandroid_backup_partition(backup_path, "/system"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/preload"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/data"))) return ret; if (has_datadata()) { if (0 != (ret = nandroid_backup_partition(backup_path, "/datadata"))) return ret; } if (is_data_media() || 0 != stat("/sdcard/.android_secure", &s)) { ui_print("No /sdcard/.android_secure found. Skipping backup of applications on external storage.\n"); } else { if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/sdcard/.android_secure", 0))) return ret; } if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0))) return ret; vol = volume_for_path("/sd-ext"); if (vol == NULL || 0 != stat(vol->device, &s)) { ui_print("No sd-ext found. Skipping backup of sd-ext.\n"); } else { if (0 != ensure_path_mounted("/sd-ext")) ui_print("Could not mount sd-ext. sd-ext backup may not be supported on this device. Skipping backup of sd-ext.\n"); else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) return ret; } ui_print("Generating md5 sum...\n"); sprintf(tmp, "nandroid-md5.sh %s", backup_path); if (0 != (ret = __system(tmp))) { ui_print("Error while generating md5 sum!\n"); return ret; } sprintf(tmp, "chmod -R 777 %s ; chmod -R u+r,u+w,g+r,g+w,o+r,o+w /sdcard/clockworkmod ; chmod u+x,g+x,o+x /sdcard/clockworkmod/backup ; chmod u+x,g+x,o+x /sdcard/clockworkmod/blobs", backup_path); __system(tmp); sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 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; } 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; }
void wipe_data(int confirm) { if (confirm) { static char** title_headers = NULL; if (title_headers == NULL) { char* headers[] = { "Confirm wipe of all user data?", " THIS CAN NOT BE UNDONE.", "", NULL }; title_headers = prepend_title((const char**)headers); } char* items[] = { " No", #if TARGET_BOOTLOADER_BOARD_NAME == otter " Yes -- delete all user data", // [1] #else " No", " No", " No", " No", " No", " No", " Yes -- delete all user data", // [7] " No", " No", " No", #endif NULL }; int chosen_item = get_menu_selection(title_headers, items, 1, 0); #if TARGET_BOOTLOADER_BOARD_NAME == otter if (chosen_item != 1) { #else if (chosen_itme != 7) { #endif return; } } ui_print("\n-- Wiping data...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } #if TARGET_BOOTLOADER_BOARD_NAME != otter // ToDo: make this check for the partition rather then the device erase_volume("/sd-ext"); #endif erase_volume("/sdcard/.android_secure"); ui_print("%s\n", datawipecomplete); } void erase_cache(int orscallback) { if(orscallback) { if(orswipeprompt && !confirm_selection("Confirm wipe?","Yes - Wipe Cache")) { ui_print("Skipping cache wipe...\n"); return; } } else if (!confirm_selection("Confirm wipe?", "Yes - Wipe Cache")) { return; } ui_print("\n-- Wiping cache...\n"); erase_volume("/cache"); ui_print("%s\n", cachewipecomplete); if (!ui_text_visible()) return; } void erase_dalvik_cache(int orscallback) { if(orscallback) { if(orswipeprompt && !confirm_selection("Confirm wipe?", "Yes - Wipe Dalvik Cache")) { ui_print("Skipping dalvik cache wipe...\n"); return; } } else if (!confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) { return; } if (0 != ensure_path_mounted("/data")) { return; } #if TARGET_BOOTLOADER_BOARD_NAME != otter ensure_path_mounted("/sd-ext"); #endif ensure_path_mounted("/cache"); __system("rm -r /data/dalvik-cache"); __system("rm -r /cache/dalvik-cache"); #if TARGET_BOOTLOADER_BOARD_NAME != otter __system("rm -r /sd-ext/dalvik-cache"); #endif ui_print("Dalvik Cache wiped.\n"); ensure_path_unmounted("/data"); } void wipe_all(int orscallback) { if(orscallback) { if(orswipeprompt && !confirm_selection("Confirm wipe all?", "Yes - Wipe All")) { ui_print("Skipping full wipe...\n"); return; } } else if (!confirm_selection("Confirm wipe all?", "Yes - Wipe All")) { return; } ui_print("\n-- Wiping system, data, cache...\n"); erase_volume("/system"); erase_volume("/data"); erase_volume("/cache"); ui_print("\nFull wipe complete!\n"); if (!ui_text_visible()) return; } int format_device(const char *device, const char *path, const char *fs_type) { Volume* v = volume_for_path(path); if (v == NULL) { // no /sdcard? let's assume /data/media if (strstr(path, "/sdcard") == path && is_data_media()) { return format_unknown_device(NULL, path, NULL); } // silent failure for sd-ext if (strcmp(path, "/sd-ext") == 0) return -1; LOGE("unknown volume \"%s\"\n", path); return -1; } if (strcmp(fs_type, "ramdisk") == 0) { // you can't format the ramdisk. LOGE("can't format_volume \"%s\"", path); return -1; } if (strcmp(fs_type, "rfs") == 0) { if (ensure_path_unmounted(path) != 0) { LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point); return -1; } if (0 != format_rfs_device(device, path)) { LOGE("format_volume: format_rfs_device failed on %s\n", device); return -1; } return 0; } if (strcmp(v->mount_point, path) != 0) { return format_unknown_device(v->device, path, NULL); } if (ensure_path_unmounted(path) != 0) { LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point); return -1; } if (strcmp(fs_type, "yaffs2") == 0 || strcmp(fs_type, "mtd") == 0) { mtd_scan_partitions(); const MtdPartition* partition = mtd_find_partition_by_name(device); if (partition == NULL) { LOGE("format_volume: no MTD partition \"%s\"\n", device); return -1; } MtdWriteContext *write = mtd_write_partition(partition); if (write == NULL) { LOGW("format_volume: can't open MTD \"%s\"\n", device); return -1; } else if (mtd_erase_blocks(write, -1) == (off_t) -1) { LOGW("format_volume: can't erase MTD \"%s\"\n", device); mtd_write_close(write); return -1; } else if (mtd_write_close(write)) { LOGW("format_volume: can't close MTD \"%s\"\n",device); return -1; } return 0; } if (strcmp(fs_type, "ext4") == 0) { int length = 0; if (strcmp(v->fs_type, "ext4") == 0) { // Our desired filesystem matches the one in fstab, respect v->length length = v->length; } reset_ext4fs_info(); int result = make_ext4fs(device, length, v->mount_point, sehandle); if (result != 0) { LOGE("format_volume: make_extf4fs failed on %s\n", device); return -1; } return 0; } return format_unknown_device(device, path, fs_type); }
void wipe_data(int confirm) { if (confirm) { static char** title_headers = NULL; if (title_headers == NULL) { char* headers[] = { "Confirm wipe of all user data?", " Confirm?", "", NULL }; title_headers = prepend_title((const char**)headers); } char* items[] = { " No", " No", " No", " No", " No", " No", " No", " Yes -- delete all user data", // [7] " No", " No", " No", NULL }; int chosen_item = get_menu_selection(title_headers, items, 1, 0); if (chosen_item != 7) { return; } } ui_print("\n-- Wiping data...\n"); device_wipe_data(); erase_volume("/data"); erase_volume("/cache"); if (has_datadata()) { erase_volume("/datadata"); } erase_volume("/sd-ext"); ensure_path_mounted("/sdcard"); #ifdef BOARD_HAS_REMOVABLE_STORAGE ensure_path_mounted("/external_sd"); if( access( "/sdcard/clockworkmod/.is_as_external", F_OK ) != -1) { erase_volume("/external_sd/.android_secure"); } else { #endif erase_volume("/sdcard/.android_secure"); #ifdef BOARD_HAS_REMOVABLE_STORAGE } #endif ui_print("Data wipe complete.\n"); ensure_path_mounted("/data"); ensure_path_mounted("/sdcard"); ensure_path_mounted("/external_sd"); struct stat st; if (0 == lstat("/sdcard/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 if (0 == lstat("/external_sd/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("/sdcard/0,/external_sd/0 not found. migration may occur in Android 4.2.\n"); } ensure_path_unmounted("/data"); }
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); } #ifdef RECOVERY_CHARGEMODE handle_chargemode(); #endif //__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)); #ifdef RECOVERY_CHARGEMODE int flag; flag = get_chargemode(); if(flag == 1){ // __system("mount /dev/block/mmcblk0p12 /system"); // __system("sleep 1"); __system("charge"); }else { #endif device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_WELCOME)"\n"); ui_print(EXPAND(RECOVERY_VERSION_INFO)"\n"); ui_print(EXPAND(RECOVERY_BUILD_DATE)"\n"); __system("/sbin/postrecoveryboot.sh"); #ifdef BOARD_RECOVERY_SWIPE #ifndef BOARD_TOUCH_RECOVERY //display directions for swipe controls ui_print("上/下滑动选择.\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(); 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(); enable_key_backlight(); 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("清除数据失败.\n"); } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("清除缓存失败.\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()) { 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; } #ifdef RECOVERY_CHARGEMODE return 0; }
int nandroid_backup(const char* backup_path) { nandroid_backup_bitfield = 0; ui_set_background(BACKGROUND_ICON_INSTALLING); refresh_default_backup_handler(); if (ensure_path_mounted(backup_path) != 0) { return print_and_error("Can't mount backup path.\n"); } Volume* volume = volume_for_path(backup_path); if (NULL == volume) return print_and_error("Unable to find volume for backup path.\n"); if (is_data_media_volume_path(volume->mount_point)) volume = volume_for_path("/data"); int ret; struct statfs s; if (NULL != volume) { if (0 != (ret = statfs(volume->mount_point, &s))) return print_and_error("Unable to stat backup path.\n"); uint64_t bavail = s.f_bavail; uint64_t bsize = s.f_bsize; uint64_t sdcard_free = bavail * bsize; uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024); ui_print("SD Card space free: %lluMB\n", sdcard_free_mb); if (sdcard_free_mb < 150) ui_print("There may not be enough free space to complete backup... continuing...\n"); } char tmp[PATH_MAX]; ensure_directory(backup_path); if (backup_boot && 0 != (ret = nandroid_backup_partition(backup_path, "/boot"))) return ret; if (backup_recovery && 0 != (ret = nandroid_backup_partition(backup_path, "/recovery"))) return ret; Volume *vol = volume_for_path("/wimax"); if (backup_wimax && vol != NULL && 0 == stat(vol->device, &s)) { char serialno[PROPERTY_VALUE_MAX]; ui_print("Backing up WiMAX...\n"); serialno[0] = 0; property_get("ro.serialno", serialno, ""); sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); ret = backup_raw_partition(vol->fs_type, vol->device, tmp); if (0 != ret) return print_and_error("Error while dumping WiMAX image!\n"); } //2 copies of efs are made: tarball and raw backup if (backup_efs) { //first backup in raw format, returns 0 on success (or if skipped), else 1 if (0 != custom_backup_raw_handler(backup_path, "/efs")) { ui_print("EFS raw image backup failed! Trying tar backup...\n"); } //second backup in tar format sprintf(tmp, "%s/efs_tar", backup_path); ensure_directory(tmp); if (0 != (ret = nandroid_backup_partition(tmp, "/efs"))) return ret; } if (backup_modem) { if (0 != (ret = nandroid_backup_partition(backup_path, "/modem"))) return ret; } if (backup_system && 0 != (ret = nandroid_backup_partition(backup_path, "/system"))) return ret; if (is_custom_backup && backup_preload) { if (0 != (ret = nandroid_backup_partition(backup_path, "/preload"))) { ui_print("Failed to backup /preload!\n"); return ret; } } else if (!is_custom_backup #ifdef PHILZ_TOUCH_RECOVERY && nandroid_add_preload #endif ) { if (0 != (ret = nandroid_backup_partition(backup_path, "/preload"))) { ui_print("Failed to backup preload! Try to disable it.\n"); ui_print("Skipping /preload...\n"); //return ret; } } if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/data"))) return ret; if (has_datadata()) { if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/datadata"))) return ret; } if (is_data_media() || 0 != stat("/sdcard/.android_secure", &s)) { ui_print("No /sdcard/.android_secure found. Skipping backup of applications on external storage.\n"); } else { if (backup_data && 0 != (ret = nandroid_backup_partition_extended(backup_path, "/sdcard/.android_secure", 0))) return ret; } if (backup_cache && 0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0))) return ret; if (backup_sdext) { vol = volume_for_path("/sd-ext"); if (vol == NULL || 0 != stat(vol->device, &s)) { ui_print("No sd-ext found. Skipping backup of sd-ext.\n"); } else { if (0 != ensure_path_mounted("/sd-ext")) ui_print("Could not mount sd-ext. sd-ext backup may not be supported on this device. Skipping backup of sd-ext.\n"); else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) return ret; } } #ifdef PHILZ_TOUCH_RECOVERY if (enable_md5sum) #endif { ui_print("Generating md5 sum...\n"); sprintf(tmp, "nandroid-md5.sh %s", backup_path); if (0 != (ret = __system(tmp))) { ui_print("Error while generating md5 sum!\n"); return ret; } } sprintf(tmp, "chmod -R 777 %s ; chmod -R u+r,u+w,g+r,g+w,o+r,o+w /sdcard/clockworkmod ; chmod u+x,g+x,o+x /sdcard/clockworkmod/backup ; chmod u+x,g+x,o+x /sdcard/clockworkmod/blobs", backup_path); __system(tmp); sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 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; }
int nandroid_restore(const char* backup_path, int restore_boot, int restore_system, int restore_data, int restore_cache, int restore_sdext, int restore_wimax) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); if (ensure_path_mounted(backup_path) != 0) return print_and_error("Can't mount backup path\n"); char tmp[PATH_MAX]; #ifdef PHILZ_TOUCH_RECOVERY if (enable_md5sum) #endif { ui_print("Checking MD5 sums...\n"); sprintf(tmp, "cd %s && md5sum -c nandroid.md5", backup_path); if (0 != __system(tmp)) return print_and_error("MD5 mismatch!\n"); } int ret; if (restore_boot && NULL != volume_for_path("/boot") && 0 != (ret = nandroid_restore_partition(backup_path, "/boot"))) return ret; if (backup_recovery && 0 != (ret = nandroid_restore_partition(backup_path, "/recovery"))) return ret; struct stat s; Volume *vol = volume_for_path("/wimax"); if (restore_wimax && vol != NULL && 0 == stat(vol->device, &s)) { char serialno[PROPERTY_VALUE_MAX]; serialno[0] = 0; property_get("ro.serialno", serialno, ""); sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); struct stat st; if (0 != stat(tmp, &st)) { ui_print("WARNING: WiMAX partition exists, but nandroid\n"); ui_print(" backup does not contain WiMAX image.\n"); ui_print(" You should create a new backup to\n"); ui_print(" protect your WiMAX keys.\n"); } else { ui_print("Erasing WiMAX before restore...\n"); if (0 != (ret = format_volume("/wimax"))) return print_and_error("Error while formatting wimax!\n"); ui_print("Restoring WiMAX image...\n"); if (0 != (ret = restore_raw_partition(vol->fs_type, vol->device, tmp))) return ret; } } // restore of raw efs image files (efs_time-stamp.img) is done elsewhere // as it needs to pass in a filename (instead of a folder) as backup_path // this could be done here since efs is processed alone, but must be done before md5 checksum! if (backup_efs == RESTORE_EFS_TAR && 0 != (ret = nandroid_restore_partition(backup_path, "/efs"))) return ret; if (backup_modem == RAW_IMG_FILE && 0 != (ret = nandroid_restore_partition(backup_path, "/modem"))) return ret; else if (backup_modem == RAW_BIN_FILE) { sprintf(tmp, "%s/modem.bin", backup_path); custom_restore_raw_handler(tmp, "/modem"); } if (restore_system && 0 != (ret = nandroid_restore_partition(backup_path, "/system"))) return ret; if (is_custom_backup && backup_preload) { if (0 != (ret = nandroid_restore_partition(backup_path, "/preload"))) { ui_print("Failed to restore /preload!\n"); return ret; } } else if (!is_custom_backup #ifdef PHILZ_TOUCH_RECOVERY && nandroid_add_preload #endif ) { if (restore_system && 0 != (ret = nandroid_restore_partition(backup_path, "/preload"))) { ui_print("Failed to restore preload! Try to disable it.\n"); ui_print("Skipping /preload...\n"); //return ret; } } if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "/data"))) return ret; if (has_datadata()) { if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "/datadata"))) return ret; } if (restore_data && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/sdcard/.android_secure", 0))) return ret; if (restore_cache && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/cache", 0))) return ret; if (restore_sdext && 0 != (ret = nandroid_restore_partition(backup_path, "/sd-ext"))) return ret; sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nRestore complete!\n"); return 0; }
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; }
int main(int argc, char **argv) { 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], "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); // Recovery needs to install world-readable files, so clear umask // set by init 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)); 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; 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 '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 (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 (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 { 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_show_text(1); ui_set_background(BACKGROUND_ICON_ERROR); } 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"); #ifdef BOARD_HAS_DUAL_SYSTEM if(multiboot==1){ #endif android_reboot(ANDROID_RB_RESTART, 0, 0); #ifdef BOARD_HAS_DUAL_SYSTEM }else{ set_reboot_message(multiboot==2); sync(); android_reboot(ANDROID_RB_RESTART, 0, 0); } #endif } else { ui_print("关闭手机...\n"); android_reboot(ANDROID_RB_POWEROFF, 0, 0); } return EXIT_SUCCESS; }
int nandroid_backup(const char* backup_path) { nandroid_backup_bitfield = 0; ui_set_background(BACKGROUND_ICON_INSTALLING); refresh_default_backup_handler(); if (ensure_path_mounted(backup_path) != 0) { #ifndef USE_CHINESE_FONT return print_and_error("Can't mount backup path.\n"); #else return print_and_error("无法挂载备份路径。\n"); #endif } Volume* volume; if (is_data_media_volume_path(backup_path)) volume = volume_for_path("/data"); else volume = volume_for_path(backup_path); if (NULL == volume) #ifndef USE_CHINESE_FONT return print_and_error("Unable to find volume for backup path.\n"); #else return print_and_error("无法找到备份路径所在卷。\n"); #endif int ret; struct statfs sfs; struct stat s; if (NULL != volume) { if (0 != (ret = statfs(volume->mount_point, &sfs))) #ifndef USE_CHINESE_FONT return print_and_error("Unable to stat backup path.\n"); #else return print_and_error("无法统计备份路径。\n"); #endif uint64_t bavail = sfs.f_bavail; uint64_t bsize = sfs.f_bsize; uint64_t sdcard_free = bavail * bsize; uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024); #ifndef USE_CHINESE_FONT ui_print("SD Card space free: %lluMB\n", sdcard_free_mb); #else ui_print("SD 卡剩余空间: %lluMB\n", sdcard_free_mb); #endif if (sdcard_free_mb < 150) #ifndef USE_CHINESE_FONT ui_print("There may not be enough free space to complete backup... continuing...\n"); #else ui_print("可能没有足够的空间完成备份... 继续...\n"); #endif } char tmp[PATH_MAX]; ensure_directory(backup_path); if (0 != (ret = nandroid_backup_partition(backup_path, "/boot"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/recovery"))) return ret; Volume *vol = volume_for_path("/wimax"); if (vol != NULL && 0 == stat(vol->blk_device, &s)) { char serialno[PROPERTY_VALUE_MAX]; #ifndef USE_CHINESE_FONT ui_print("Backing up WiMAX...\n"); #else ui_print("正在备份 WiMAX...\n"); #endif serialno[0] = 0; property_get("ro.serialno", serialno, ""); sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); ret = backup_raw_partition(vol->fs_type, vol->blk_device, tmp); if (0 != ret) #ifndef USE_CHINESE_FONT return print_and_error("Error while dumping WiMAX image!\n"); #else return print_and_error("导出 WiMAX 镜像时出错!\n"); #endif } if (0 != (ret = nandroid_backup_partition(backup_path, "/system"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "/data"))) return ret; if (has_datadata()) { if (0 != (ret = nandroid_backup_partition(backup_path, "/datadata"))) return ret; } if (is_data_media() || 0 != stat(get_android_secure_path(), &s)) { #ifndef USE_CHINESE_FONT ui_print("No .android_secure found. Skipping backup of applications on external storage.\n"); #else ui_print("未找到 .android_secure。跳过备份安装在外置存储卡上的应用程序。\n"); #endif } else { if (0 != (ret = nandroid_backup_partition_extended(backup_path, get_android_secure_path(), 0))) return ret; } if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0))) return ret; vol = volume_for_path("/sd-ext"); if (vol == NULL || 0 != stat(vol->blk_device, &s)) { #ifndef USE_CHINESE_FONT LOGI("No sd-ext found. Skipping backup of sd-ext.\n"); #else LOGI("未找到 sd-ext。跳过对 sd-ext 的备份。\n"); #endif } else { if (0 != ensure_path_mounted("/sd-ext")) #ifndef USE_CHINESE_FONT LOGI("Could not mount sd-ext. sd-ext backup may not be supported on this device. Skipping backup of sd-ext.\n"); #else LOGI("无法挂载 sd-ext。此设备可能不支持对 sd-ext 进行备份,跳过对sd-ext的备份。\n"); #endif else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) return ret; }