int gen_twrp_md5sum(const char* backup_path) { char md5file[PATH_MAX]; int numFiles = 0; ui_print("\n>> Generating md5 sum...\n"); ensure_path_mounted(backup_path); // this will exclude subfolders! char** files = gather_files(backup_path, "", &numFiles); if (numFiles == 0) { LOGE("No files found in backup path %s\n", backup_path); free_string_array(files); return -1; } int i = 0; for(i = 0; i < numFiles; i++) { ui_quick_reset_and_show_progress(1, 0); ui_print(" - %s\n", BaseName(files[i])); sprintf(md5file, "%s.md5", files[i]); if (write_md5digest(files[i], md5file, 0) < 0) { LOGE("Error while generating md5sum!\n"); ui_reset_progress(); free_string_array(files); return -1; } } ui_print("MD5 sum created.\n"); ui_reset_progress(); free_string_array(files); return 0; }
int gen_nandroid_md5sum(const char* backup_path) { char md5file[PATH_MAX]; char** files; int ret = -1; int numFiles = 0; ui_print("\n>> Generating md5 sum...\n"); ensure_path_mounted(backup_path); // this will exclude subfolders! set_gather_hidden_files(1); files = gather_files(backup_path, "", &numFiles); set_gather_hidden_files(0); if (numFiles == 0) { LOGE("No files found in backup path %s\n", backup_path); goto out; } // create empty md5file, overwrite existing one if we're regenerating the md5 for the backup sprintf(md5file, "%s/nandroid.md5", backup_path); write_string_to_file(md5file, ""); int i = 0; for (i = 0; i < numFiles; i++) { // exclude md5 and log files if (strcmp(BaseName(files[i]), "nandroid.md5") == 0 || strcmp(BaseName(files[i]), "recovery.log") == 0) continue; ui_quick_reset_and_show_progress(1, 0); ui_print(" > %s\n", BaseName(files[i])); if (write_md5digest(files[i], md5file, 1) < 0) goto out; } ret = 0; out: ui_reset_progress(); free_string_array(files); if (ret != 0) LOGE("Error while generating md5 sum!\n"); return ret; }
// check size of archive files to get total backed up data size // find all backup image files of a given partition and increment Backup_Size // Backup_Size is set to 0 at start of nandroid_restore() process so that we do not print size progress on void check_restore_size(const char* backup_file_image, const char* backup_path) { // refresh target partition size if (Get_Size_Via_statfs(backup_path) != 0) { Backup_Size = 0; return; } Before_Used_Size = Used_Size; char tmp[PATH_MAX]; char filename[PATH_MAX]; char** files; int numFiles = 0; sprintf(tmp, "%s/", DirName(backup_file_image)); files = gather_files(tmp, "", &numFiles); // if it's a twrp multi volume backup, ensure we remove trailing 000: strlen("000") = 3 if (strlen(backup_file_image) > strlen("win000") && strcmp(backup_file_image + strlen(backup_file_image) - strlen("win000"), "win000") == 0) snprintf(tmp, strlen(backup_file_image) - 3, "%s", backup_file_image); else strcpy(tmp, backup_file_image); sprintf(filename, "%s", BaseName(tmp)); int i; unsigned long fsize; for(i = 0; i < numFiles; i++) { if (strstr(files[i], filename) != NULL) { fsize = Get_File_Size(files[i]); // check if it is a compressed archive and increase size by 45% // this needs a better implementation to do later if (is_gzip_file(files[i]) > 0) fsize += (fsize * 45) / 100; Backup_Size += fsize; } } free_string_array(files); }
int check_twrp_md5sum(const char* backup_path) { char md5file[PATH_MAX]; char** files; int numFiles = 0; ui_print("\n>> Checking MD5 sums...\n"); ensure_path_mounted(backup_path); files = gather_files(backup_path, "", &numFiles); if (numFiles == 0) { LOGE("No files found in %s\n", backup_path); free_string_array(files); return -1; } int i = 0; for(i = 0; i < numFiles; i++) { // exclude md5 files char *str = strstr(files[i], ".md5"); if (str != NULL && strcmp(str, ".md5") == 0) continue; ui_quick_reset_and_show_progress(1, 0); ui_print(" - %s\n", BaseName(files[i])); sprintf(md5file, "%s.md5", files[i]); if (verify_md5digest(files[i], md5file) != 0) { LOGE("md5sum error!\n"); ui_reset_progress(); free_string_array(files); return -1; } } ui_print("MD5 sum ok.\n"); ui_reset_progress(); free_string_array(files); return 0; }
// pass in NULL for fileExtensionOrDirectory and you will get a directory chooser char* choose_file_menu(const char* directory, const char* fileExtensionOrDirectory, const char* headers[]) { char path[PATH_MAX] = ""; DIR *dir; struct dirent *de; int numFiles = 0; int numDirs = 0; int i; char* return_value = NULL; int dir_len = strlen(directory); i = 0; while (headers[i]) { i++; } const char** fixed_headers = (const char*)malloc((i + 3) * sizeof(char*)); i = 0; while (headers[i]) { fixed_headers[i] = headers[i]; i++; } fixed_headers[i] = directory; fixed_headers[i + 1] = ""; fixed_headers[i + 2 ] = NULL; char** files = gather_files(directory, fileExtensionOrDirectory, &numFiles); char** dirs = NULL; if (fileExtensionOrDirectory != NULL) dirs = gather_files(directory, NULL, &numDirs); int total = numDirs + numFiles; if (total == 0) { ui_print("No files found.\n"); } else { char** list = (char**) malloc((total + 1) * sizeof(char*)); list[total] = NULL; for (i = 0 ; i < numDirs; i++) { list[i] = strdup(dirs[i] + dir_len); } for (i = 0 ; i < numFiles; i++) { list[numDirs + i] = strdup(files[i] + dir_len); } for (;;) { int chosen_item = get_menu_selection(fixed_headers, list, 0, 0); if (chosen_item == GO_BACK) break; static char ret[PATH_MAX]; if (chosen_item < numDirs) { char* subret = choose_file_menu(dirs[chosen_item], fileExtensionOrDirectory, headers); if (subret != NULL) { strcpy(ret, subret); return_value = ret; break; } continue; } strcpy(ret, files[chosen_item - numDirs]); return_value = ret; break; } free_string_array(list); } free_string_array(files); free_string_array(dirs); free(fixed_headers); return return_value; }
int verify_nandroid_md5sum(const char* backup_path) { char* backupfile; char line[PATH_MAX]; char md5file[PATH_MAX]; ui_print("\n>> Checking MD5 sums...\n"); ensure_path_mounted(backup_path); sprintf(md5file, "%s/nandroid.md5", backup_path); FILE *fp = fopen(md5file, "r"); if (fp == NULL) { LOGE("cannot open md5file\n"); return -1; } // unlike original cwm, an empty md5 file will fail check // also, if a file doesn't have and md5sum entry, it will fail while (fgets(line, sizeof(line), fp) != NULL) { backupfile = strstr(line, " "); // skip empty new lines, but non other bad formatted lines if (backupfile == NULL && strcmp(line, "\n") != 0) { fclose(fp); return -1; } // mis-formatted line (backupfile must be at least one char as it includes the two spaces) if (strlen(backupfile) < 3 || strcmp(backupfile, " \n") == 0) { fclose(fp); return -1; } // save the line before we modify it char *md5sum = strdup(line); if (md5sum == NULL) { LOGE("memory error\n"); fclose(fp); return -1; } // remove leading two spaces and end new line backupfile += 2; // 2 == strlen(" ") if (strcmp(backupfile + strlen(backupfile) - 1, "\n") == 0) backupfile[strlen(backupfile) - 1] = '\0'; // create a temporary md5file for each backup file sprintf(md5file, "/tmp/%s.md5", backupfile); write_string_to_file(md5file, md5sum); free(md5sum); } fclose(fp); // verify backup integrity for each backupfile to the md5sum we saved in temporary md5file int i = 0; int numFiles = 0; char** files; set_gather_hidden_files(1); files = gather_files(backup_path, "", &numFiles); set_gather_hidden_files(1); if (numFiles == 0) { free_string_array(files); return -1; } for(i = 0; i < numFiles; i++) { // exclude md5 and log files if (strcmp(BaseName(files[i]), "nandroid.md5") == 0 || strcmp(BaseName(files[i]), "recovery.log") == 0) continue; ui_quick_reset_and_show_progress(1, 0); sprintf(md5file, "/tmp/%s.md5", BaseName(files[i])); ui_print(" > %s\n", BaseName(files[i])); if (verify_md5digest(files[i], md5file) != 0) { free_string_array(files); ui_reset_progress(); return -1; } delete_a_file(md5file); } ui_reset_progress(); free_string_array(files); return 0; }