int nandroid_backup_cache(const char* backup_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); if (ensure_root_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_extended(backup_path, "CACHE:", 0))) return ret; sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 0; }
int tarbackup_backup(const char* backup_path, int backup_system, int backup_data, int backup_cache, int backup_android_secure) { ui_set_background(BACKGROUND_ICON_INSTALLING); if (ensure_root_path_mounted("SDCARD:") != 0) return print_and_error("Can't mount /sdcard\n"); int ret=0; 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 < 220) 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 (backup_system && 0 != (ret = tarbackup_backup_partition_extended(backup_path, "SYSTEM:", 1))) return ret; if (backup_data && 0 != (ret = tarbackup_backup_partition_extended(backup_path, "DATA:", 1))) return ret; if (backup_data && 0 != (ret = tarbackup_backup_partition_extended(backup_path, "DATADATA:", 1))) return ret; /* struct stat st; if (0 != stat("/sdcard/.android_secure", &st)) { 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 (backup_cache && 0 != (ret = tarbackup_backup_partition_extended(backup_path, "CACHE:", 0))) 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; } */ sync(); ui_set_background(BACKGROUND_ICON_EBCLOCKWORK); ui_reset_progress(); ui_print("\nBackup complete!\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) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); yaffs_files_total = 0; if (ensure_root_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; #ifndef BOARD_RECOVERY_IGNORE_BOOTABLES if (restore_boot) { ui_print("Erasing boot before restore...\n"); if (0 != (ret = format_root_device("BOOT:"))) return print_and_error("Error while formatting BOOT:!\n"); sprintf(tmp, "%s/boot.img", backup_path); ui_print("Restoring boot image...\n"); if (0 != (ret = restore_raw_partition("boot", tmp))) { ui_print("Error while flashing boot image!"); return ret; } } #endif 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; #ifdef BOARD_HAS_DATADATA if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "DATADATA:"))) return ret; #endif 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, "SDEXT:"))) return ret; sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nRestore complete!\n"); return 0; }
int nandroid_restore_datamedia(const char* backup_path) { char tmp[PATH_MAX]; ui_print("\n>> Restoring /data/media...\n"); if (is_data_media_volume_path(backup_path)) { // non fatal failure LOGE(" - can't restore folder to its self, skipping...\n"); return 0; } Volume *v = volume_for_path("/data"); if (v == NULL) return -1; sprintf(tmp, "%s/%s", get_primary_storage_path(), NANDROID_HIDE_PROGRESS_FILE); ensure_path_mounted(tmp); int callback = !file_found(tmp); struct stat s; char backup_file_image[PATH_MAX]; const char *filesystems[] = { "yaffs2", "ext2", "ext3", "ext4", "vfat", "exfat", "rfs", "f2fs", "auto", NULL }; const char *filesystem; int i = 0; nandroid_restore_handler restore_handler = NULL; while ((filesystem = filesystems[i]) != NULL) { sprintf(backup_file_image, "%s/datamedia.%s.tar", backup_path, filesystem); if (0 == stat(backup_file_image, &s)) { restore_handler = tar_extract_wrapper; sprintf(tmp, "cd / ; set -o pipefail ; cat %s* | tar -xpv ; exit $?", backup_file_image); break; } sprintf(backup_file_image, "%s/datamedia.%s.tar.gz", backup_path, filesystem); if (0 == stat(backup_file_image, &s)) { restore_handler = tar_gzip_extract_wrapper; sprintf(tmp, "cd / ; set -o pipefail ; cat %s* | pigz -d -c | tar -xpv ; exit $?", backup_file_image); break; } i++; } if (filesystem == NULL || restore_handler == NULL) { LOGE("No backup found, skipping...\n"); return 0; } if (0 != format_unknown_device(NULL, "/data/media", NULL)) return print_and_error("Error while erasing /data/media\n", NANDROID_ERROR_GENERAL); // data can be unmounted by format_unknown_device() if (0 != ensure_path_mounted("/data")) return -1; if (0 != do_tar_extract(tmp, backup_file_image, "/data", callback)) return print_and_error("Failed to restore /data/media!\n", NANDROID_ERROR_GENERAL); ui_print("Restore of /data/media completed.\n"); return 0; }
int nandroid_backup_sd(const char* backup_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); 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) { if (strstr(backup_path, "/sdcard") == backup_path && is_data_media()) volume = volume_for_path("/data"); else return print_and_error("Unable to find volume for backup path.\n"); } 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]; sprintf(tmp, "mkdir -p %s", backup_path); __system(tmp); Volume *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; } sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 0; }
int nandroid_advanced_backup(const char* backup_path, const char *root) { 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) { if (strstr(backup_path, "/sdcard") == backup_path && is_data_media()) volume = volume_for_path("/data"); else return print_and_error("Unable to find volume for backup path.\n"); } 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]; sprintf(tmp, "mkdir -p %s", backup_path); __system(tmp); if (0 != (ret = nandroid_backup_partition(backup_path, root))) 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; } sync(); ui_print("\nBackup complete!\n"); return 0; }
int nandroid_backup_sd(const char* backup_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); if (ensure_root_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); struct stat st; if (0 != stat(BOARD_SDEXT_DEVICE, &st)) { ui_print("No sd-ext found. Skipping backup of sd-ext.\n"); } else { if (0 != ensure_root_path_mounted("SDEXT:")) 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, "SDEXT:"))) return ret; } sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 0; }
int nandroid_backup_boot(const char* backup_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); if (ensure_root_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); #ifndef BOARD_RECOVERY_IGNORE_BOOTABLES ui_print("Backing up boot...\n"); sprintf(tmp, "%s/%s", backup_path, "boot.img"); ret = backup_raw_partition("boot", tmp); if (0 != ret) return print_and_error("Error while dumping boot image!\n"); #endif sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 0; }
// backup /data/media support // we reach here only if backup_data_media == 1 // backup_data_media can be set to 1 only in "custom backup and restore" menu AND if is_data_media() && !twrp_backup_mode.value int nandroid_backup_datamedia(const char* backup_path) { char tmp[PATH_MAX]; ui_print("\n>> Backing up /data/media...\n"); if (is_data_media_volume_path(backup_path)) { // non fatal failure LOGE(" - can't backup folder to its self, skipping...\n"); return 0; } if (0 != ensure_path_mounted("/data")) return -1; sprintf(tmp, "%s/%s", get_primary_storage_path(), NANDROID_HIDE_PROGRESS_FILE); ensure_path_mounted(tmp); int callback = !file_found(tmp); compute_directory_stats("/data/media"); Volume *v = volume_for_path("/data"); if (v == NULL) return -1; char backup_file_image[PATH_MAX]; sprintf(backup_file_image, "%s/datamedia.%s", backup_path, v->fs_type == NULL ? "auto" : v->fs_type); int fmt; fmt = nandroid_get_default_backup_format(); if (fmt == NANDROID_BACKUP_FORMAT_TAR) { sprintf(tmp, "cd / ; touch %s.tar ; set -o pipefail ; (tar -cpv data/media | split -a 1 -b 1000000000 /proc/self/fd/0 %s.tar.) 2> /proc/self/fd/1 ; exit $?", backup_file_image, backup_file_image); } else if (fmt == NANDROID_BACKUP_FORMAT_TGZ) { sprintf(tmp, "cd / ; touch %s.tar.gz ; set -o pipefail ; (tar -cpv data/media | pigz -c -%d | split -a 1 -b 1000000000 /proc/self/fd/0 %s.tar.gz.) 2> /proc/self/fd/1 ; exit $?", backup_file_image, compression_value.value, backup_file_image); } else { // non fatal failure LOGE(" - backup format must be tar(.gz), skipping...\n"); return 0; } int ret; ret = do_tar_compress(tmp, callback, backup_file_image); ensure_path_unmounted("/data"); if (0 != ret) return print_and_error("Failed to backup /data/media!\n", ret); ui_print("Backup of /data/media completed.\n"); return 0; }
int nandroid_backup_androidSecure(const char* backup_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); if (ensure_root_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"); struct stat st; if (0 != stat("/mnt/sdcard/.android_secure", &st)) { ui_print("No /mnt/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; } sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 0; }
int nandroid_restore_sd(const char* backup_path, int restore_sdext) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); yaffs_files_total = 0; if (ensure_path_mounted(backup_path) != 0) return print_and_error("Can't mount backup path\n"); char tmp[PATH_MAX]; int 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 nandroid_restore_androidSecure(const char* backup_path, int restore_androidSecure) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); yaffs_files_total = 0; if (ensure_root_path_mounted("SDCARD:") != 0) return print_and_error("Can't mount /sdcard\n"); char tmp[PATH_MAX]; int ret; if (restore_androidSecure && 0 != (ret = nandroid_restore_partition_extended(backup_path, "SDCARD:/.android_secure", 0))) return ret; sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\nRestore complete!\n"); return 0; }
int tarbackup_restore(const char* backup_path, int restore_system, int restore_data, int restore_cache, int restore_sdext) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); if (ensure_root_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=0; if (restore_system && 0 != (ret = tarbackup_restore_partition_extended(backup_path, "SYSTEM:", 1))) return ret; if (restore_data && 0 != (ret = tarbackup_restore_partition_extended(backup_path, "DATA:", 1))) return ret; if (restore_data && 0 != (ret = tarbackup_restore_partition_extended(backup_path, "DATADATA:", 1))) return ret; /* if (restore_data && 0 != (ret = tarbackup_restore_partition_extended(backup_path, "SDCARD:/.android_secure", 0))) return ret; */ if (restore_cache && 0 != (ret = tarbackup_restore_partition_extended(backup_path, "CACHE:", 0))) return ret; sync(); ui_set_background(BACKGROUND_ICON_EBCLOCKWORK); ui_reset_progress(); ui_print("\nRestore complete!\n"); detect_root_fs(); 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; }
// custom raw restore handler // used to restore efs in raw mode or modem.bin files // for now, only called directly from outside functions (not from nandroid_restore()) // user selects an image file to restore, so backup_file_image path is already mounted int dd_raw_restore_handler(const char* backup_file_image, const char* root) { ui_print("\n>> Restoring %s...\n", root); Volume *vol = volume_for_path(root); if (vol == NULL || vol->fs_type == NULL) { ui_print("volume not found! Skipping raw restore of %s...\n", root); return 0; } ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); // make sure we have a valid image file name int i = 0; char errmsg[PATH_MAX]; char tmp[PATH_MAX]; char filename[PATH_MAX]; const char *raw_image_format[] = { ".img", ".bin", NULL }; sprintf(filename, "%s", BaseName(backup_file_image)); while (raw_image_format[i] != NULL) { if (strlen(filename) > strlen(raw_image_format[i]) && strcmp(filename + strlen(filename) - strlen(raw_image_format[i]), raw_image_format[i]) == 0 && strncmp(filename, vol->mount_point + 1, strlen(vol->mount_point)-1) == 0) { break; } i++; } if (raw_image_format[i] == NULL) { sprintf(errmsg, "invalid image file! Failed to restore %s to %s\n", filename, root); return print_and_error(errmsg, NANDROID_ERROR_GENERAL); } //make sure file exists if (!file_found(backup_file_image)) { sprintf(errmsg, "%s not found. Skipping restore of %s\n", backup_file_image, root); return print_and_error(errmsg, NANDROID_ERROR_GENERAL); } //restore raw image int ret = 0; char* device_mmcblk; ui_print("Restoring %s to %s\n", filename, vol->mount_point); if (strstr(vol->blk_device, "/dev/block/mmcblk") != NULL || strstr(vol->blk_device, "/dev/block/mtdblock") != NULL) { sprintf(tmp, "raw-backup.sh -r '%s' %s %s", backup_file_image, vol->blk_device, vol->mount_point); } else if (vol->blk_device2 != NULL && (strstr(vol->blk_device2, "/dev/block/mmcblk") != NULL || strstr(vol->blk_device2, "/dev/block/mtdblock") != NULL)) { sprintf(tmp, "raw-backup.sh -r '%s' %s %s", backup_file_image, vol->blk_device2, vol->mount_point); } else if ((device_mmcblk = readlink_device_blk(root)) != NULL) { sprintf(tmp, "raw-backup.sh -r '%s' %s %s", backup_file_image, device_mmcblk, vol->mount_point); free(device_mmcblk); } else { sprintf(errmsg, "raw restore: no device found (%s)\n", root); return print_and_error(errmsg, NANDROID_ERROR_GENERAL); } ret = __system(tmp); if (0 != ret) { sprintf(errmsg, "failed raw restore of %s to %s\n", filename, root); print_and_error(errmsg, ret); } else { finish_nandroid_job(); } sprintf(tmp, "%s/log.txt", DirName(backup_file_image)); ui_print_custom_logtail(tmp, 3); return ret; }
void dumping_odin_image(const char* root) { if (strcmp(get_type_internal_fs(root), "rfs")) { ui_print("You can use this only for RFS filesystem!\n"); return -1; } struct statfs s; if (0 != 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 < 400) ui_print("There may not be enough free space to complete dump... continuing...\n"); int n_odin_ifile=0; const char* odin_ifile[3] = { "factoryfs.rfs", "datafs.rfs", "cache.rfs" }; char backup_path[PATH_MAX], sdev[32], *st; if (!strcmp(root, "DATA:")) n_odin_ifile = 1; else if (!strcmp(root, "CACHE:")) n_odin_ifile = 2; char tar_file[PATH_MAX]; time_t t = time(NULL); struct tm *tmp = localtime(&t); if (tmp == NULL) { struct timeval tp; gettimeofday(&tp, NULL); sprintf(tar_file, "%d", tp.tv_sec); } else { strftime(tar_file, sizeof(tar_file), "%F.%H.%M.%S", tmp); } ensure_root_path_unmounted(root); if (ensure_root_path_mounted("SDCARD:") != 0) { LOGE ("Can't mount /sdcard\n"); return; } if (0 != __system("mkdir -p /sdcard/ebrecovery/odin/tmp")) { ui_print("Can't create tmp folder for backup\n"); return -1; } strcpy(sdev, get_dev_for_root(root)); if (st = strstr(sdev, "stl")) { memcpy(st, "bml", 3); } else { ui_print("Mistake in device name %s\n", sdev); return -1; } ui_print("Dumping %s..\n", root); sprintf(backup_path, "fdump -t %s /sdcard/ebrecovery/odin/tmp/%s", sdev, odin_ifile[n_odin_ifile]); if (0 != __system(backup_path)) { ui_print("Can't create odin image [%s]\n", odin_ifile[n_odin_ifile]); return -1; } sprintf(backup_path, "cd /sdcard/ebrecovery/odin/tmp && tar -cf ../%s.tar %s", tar_file, odin_ifile[n_odin_ifile]); if (0 != __system(backup_path)) { ui_print("Can't create odin image [%s]\n", odin_ifile[n_odin_ifile]); return -1; } __system("rm -r /sdcard/ebrecovery/odin/tmp"); ui_print("Done\n"); }
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 nandroid_backup_flags(const char* backup_path, int flags) { ui_set_background(BACKGROUND_ICON_INSTALLING); if (ensure_root_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); #ifndef BOARD_RECOVERY_IGNORE_BOOTABLES ui_print("Backing up boot...\n"); sprintf(tmp, "%s/%s", backup_path, "boot.img"); ret = read_raw_image("boot", tmp); if (0 != ret) return print_and_error("Error while dumping boot image!\n"); ui_print("Backing up recovery...\n"); sprintf(tmp, "%s/%s", backup_path, "recovery.img"); ret = read_raw_image("recovery", tmp); if (0 != ret) return print_and_error("Error while dumping recovery image!\n"); #endif if (0 != (ret = nandroid_backup_partition(backup_path, "SYSTEM:"))) return ret; if (0 != (ret = nandroid_backup_partition(backup_path, "DATA:"))) return ret; #ifdef HAS_DATADATA if (0 != (ret = nandroid_backup_partition(backup_path, "DATADATA:"))) return ret; #endif struct stat st; if (0 != stat("/sdcard/.android_secure", &st)) { 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; if (0 != stat(SDEXT_DEVICE, &st)) { ui_print("No sd-ext found. Skipping backup of sd-ext.\n"); } else { if (0 != ensure_root_path_mounted("SDEXT:")) 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, "SDEXT:"))) 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; } sync(); ui_set_background(BACKGROUND_ICON_EBCLOCKWORK); ui_reset_progress(); ui_print("\nBackup complete!\n"); return 0; }
int twrp_backup(const char* backup_path) { // keep this for extra security and keep close to stock code // refresh_default_backup_handler() mounts /sdcard. We stat it in nandroid_backup_partition_extended() for callback nandroid_backup_bitfield = 0; refresh_default_backup_handler(); if (ensure_path_mounted(backup_path) != 0) return print_and_error("Can't mount backup path.\n", NANDROID_ERROR_GENERAL); int ret; struct statfs s; // refresh size stats for backup_path // this will also ensure volume for backup path != NULL if (0 != Get_Size_Via_statfs(backup_path)) return print_and_error("Unable to stat backup path.\n", NANDROID_ERROR_GENERAL); // estimate backup size and ensure we have enough free space available on backup_path if (check_backup_size(backup_path) < 0) return print_and_error("Not enough free space: backup cancelled.\n", NANDROID_ERROR_GENERAL); // moved after backup size check to fix pause before showing low space prompt // this is caused by friendly log view triggering on ui_set_background(BACKGROUND_ICON_INSTALLING) call // also, it is expected to have the background installing icon when we actually start backup ui_set_background(BACKGROUND_ICON_INSTALLING); nandroid_start_msec = timenow_msec(); // starts backup monitoring timer for total backup time #ifdef PHILZ_TOUCH_RECOVERY last_key_ev = nandroid_start_msec; // support dim screen timeout during nandroid operation #endif char tmp[PATH_MAX]; ensure_directory(backup_path, 0755); if (backup_boot && volume_for_path(BOOT_PARTITION_MOUNT_POINT) != NULL && 0 != (ret = nandroid_backup_partition(backup_path, BOOT_PARTITION_MOUNT_POINT))) return print_and_error(NULL, ret); if (backup_recovery && volume_for_path("/recovery") != NULL && 0 != (ret = nandroid_backup_partition(backup_path, "/recovery"))) return print_and_error(NULL, ret); #ifdef BOARD_USE_MTK_LAYOUT if ((backup_boot || backup_recovery) && volume_for_path("/uboot") != NULL && 0 != (ret = nandroid_backup_partition(backup_path, "/uboot"))) return print_and_error(NULL, ret); #endif Volume *vol = volume_for_path("/efs"); if (backup_efs && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/efs"))) return print_and_error(NULL, ret); } vol = volume_for_path("/misc"); if (backup_misc && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/misc"))) return print_and_error(NULL, ret); } vol = volume_for_path("/modem"); if (backup_modem && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/modem"))) return print_and_error(NULL, ret); } vol = volume_for_path("/radio"); if (backup_radio && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/radio"))) return print_and_error(NULL, ret); } if (backup_system && 0 != (ret = nandroid_backup_partition(backup_path, "/system"))) return print_and_error(NULL, ret); vol = volume_for_path("/preload"); if (backup_preload && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/preload"))) return print_and_error(NULL, ret); } if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/data"))) return print_and_error(NULL, ret); if (has_datadata()) { if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/datadata"))) return print_and_error(NULL, ret); } // handle .android_secure on external and internal storage set_android_secure_path(tmp); if (backup_data && android_secure_ext) { if (0 != (ret = nandroid_backup_partition_extended(backup_path, tmp, 0))) return print_and_error(NULL, ret); } if (backup_cache && 0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0))) return print_and_error(NULL, ret); if (backup_sdext) { if (0 != ensure_path_mounted("/sd-ext")) { LOGI("No sd-ext found. Skipping backup of sd-ext.\n"); } else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) { return print_and_error(NULL, ret); } } // handle extra partitions int i; int extra_partitions_num = get_extra_partitions_state(); for (i = 0; i < extra_partitions_num; ++i) { if (extra_partition[i].backup_state && 0 != (ret = nandroid_backup_partition(backup_path, extra_partition[i].mount_point))) return print_and_error(NULL, ret); } if (enable_md5sum.value) { if (0 != (ret = gen_twrp_md5sum(backup_path))) return print_and_error(NULL, ret); } sprintf(tmp, "chmod -R 777 %s", backup_path); __system(tmp); finish_nandroid_job(); show_backup_stats(backup_path); if (reboot_after_nandroid) reboot_main_system(ANDROID_RB_RESTART, 0, 0); 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 twrp_restore(const char* backup_path) { Backup_Size = 0; // by default, do not calculate size // progress bar will be of indeterminate progress // setting nandroid_files_total = 0 will force this in nandroid_callback() ui_set_background(BACKGROUND_ICON_INSTALLING); nandroid_files_total = 0; nandroid_start_msec = timenow_msec(); #ifdef PHILZ_TOUCH_RECOVERY // support dim screen timeout during nandroid operation last_key_ev = timenow_msec(); #endif if (ensure_path_mounted(backup_path) != 0) return print_and_error("Can't mount backup path\n", NANDROID_ERROR_GENERAL); char tmp[PATH_MAX]; if (enable_md5sum.value) { if (0 != check_twrp_md5sum(backup_path)) return print_and_error("MD5 mismatch!\n", NANDROID_ERROR_GENERAL); } ui_show_indeterminate_progress(); // call after verify_nandroid_md5sum() as it will reset the progress int ret; if (backup_boot && volume_for_path(BOOT_PARTITION_MOUNT_POINT) != NULL && 0 != (ret = nandroid_restore_partition(backup_path, BOOT_PARTITION_MOUNT_POINT))) return print_and_error(NULL, ret); if (backup_recovery && volume_for_path("/recovery") != NULL && 0 != (ret = nandroid_restore_partition(backup_path, "/recovery"))) return print_and_error(NULL, ret); #ifdef BOARD_USE_MTK_LAYOUT if ((backup_boot || backup_recovery) && volume_for_path("/uboot") != NULL && 0 != (ret = nandroid_restore_partition(backup_path, "/uboot"))) return print_and_error(NULL, ret); #endif Volume *vol = volume_for_path("/efs"); if (backup_efs == RESTORE_EFS_TAR && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/efs"))) return print_and_error(NULL, ret); } vol = volume_for_path("/misc"); if (backup_misc && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/misc"))) return print_and_error(NULL, ret); } vol = volume_for_path("/modem"); if (backup_modem == RAW_IMG_FILE && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/modem"))) return print_and_error(NULL, ret); } vol = volume_for_path("/radio"); if (backup_radio == RAW_IMG_FILE && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/radio"))) return print_and_error(NULL, ret); } if (backup_system && 0 != (ret = nandroid_restore_partition(backup_path, "/system"))) return print_and_error(NULL, ret); vol = volume_for_path("/preload"); if (backup_preload && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/preload"))) return print_and_error(NULL, ret); } if (backup_data && 0 != (ret = nandroid_restore_partition(backup_path, "/data"))) return print_and_error(NULL, ret); if (has_datadata()) { if (backup_data && 0 != (ret = nandroid_restore_partition(backup_path, "/datadata"))) return print_and_error(NULL, ret); } // handle .android_secure on external and internal storage set_android_secure_path(tmp); if (backup_data && android_secure_ext) { if (0 != (ret = nandroid_restore_partition_extended(backup_path, tmp, 0))) return print_and_error(NULL, ret); } if (backup_cache && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/cache", 0))) return print_and_error(NULL, ret); if (backup_sdext && 0 != (ret = nandroid_restore_partition(backup_path, "/sd-ext"))) return print_and_error(NULL, ret); // handle extra partitions int i; int extra_partitions_num = get_extra_partitions_state(); for (i = 0; i < extra_partitions_num; ++i) { if (extra_partition[i].backup_state && 0 != (ret = nandroid_restore_partition(backup_path, extra_partition[i].mount_point))) return print_and_error(NULL, ret); } finish_nandroid_job(); show_restore_stats(); if (reboot_after_nandroid) reboot_main_system(ANDROID_RB_RESTART, 0, 0); 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(); 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) { #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; }
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 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卡剩余空间: %lluMB\n", sdcard_free_mb); if (sdcard_free_mb < 150) ui_print("可能没有足够的空间完成备份... 继续...\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->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("没有发现 /sdcard/.android_secure. 放弃备份SD卡上安装的程序.\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. 放弃备份sd-ext.\n"); } else { if (0 != ensure_path_mounted("/sd-ext")) ui_print("不能挂载sd-ext. sd-ext备份可能不支持此设备. 放弃备份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; } sync(); ui_set_background(BACKGROUND_ICON_NONE); ui_reset_progress(); ui_print("\n备份完成!\n"); return 0; }