void TWPartition::Setup_Image(bool Display_Error) { Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1); Backup_Name = Display_Name; if (Fstab_File_System == "emmc") Backup_Method = DD; else if (Fstab_File_System == "mtd" || Fstab_File_System == "bml") Backup_Method = FLASH_UTILS; else LOGI("Unhandled file system '%s' on image '%s'\n", Fstab_File_System.c_str(), Display_Name.c_str()); if (Find_Partition_Size()) { Used = Size; Backup_Size = Size; } else { if (Display_Error) LOGE("Unable to find parition size for '%s'\n", Mount_Point.c_str()); else LOGI("Unable to find parition size for '%s'\n", Mount_Point.c_str()); } }
int check_backup_size(const char* backup_path) { // these are the size stats for backup_path we previously refreshed by calling Get_Size_Via_statfs() int total_mb = (int)(Total_Size / 1048576LLU); int used_mb = (int)(Used_Size / 1048576LLU); int free_mb = (int)(Free_Size / 1048576LLU); int free_percent = free_mb * 100 / total_mb; Before_Used_Size = Used_Size; // save Used_Size to refresh data written stats later Backup_Size = 0; // supported nandroid partitions char* Base_Partitions_List[BASE_PARTITIONS_NUM] = { "/recovery", BOOT_PARTITION_MOUNT_POINT, "/wimax", "/modem", "/radio", "/efs", "/misc", "/system", "/preload", "/data", "/datadata", "/cache", "/sd-ext" }; int items_num = BASE_PARTITIONS_NUM + MAX_EXTRA_NANDROID_PARTITIONS + 1; char* Partitions_List[items_num]; int i; for (i = 0; i < BASE_PARTITIONS_NUM; ++i) { Partitions_List[i] = Base_Partitions_List[i]; } int extra_partitions_num = get_extra_partitions_state(); for (i = 0; i < extra_partitions_num; ++i) { Partitions_List[BASE_PARTITIONS_NUM + i] = extra_partition[i].mount_point; } Partitions_List[BASE_PARTITIONS_NUM + extra_partitions_num] = NULL; int preload_status = 0; if ((is_custom_backup && backup_preload) || (!is_custom_backup && nandroid_add_preload.value)) preload_status = 1; int Base_Partitions_Backup_Status[] = { backup_recovery, backup_boot, backup_wimax, backup_modem, backup_radio, backup_efs, backup_misc, backup_system, preload_status, backup_data, backup_data, backup_cache, backup_sdext, }; LOGI("Checking needed space for backup '%s'\n", backup_path); // calculate needed space for backup // assume recovery and wimax always use a raw backup mode (Is_Image() = 0) char skipped_parts[1024] = ""; int ret = 0; Volume* vol; for (i = 0; Partitions_List[i] != NULL; ++i) { if (i >= BASE_PARTITIONS_NUM) { if (!extra_partition[i - BASE_PARTITIONS_NUM].backup_state) continue; } else if (!Base_Partitions_Backup_Status[i]) { continue; } // size of /data will be calculated later for /data/media devices to subtract sdcard size from it if (strcmp(Partitions_List[i], "/data") == 0 && is_data_media()) continue; // redundant but keep for compatibility: // has_datadata() does a volume_for_path() != NULL check if (strcmp(Partitions_List[i], "/datadata") == 0 && !has_datadata()) continue; vol = volume_for_path(Partitions_List[i]); if (vol == NULL) continue; if (Is_Image(Partitions_List[i]) == 0) { if (Find_Partition_Size(Partitions_List[i]) == 0) { Backup_Size += Total_Size; LOGI("%s backup size (/proc)=%lluMb\n", Partitions_List[i], Total_Size / 1048576LLU); // debug } else { ret++; strcat(skipped_parts, " - "); strcat(skipped_parts, Partitions_List[i]); } } else if (Is_File_System(Partitions_List[i]) == 0) { // Get_Size_Via_statfs() will ensure vol->mount_point != NULL if (0 == ensure_path_mounted(vol->mount_point) && 0 == Get_Size_Via_statfs(vol->mount_point)) { Backup_Size += Used_Size; LOGI("%s backup size (stat)=%lluMb\n", Partitions_List[i], Used_Size / 1048576LLU); // debug } else { ret++; strcat(skipped_parts, " - "); strcat(skipped_parts, Partitions_List[i]); } } else { ret++; strcat(skipped_parts, " - Unknown file system: "); strcat(skipped_parts, Partitions_List[i]); } } // handle special partitions and folders: // handle /data and /data/media partitions size for /data/media devices unsigned long long data_backup_size = 0; unsigned long long data_used_bytes = 0; unsigned long long data_media_size = 0; if (is_data_media() && (backup_data || backup_data_media)) { if (0 == ensure_path_mounted("/data") && 0 == Get_Size_Via_statfs("/data")) { data_media_size = Get_Folder_Size("/data/media"); data_used_bytes = Get_Folder_Size("/data"); data_backup_size = data_used_bytes - data_media_size; LOGI("/data: tot size=%lluMb, free=%lluMb, backup size=%lluMb, used=%lluMb, media=%lluMb\n", Total_Size/1048576LLU, Free_Size/1048576LLU, data_backup_size/1048576LLU, data_used_bytes/1048576LLU, data_media_size/1048576LLU); } else { if (backup_data) { strcat(skipped_parts, " - /data"); ret++; } if (backup_data_media) { strcat(skipped_parts, " - /data/media"); ret++; } } } if (backup_data) Backup_Size += data_backup_size; // check if we are also backing up /data/media // if backup_path is same as /data/media, ignore this as it will not be processed by nandroid_backup_datamedia() if (backup_data_media && !is_data_media_volume_path(backup_path)) { Backup_Size += data_media_size; LOGI("included /data/media size\n"); // debug } // .android_secure size calculation // set_android_secure_path() will mount tmp so no need to remount before calling Get_Folder_Size(tmp) char tmp[PATH_MAX]; set_android_secure_path(tmp); if (backup_data && android_secure_ext) { unsigned long long andsec_size; andsec_size = Get_Folder_Size(tmp); Backup_Size += andsec_size; LOGI("%s backup size=%lluMb\n", tmp, andsec_size / 1048576LLU); // debug } // check if we have the needed space int backup_size_mb = (int)(Backup_Size / 1048576LLU); ui_print("\n>> Free space: %dMb (%d%%)\n", free_mb, free_percent); ui_print(">> Needed space: %dMb\n", backup_size_mb); if (ret) ui_print(">> Unknown partitions size (%d):%s\n", ret, skipped_parts); // dedupe wrapper needs less space than actual backup size (incremental backups) // only check free space in Mb if we use tar or tar.gz as a default format // also, add extra 50 Mb for security measures if (free_percent < 3 || (default_backup_handler != dedupe_compress_wrapper && free_mb < backup_size_mb + 50)) { LOGW("Low space for backup!\n"); if (!ui_is_initialized()) { // do not prompt when it is an "adb shell nandroid backup" command LOGW("\n>>> Backup could fail with I/O error!! <<<\n\n"); } else if (nand_prompt_on_low_space.value && !confirm_selection("Low free space! Continue anyway?", "Yes - Continue Nandroid Job")) return -1; } return 0; }