static void compute_directory_stats(const char* directory) { char tmp[PATH_MAX]; char count_text[100]; // reset file count if we ever return before setting it nandroid_files_count = 0; nandroid_files_total = 0; sprintf(tmp, "find %s | %s wc -l > /tmp/dircount", directory, strcmp(directory, "/data") == 0 && is_data_media() ? "grep -v /data/media |" : ""); __system(tmp); FILE* f = fopen("/tmp/dircount", "r"); if (f == NULL) return; if (fgets(count_text, sizeof(count_text), f) == NULL) { fclose(f); return; } size_t len = strlen(count_text); if (count_text[len - 1] == '\n') count_text[len - 1] = '\0'; fclose(f); nandroid_files_total = atoi(count_text); ui_reset_progress(); ui_show_progress(1, 0); }
/* show_progress <fraction> <duration> * * Use <fraction> of the on-screen progress meter for the next operation, * automatically advancing the meter over <duration> seconds (or more rapidly * if the actual rate of progress can be determined). */ static int cmd_show_progress(const char *name, void *cookie, int argc, const char *argv[]) { UNUSED(cookie); CHECK_WORDS(); if (argc != 2) { LOGE("Command %s requires exactly two arguments\n", name); return 1; } char *end; double fraction = strtod(argv[0], &end); if (end[0] != '\0' || argv[0][0] == '\0' || fraction < 0 || fraction > 1) { LOGE("Command %s: invalid fraction \"%s\"\n", name, argv[0]); return 1; } int duration = strtoul(argv[1], &end, 0); if (end[0] != '\0' || argv[0][0] == '\0') { LOGE("Command %s: invalid duration \"%s\"\n", name, argv[1]); return 1; } // Half of the progress bar is taken by verification, // so everything that happens during installation is scaled. ui_show_progress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), duration); gDidShowProgress = 1; return 0; }
int install_package(const char *root_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_print("Finding update package...\n"); ui_show_indeterminate_progress(); LOGI("Update location: %s\n", root_path); if (ensure_root_path_mounted(root_path) != 0) { LOGE("Can't mount %s\n", root_path); return INSTALL_CORRUPT; } char path[PATH_MAX] = ""; if (translate_root_path(root_path, path, sizeof(path)) == NULL) { LOGE("Bad path %s\n", root_path); return INSTALL_CORRUPT; } ui_print("Opening update package...\n"); LOGI("Update file path: %s\n", path); int numKeys; RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys); if (loadedKeys == NULL) { LOGE("Failed to load keys\n"); return INSTALL_CORRUPT; } LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE); // Give verification half the progress bar... ui_print("Verifying update package...\n"); ui_show_progress( VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); int err; err = verify_file(path, loadedKeys, numKeys); free(loadedKeys); LOGI("verify_file returned %d\n", err); if (err != VERIFY_SUCCESS) { LOGE("signature verification failed\n"); return INSTALL_CORRUPT; } /* Try to open the package. */ ZipArchive zip; err = mzOpenZipArchive(path, &zip); if (err != 0) { LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); return INSTALL_CORRUPT; } /* Verify and install the contents of the package. */ int status = handle_update_package(path, &zip); mzCloseZipArchive(&zip); return status; }
// called only for multi-volume backups to generate stats for progress bar // file list was gathered from mounted partition: no need to mount before stat line static void compute_twrp_backup_stats(int index) { char tmp[PATH_MAX]; char line[PATH_MAX]; struct stat info; int total = 0; sprintf(tmp, "/tmp/list/filelist%03i", index); FILE *fp = fopen(tmp, "rb"); if (fp != NULL) { while (fgets(line, sizeof(line), fp) != NULL) { line[strlen(line) - 1] = '\0'; stat(line, &info); if (S_ISDIR(info.st_mode)) { compute_directory_stats(line); total += nandroid_files_total; } else total += 1; } nandroid_files_total = total; fclose(fp); } else { LOGE("Cannot compute backup stats for %s\n", tmp); LOGE("No progress will be shown during backup\n"); nandroid_files_total = 0; } nandroid_files_count = 0; ui_reset_progress(); ui_show_progress(1, 0); }
/** * get_menu_selection() * */ int get_menu_selection(char** headers, char** items, int menu_only, int initial_selection) { // throw away keys pressed previously, so user doesn't // accidentally trigger menu items. ui_clear_key_queue(); ui_start_menu(headers, items, initial_selection); int selected = initial_selection; int chosen_item = -1; while (chosen_item < 0) { #ifdef BOARD_WITH_CPCAP int level = battery_level(); if (level > 0) { if ((50 * progress_value) != level / 2) { progress_value = level / 100.0; if (level < 20) ui_print("Low battery ! %3d %%\n", level); ui_reset_progress(); ui_show_progress(progress_value, 1); ui_set_progress(1.0); } } #endif int key = ui_wait_key(); int visible = ui_text_visible(); int action = device_handle_key(key, visible); if (action < 0) { switch (action) { case HIGHLIGHT_UP: --selected; selected = ui_menu_select(selected); break; case HIGHLIGHT_DOWN: ++selected; selected = ui_menu_select(selected); break; case SELECT_ITEM: chosen_item = selected; break; case ACTION_CANCEL: chosen_item = GO_BACK; break; case NO_ACTION: break; } } else if (!menu_only) { chosen_item = action; } } ui_end_menu(); return chosen_item; }
static int really_install_package(const char *path) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_print("正在查找升级包...\n"); ui_show_indeterminate_progress(); LOGI("Update location: %s\n", path); if (ensure_path_mounted(path) != 0) { LOGE("Can't mount %s\n", path); return INSTALL_CORRUPT; } ui_print("正在打开升级包...\n"); int err; if (signature_check_enabled) { int numKeys; RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys); if (loadedKeys == NULL) { LOGE("Failed to load keys\n"); return INSTALL_CORRUPT; } LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE); // Give verification half the progress bar... ui_print("正在校验升级包...\n"); ui_show_progress( VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); err = verify_file(path, loadedKeys, numKeys); free(loadedKeys); LOGI("verify_file returned %d\n", err); if (err != VERIFY_SUCCESS) { LOGE("signature verification failed\n"); ui_show_text(1); if (!confirm_selection("Install Untrusted Package?", "确认 - 安装不严格的zip卡刷包")) return INSTALL_CORRUPT; } } /* Try to open the package. */ ZipArchive zip; err = mzOpenZipArchive(path, &zip); if (err != 0) { LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); return INSTALL_CORRUPT; } /* Verify and install the contents of the package. */ ui_print("正在安装更新...\n"); return try_update_binary(path, &zip); }
int install_package(const char *path) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_print("Finding update package...\n"); ui_show_indeterminate_progress(); LOGI("Update location: %s\n", path); if (ensure_path_mounted(path) != 0) { LOGE("Can't mount %s\n", path); return INSTALL_CORRUPT; } int err; ui_print("Opening update package...\n"); if (DataManager_GetIntValue(TW_SIGNED_ZIP_VERIFY_VAR)) { int numKeys; RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys); if (loadedKeys == NULL) { LOGE("Failed to load keys\n"); return INSTALL_CORRUPT; } LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE); // Give verification half the progress bar... ui_print("Verifying update package...\n"); ui_show_progress( VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); err = verify_file(path, loadedKeys, numKeys); free(loadedKeys); LOGI("verify_file returned %d\n", err); if (err != VERIFY_SUCCESS) { LOGE("signature verification failed\n"); return INSTALL_CORRUPT; } } /* Try to open the package. */ ZipArchive zip; err = mzOpenZipArchive(path, &zip); if (err != 0) { LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); return INSTALL_CORRUPT; } /* Verify and install the contents of the package. */ ui_print("Installing update...\n"); return try_update_binary(path, &zip); }
static int lua_ui_show_progress(lua_State *L) { int x, y, w, h; x = lua_tonumber(L, 2); y = lua_tonumber(L, 3); w = lua_tonumber(L, 4); h = lua_tonumber(L, 5); ui_show_progress(x, y, w, h); return 0; }
static void compute_directory_stats(const char* directory) { char tmp[PATH_MAX]; sprintf(tmp, "find %s | %s wc -l > /tmp/dircount", directory, strcmp(directory, "/data") == 0 && is_data_media() ? "grep -v /data/media |" : ""); __system(tmp); char count_text[100]; FILE* f = fopen("/tmp/dircount", "r"); fread(count_text, 1, sizeof(count_text), f); fclose(f); nandroid_files_count = 0; nandroid_files_total = atoi(count_text); ui_reset_progress(); ui_show_progress(1, 0); }
static void compute_directory_stats(const char* directory) { char tmp[PATH_MAX]; sprintf(tmp, "find %s | wc -l > /tmp/dircount", directory); __system(tmp); char count_text[100]; FILE* f = fopen("/tmp/dircount", "r"); fread(count_text, 1, sizeof(count_text), f); fclose(f); yaffs_files_count = 0; yaffs_files_total = atoi(count_text); ui_reset_progress(); ui_show_progress(1, 0); }
static void compute_archive_stats(const char* archive_file) { char tmp[PATH_MAX]; sprintf(tmp, "cat %s* | tar -t | wc -l > /tmp/archivecount", archive_file); LOGE("Computing archive stats for %s\n", basename(archive_file)); __system(tmp); char count_text[100]; FILE* f = fopen("/tmp/archivecount", "r"); fread(count_text, 1, sizeof(count_text), f); fclose(f); nandroid_files_count = 0; nandroid_files_total = atoi(count_text); ui_reset_progress(); ui_show_progress(1, 0); }
static int handle_update_package(const char *path, ZipArchive *zip) { // Give verification half the progress bar... ui_print("Verifying update package...\n"); ui_show_progress( VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); /* if (!verify_jar_signature(zip, keys, numKeys)) { LOGE("Verification failed\n"); return INSTALL_CORRUPT; } */ // Update should take the rest of the progress bar. ui_print("Installing update...\n"); int result = try_update_binary(path, zip); if (result == INSTALL_SUCCESS || result == INSTALL_ERROR) { register_package_root(NULL, NULL); // Unregister package root return result; } // if INSTALL_CORRUPT is returned, this package doesn't have an // update binary. Fall back to the older mechanism of looking for // an update script. const ZipEntry *script_entry; script_entry = find_update_script(zip); if (script_entry == NULL) { LOGE("Can't find update script\n"); return INSTALL_CORRUPT; } if (register_package_root(zip, path) < 0) { LOGE("Can't register package root\n"); return INSTALL_ERROR; } int ret = handle_update_script(zip, script_entry); register_package_root(NULL, NULL); // Unregister package root return ret; }
// If the package contains an update binary, extract it and run it. static int try_update_binary(const char *path, ZipArchive *zip) { int custom_binary = 0; const ZipEntry* or_script_entry = mzFindZipEntry(zip, ASSUMED_OR_UPDATE_SCRIPT_NAME); if (or_script_entry != NULL) { ui_print("使用shell脚本...\n"); return handle_or_update(path, zip); } const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME); if (binary_entry == NULL) ui_print("使用默认的updater...\n"); else custom_binary = 1; char* binary = "/tmp/update_binary"; unlink(binary); if (custom_binary) { int fd = creat(binary, 0755); if (fd < 0) { LOGE("无法制作%s\n", binary); return 1; } bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd); close(fd); if (!ok) { LOGE("无法复制%s\n", ASSUMED_UPDATE_BINARY_NAME); return 1; } } else binary = DEFAULT_UPDATE_BINARY_NAME; ui_show_indeterminate_progress(); int pipefd[2]; pipe(pipefd); // When executing the update binary contained in the package, the // arguments passed are: // // - the version number for this interface // // - an fd to which the program can write in order to update the // progress bar. The program can write single-line commands: // // progress <frac> <secs> // fill up the next <frac> part of of the progress bar // over <secs> seconds. If <secs> is zero, use // set_progress commands to manually control the // progress of this segment of the bar // // set_progress <frac> // <frac> should be between 0.0 and 1.0; sets the // progress bar within the segment defined by the most // recent progress command. // // firmware <"hboot"|"radio"> <filename> // arrange to install the contents of <filename> in the // given partition on reboot. (API v2: <filename> may // start with "PACKAGE:" to indicate taking a file from // the OTA package.) // // ui_print <string> // display <string> on the screen. // // stasis // quit the gui // - the name of the package zip file. // char** args = malloc(sizeof(char*) * 5); args[0] = binary; args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk args[2] = malloc(10); sprintf(args[2], "%d", pipefd[1]); args[3] = (char*)path; args[4] = NULL; pid_t pid = fork(); if (pid == 0) { close(pipefd[0]); execv(binary, args); fprintf(stderr, "E:无法运行%s (%s)\n", binary, strerror(errno)); _exit(-1); } close(pipefd[1]); char* firmware_type = NULL; char* firmware_filename = NULL; char buffer[1024]; FILE* from_child = fdopen(pipefd[0], "r"); ui_set_progress(0.0); while (fgets(buffer, sizeof(buffer), from_child) != NULL) { char* command = strtok(buffer, " \n"); if (command == NULL) continue; else if (strcmp(command, "progress") == 0) { char* fraction_s = strtok(NULL, " \n"); char* seconds_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); int seconds = strtol(seconds_s, NULL, 10); ui_show_progress(fraction, seconds); } else if (strcmp(command, "set_progress") == 0) { char* fraction_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); ui_set_progress(fraction); } else if (strcmp(command, "firmware") == 0) { char* type = strtok(NULL, " \n"); char* filename = strtok(NULL, " \n"); if (type != NULL && filename != NULL) { if (firmware_type != NULL) LOGE("忽略试图进行多个固件更新"); else { firmware_type = strdup(type); firmware_filename = strdup(filename); } } } else if (strcmp(command, "ui_print") == 0) { char* str = strtok(NULL, "\n"); if (str) ui_print(str); else ui_print("\n"); } else LOGE("未知命令[%s]\n", command); } fclose(from_child); int status; waitpid(pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGE("错误!代码%s\n(Status %d)\n", path, WEXITSTATUS(status)); return INSTALL_ERROR; } if (firmware_type != NULL) return handle_firmware_update(firmware_type, firmware_filename, zip); else return INSTALL_SUCCESS; }
int install_package(const char *root_path) { recovery_status = 0; int status = INSTALL_SUCCESS; ui_set_background(BACKGROUND_ICON_INSTALLING); ui_print("Finding update package...\n"); ui_show_indeterminate_progress(); if (ensure_root_path_mounted(root_path) != 0) { ui_print("Can't mount %s\n", root_path); status = INSTALL_CORRUPT; goto exit; } char path[PATH_MAX] = ""; if (translate_root_path(root_path, path, sizeof(path)) == NULL) { ui_print("Bad path %s\n", root_path); status = INSTALL_CORRUPT; goto exit; } printf("package name = '%s'\t path_len= %d\n",path,strlen(path)); ui_print("Opening update package...\n"); #if 0 int numKeys; RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys); if (loadedKeys == NULL) { LOGE("Failed to load keys\n"); return INSTALL_CORRUPT; } LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE); // Give verification half the progress bar... ui_print("Verifying update package...\n"); ui_show_progress( VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); int err; err = verify_file(path, loadedKeys, numKeys); free(loadedKeys); LOGI("verify_file returned %d\n", err); if (err != VERIFY_SUCCESS) { LOGE("signature verification failed\n"); return INSTALL_CORRUPT; } #endif /* Try to open the package. */ int err; ZipArchive zip; err = mzOpenZipArchive(path, &zip); if (err != 0) { ui_print("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); status = INSTALL_CORRUPT; goto exit; } /* * Verify hw version */ /* if (check_hw_version(&zip)) { ui_print("HW version doesn't match!!!"); status = INSTALL_CORRUPT; mzCloseZipArchive(&zip); goto exit; } */ /* Verify and install the contents of the package. */ ui_print("start update package file\n"); status = handle_update_package(path, &zip); ui_print("install_success!!!\n"); mzCloseZipArchive(&zip); exit: ensure_root_path_unmounted(root_path); if (status != INSTALL_SUCCESS) recovery_status = 1; else recovery_status = 0; return status; }
// If the package contains an update binary, extract it and run it. static int try_update_binary(const char *path, ZipArchive *zip) { const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME); if (binary_entry == NULL) { const ZipEntry* update_script_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_SCRIPT_NAME); if (update_script_entry != NULL) { ui_print("Amend 脚本 (update-script) 已不支持.\n"); ui_print("Amend 脚本在 Android 1.5 后不再支持.\n"); ui_print("请将升级包脚本升级到Edify脚本(updater-script 和 update-binary).\n"); ui_print("安装已取消.\n"); return INSTALL_UPDATE_BINARY_MISSING; } mzCloseZipArchive(zip); return INSTALL_UPDATE_BINARY_MISSING; } char* binary = "/tmp/update_binary"; unlink(binary); int fd = creat(binary, 0755); if (fd < 0) { mzCloseZipArchive(zip); LOGE("Can't make %s\n", binary); return 1; } bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd); close(fd); if (!ok) { LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME); mzCloseZipArchive(zip); return 1; } int pipefd[2]; pipe(pipefd); // When executing the update binary contained in the package, the // arguments passed are: // // - the version number for this interface // // - an fd to which the program can write in order to update the // progress bar. The program can write single-line commands: // // progress <frac> <secs> // fill up the next <frac> part of of the progress bar // over <secs> seconds. If <secs> is zero, use // set_progress commands to manually control the // progress of this segment of the bar // // set_progress <frac> // <frac> should be between 0.0 and 1.0; sets the // progress bar within the segment defined by the most // recent progress command. // // firmware <"hboot"|"radio"> <filename> // arrange to install the contents of <filename> in the // given partition on reboot. // // (API v2: <filename> may start with "PACKAGE:" to // indicate taking a file from the OTA package.) // // (API v3: this command no longer exists.) // // ui_print <string> // display <string> on the screen. // // - the name of the package zip file. // char** args = malloc(sizeof(char*) * 5); args[0] = binary; args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk args[2] = malloc(10); sprintf(args[2], "%d", pipefd[1]); args[3] = (char*)path; args[4] = NULL; pid_t pid = fork(); if (pid == 0) { setenv("UPDATE_PACKAGE", path, 1); close(pipefd[0]); execv(binary, args); fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno)); _exit(-1); } close(pipefd[1]); char* firmware_type = NULL; char* firmware_filename = NULL; char buffer[1024]; FILE* from_child = fdopen(pipefd[0], "r"); while (fgets(buffer, sizeof(buffer), from_child) != NULL) { char* command = strtok(buffer, " \n"); if (command == NULL) { continue; } else if (strcmp(command, "progress") == 0) { char* fraction_s = strtok(NULL, " \n"); char* seconds_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); int seconds = strtol(seconds_s, NULL, 10); ui_show_progress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds); } else if (strcmp(command, "set_progress") == 0) { char* fraction_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); ui_set_progress(fraction); } else if (strcmp(command, "firmware") == 0) { char* type = strtok(NULL, " \n"); char* filename = strtok(NULL, " \n"); if (type != NULL && filename != NULL) { if (firmware_type != NULL) { LOGE("ignoring attempt to do multiple firmware updates"); } else { firmware_type = strdup(type); firmware_filename = strdup(filename); } } } else if (strcmp(command, "ui_print") == 0) { char* str = strtok(NULL, "\n"); if (str) { ui_print("%s", str); } else { ui_print("\n"); } } else { LOGE("unknown command [%s]\n", command); } } fclose(from_child); int status; waitpid(pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status)); mzCloseZipArchive(zip); return INSTALL_ERROR; } if (firmware_type != NULL) { int ret = handle_firmware_update(firmware_type, firmware_filename, zip); mzCloseZipArchive(zip); return ret; } return INSTALL_SUCCESS; }
/* write_raw_image <src-image> <dest-root> */ static int cmd_write_raw_image(const char *name, void *cookie, int argc, const char *argv[]) { UNUSED(cookie); CHECK_WORDS(); if (argc != 2) { LOGE("Command %s requires exactly two arguments\n", name); return 1; } // Use 10% of the progress bar (20% post-verification) by default const char *src_root_path = argv[0]; const char *dst_root_path = argv[1]; ui_print("Writing %s...\n", dst_root_path); if (!gDidShowProgress) ui_show_progress(DEFAULT_IMAGE_PROGRESS_FRACTION, 0); /* Find the source image, which is probably in a package. */ if (!is_package_root_path(src_root_path)) { LOGE("Command %s: non-package source path \"%s\" not yet supported\n", name, src_root_path); return 255; } /* Get the package. */ char srcpathbuf[PATH_MAX]; const char *src_path; const ZipArchive *package; src_path = translate_package_root_path(src_root_path, srcpathbuf, sizeof(srcpathbuf), &package); if (src_path == NULL) { LOGE("Command %s: bad source path \"%s\"\n", name, src_root_path); return 1; } /* Get the entry. */ const ZipEntry *entry = mzFindZipEntry(package, src_path); if (entry == NULL) { LOGE("Missing file %s\n", src_path); return 1; } /* Unmount the destination root if it isn't already. */ int ret = ensure_root_path_unmounted(dst_root_path); if (ret < 0) { LOGE("Can't unmount %s\n", dst_root_path); return 1; } /* Open the partition for writing. */ const MtdPartition *partition = get_root_mtd_partition(dst_root_path); if (partition == NULL) { LOGE("Can't find %s\n", dst_root_path); return 1; } MtdWriteContext *context = mtd_write_partition(partition); if (context == NULL) { LOGE("Can't open %s\n", dst_root_path); return 1; } /* Extract and write the image. */ bool ok = mzProcessZipEntryContents(package, entry, write_raw_image_process_fn, context); if (!ok) { LOGE("Error writing %s\n", dst_root_path); mtd_write_close(context); return 1; } if (mtd_erase_blocks(context, -1) == (off_t) -1) { LOGE("Error finishing %s\n", dst_root_path); mtd_write_close(context); return -1; } if (mtd_write_close(context)) { LOGE("Error closing %s\n", dst_root_path); return -1; } return 0; }
/* copy_dir <src-dir> <dst-dir> [<timestamp>] * * The contents of <src-dir> will become the contents of <dst-dir>. * The original contents of <dst-dir> are preserved unless something * in <src-dir> overwrote them. * * e.g., for "copy_dir PKG:system SYSTEM:", the file "PKG:system/a" * would be copied to "SYSTEM:a". * * The specified timestamp (in decimal seconds since 1970) will be used, * or a fixed default timestamp will be supplied otherwise. */ static int cmd_copy_dir(const char *name, void *cookie, int argc, const char *argv[]) { UNUSED(name); UNUSED(cookie); CHECK_WORDS(); // To create a consistent system image, never use the clock for timestamps. struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default if (argc == 3) { char *end; time_t value = strtoul(argv[2], &end, 0); if (value == 0 || end[0] != '\0') { LOGE("Command %s: invalid timestamp \"%s\"\n", name, argv[2]); return 1; } else if (value < timestamp.modtime) { LOGE("Command %s: timestamp \"%s\" too early\n", name, argv[2]); return 1; } timestamp.modtime = timestamp.actime = value; } else if (argc != 2) { LOGE("Command %s requires exactly two arguments\n", name); return 1; } // Use 40% of the progress bar (80% post-verification) by default ui_print("Copying files...\n"); if (!gDidShowProgress) ui_show_progress(DEFAULT_FILES_PROGRESS_FRACTION, 0); /* Mount the destination volume if it isn't already. */ const char *dst_root_path = argv[1]; int ret = ensure_root_path_mounted(dst_root_path); if (ret < 0) { LOGE("Can't mount %s\n", dst_root_path); return 1; } /* Get the real target path. */ char dstpathbuf[PATH_MAX]; const char *dst_path; dst_path = translate_root_path(dst_root_path, dstpathbuf, sizeof(dstpathbuf)); if (dst_path == NULL) { LOGE("Command %s: bad destination path \"%s\"\n", name, dst_root_path); return 1; } /* Try to copy the directory. The source may be inside a package. */ const char *src_root_path = argv[0]; char srcpathbuf[PATH_MAX]; const char *src_path; if (is_package_root_path(src_root_path)) { const ZipArchive *package; src_path = translate_package_root_path(src_root_path, srcpathbuf, sizeof(srcpathbuf), &package); if (src_path == NULL) { LOGE("Command %s: bad source path \"%s\"\n", name, src_root_path); return 1; } /* Extract the files. Set MZ_EXTRACT_FILES_ONLY, because only files * are validated by the signature. Do a dry run first to count how * many there are (and find some errors early). */ ExtractContext ctx; ctx.num_done = 0; ctx.num_total = 0; if (!mzExtractRecursive(package, src_path, dst_path, MZ_EXTRACT_FILES_ONLY | MZ_EXTRACT_DRY_RUN, ×tamp, extract_count_cb, (void *) &ctx) || !mzExtractRecursive(package, src_path, dst_path, MZ_EXTRACT_FILES_ONLY, ×tamp, extract_cb, (void *) &ctx)) { LOGW("Command %s: couldn't extract \"%s\" to \"%s\"\n", name, src_root_path, dst_root_path); return 1; } } else { LOGE("Command %s: non-package source path \"%s\" not yet supported\n", name, src_root_path); //xxx mount the src volume //xxx return 255; } return 0; }
int phx_do_backup(const char* enableVar, struct dInfo* mnt, const char* image_dir, unsigned long long img_bytes, unsigned long long file_bytes, unsigned long long* img_bytes_remaining, unsigned long long* file_bytes_remaining, unsigned long* img_byte_time, unsigned long* file_byte_time) { // Check if this partition is being backed up... if (!DataManager_GetIntValue(enableVar)) return 0; // Let's calculate the percentage of the bar this section is expected to take unsigned long int img_bps = DataManager_GetIntValue(VAR_BACKUP_AVG_IMG_RATE); unsigned long int file_bps; if (DataManager_GetIntValue(VAR_USE_COMPRESSION_VAR)) file_bps = DataManager_GetIntValue(VAR_BACKUP_AVG_FILE_COMP_RATE); else file_bps = DataManager_GetIntValue(VAR_BACKUP_AVG_FILE_RATE); if (DataManager_GetIntValue(VAR_SKIP_MD5_GENERATE_VAR) == 1) { // If we're skipping MD5 generation, our BPS is faster by about 1.65 file_bps = (unsigned long) (file_bps * 1.65); img_bps = (unsigned long) (img_bps * 1.65); } // We know the speed for both, how far into the whole backup are we, based on time unsigned long total_time = (img_bytes / img_bps) + (file_bytes / file_bps); unsigned long remain_time = (*img_bytes_remaining / img_bps) + (*file_bytes_remaining / file_bps); float pos = (total_time - remain_time) / (float) total_time; ui_set_progress(pos); LOGI("Estimated Total time: %lu Estimated remaining time: %lu\n", total_time, remain_time); // Determine how much we're about to process unsigned long long blocksize = get_backup_size(mnt); // And get the time unsigned long section_time; if (mnt->backup == image) section_time = blocksize / img_bps; else section_time = blocksize / file_bps; // Set the position pos = section_time / (float) total_time; ui_show_progress(pos, section_time); time_t start, stop; time(&start); if (phx_backup(*mnt, image_dir) == 1) { // did the backup process return an error ? 0 = no error SetDataState("Backup failed", mnt->mnt, 1, 1); ui_print("-- Error occured, check recovery.log. Aborting.\n"); //oh noes! abort abort! return 1; } time(&stop); LOGI("Partition Backup time: %d\n", (int) difftime(stop, start)); // Now, decrement out byte counts if (mnt->backup == image) { *img_bytes_remaining -= blocksize; *img_byte_time += (int) difftime(stop, start); } else { *file_bytes_remaining -= blocksize; *file_byte_time += (int) difftime(stop, start); } return 0; }
int tw_restore(struct dInfo rMnt, char *rDir) { int i; FILE *reFp; char rUppr[20]; char rMount[30]; char rFilesystem[10]; char rFilename[255]; char rCommand[255]; char rOutput[255]; time_t rStart, rStop; strcpy(rUppr,rMnt.mnt); for (i = 0; i < strlen(rUppr); i++) { rUppr[i] = toupper(rUppr[i]); } ui_print("[%s]\n",rUppr); ui_show_progress(1,150); time(&rStart); ui_print("...Verifying md5 hash for %s.\n",rMnt.mnt); if(checkMD5(rDir,rMnt.fnm) == 0) // verify md5, check if no error; 0 = no error. { strcpy(rFilename,rDir); strcat(rFilename,rMnt.fnm); sprintf(rCommand,"ls -l %s | awk -F'.' '{ print $2 }'",rFilename); // let's get the filesystem type from filename reFp = __popen(rCommand, "r"); LOGI("=> Filename is: %s\n",rMnt.fnm); while (fscanf(reFp,"%s",rFilesystem) == 1) { // if we get a match, store filesystem type LOGI("=> Filesystem is: %s\n",rFilesystem); // show it off to the world! } __pclose(reFp); if (DataManager_GetIntValue(TW_RM_RF_VAR) == 1 && (strcmp(rMnt.mnt,"system") == 0 || strcmp(rMnt.mnt,"data") == 0 || strcmp(rMnt.mnt,"cache") == 0)) { // we'll use rm -rf instead of formatting for system, data and cache if the option is set ui_print("...using rm -rf to wipe %s\n", rMnt.mnt); tw_mount(rMnt); // mount the partition first sprintf(rCommand,"rm -rf %s%s/*", "/", rMnt.mnt); LOGI("rm rf commad: %s\n", rCommand); reFp = __popen(rCommand, "r"); while (fscanf(reFp,"%s",rOutput) == 1) { ui_print_overwrite("%s",rOutput); } __pclose(reFp); } else { ui_print("...Formatting %s\n",rMnt.mnt); tw_format(rFilesystem,rMnt.blk); // let's format block, based on filesystem from filename above } ui_print("....Done.\n"); if (strcmp(rFilesystem,"mtd") == 0) { // if filesystem is mtd, we use flash image sprintf(rCommand,"flash_image %s %s",rMnt.mnt,rFilename); strcpy(rMount,rMnt.mnt); } else if (strcmp(rFilesystem,"emmc") == 0) { // if filesystem is emmc, we use dd sprintf(rCommand,"dd bs=%s if=%s of=%s",bs_size,rFilename,rMnt.dev); strcpy(rMount,rMnt.mnt); } else { tw_mount(rMnt); strcpy(rMount,"/"); if (strcmp(rMnt.mnt,".android_secure") == 0) { // if it's android_secure, we have add prefix strcat(rMount,"sdcard/"); } strcat(rMount,rMnt.mnt); sprintf(rCommand,"cd %s && tar -xvf %s",rMount,rFilename); // formulate shell command to restore } ui_print("...Restoring %s\n",rMount); reFp = __popen(rCommand, "r"); if(DataManager_GetIntValue(TW_SHOW_SPAM_VAR) == 2) { // twrp spam while (fgets(rOutput,sizeof(rOutput),reFp) != NULL) { ui_print_overwrite("%s",rOutput); } } else { while (fscanf(reFp,"%s",rOutput) == 1) { if(DataManager_GetIntValue(TW_SHOW_SPAM_VAR) == 1) ui_print_overwrite("%s",rOutput); } } __pclose(reFp); ui_print_overwrite("....Done.\n"); if (strcmp(rMnt.mnt,".android_secure") != 0) { // any partition other than android secure, tw_unmount(rMnt); // let's unmount (unmountable partitions won't matter) } } else { ui_print("...Failed md5 check. Aborted.\n\n"); return 1; } ui_reset_progress(); time(&rStop); output_time(rUppr, "DONE", (int)difftime(rStop,rStart)); return 0; }
int convert_mtd_device(const char *root, const char* fs_list) { static char* headers[] = { "Converting Menu", "", NULL, NULL }; static char* confirm_convert = "Confirm convert?"; static char* confirm = "Yes - Convert"; const char* root_fs = get_type_internal_fs(root); headers[2] = root; typedef char* string; string tfs[NUM_FILESYSTEMS] = { "rfs", "ext4" }; static string options[NUM_FILESYSTEMS*2 + 1 + 1]; int sel_fs[NUM_FILESYSTEMS*2 + 1 + 1]; int i,j=0; // with backup for (i=0; i<NUM_FILESYSTEMS; i++) { if (fs_list[i] == '*') { if (strcmp(tfs[i], root_fs)) { sel_fs[j] = i; options[j] = (string)malloc(32); sprintf(options[j++], "to %s with backup", tfs[i]); } } else break; } options[j++] = ""; // without backup for (i=0; i<NUM_FILESYSTEMS; i++) { if (fs_list[i] == '*') { if (strcmp(tfs[i], root_fs)) { sel_fs[j] = i; options[j] = (string)malloc(32); sprintf(options[j++], "to %s through format", tfs[i]); } } else break; } options[j] = NULL; int chosen_item = get_menu_selection(headers, options, 0); if (chosen_item == GO_BACK) return 1; if (chosen_item < i) { // with backup if (!confirm_selection(confirm_convert, confirm)) return 1; ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); // mount $root if (0 != ensure_root_path_mounted(root)) { ui_print("Can't mount %s for backup\n", root); return -1; } // check size of $root struct statfs stat_root; if (0 != statfs(get_mount_point_for_root(root), &stat_root)) { ui_print("Can't get size of %s\n", root); return -1; } // mount SDCARD if (0 != ensure_root_path_mounted("SDCARD:")) { ui_print("Can't mount sdcard for backup\n", root); return -1; } // check size SD struct statfs stat_sd; if (0 != statfs(get_mount_point_for_root("SDCARD:"), &stat_sd)) { ui_print("Can't get size of sdcard\n"); return -1; } uint64_t root_fsize = (uint64_t)(stat_root.f_blocks-stat_root.f_bfree)*(uint64_t)stat_root.f_bsize; uint64_t sd_free_size = (uint64_t)stat_sd.f_bfree*(uint64_t)stat_sd.f_bsize; ui_print("SD free: %lluMB / need: %lluMB\n", sd_free_size/(1024*1024), root_fsize/(1024*1024)); if (root_fsize > sd_free_size) { ui_print("Can't backup need: %lluMB on SD\n", root_fsize/(1024*1024)); return -1; } // create folder for backup [/sdcard/ebrecovery/tmp] [mkdir -p /sdcard/ebrecovery/tmp] if (0 != __system("mkdir -p /sdcard/ebrecovery/tmp")) { ui_print("Can't create tmp folder for backup\n"); return -1; } ui_show_progress(0.3, root_fsize*30/(140*1024*1024)); // backup ui_print("Backuping %s...\n", root); char br_exec[256]; sprintf(br_exec, "tar -c --exclude=*RFS_LOG.LO* -f /sdcard/ebrecovery/tmp/ctmp.tar %s", get_mount_point_for_root(root)+1); if (0 != __system(br_exec)) { ui_print("Can't create backup file\n"); return -1; } // check size of backup file > sizeof($root)? // set new FS ui_print("Change fs type %s -> %s\n", get_type_internal_fs(root), tfs[sel_fs[chosen_item]]); if (0 != set_type_internal_fs(root, tfs[sel_fs[chosen_item]])) { ui_print("Error change type of file system to %s for %s\n", tfs[sel_fs[chosen_item]], root); return -1; } // format $root ui_show_progress(0.05, 10); ui_print("Formatting %s...\n", root); if (0 != format_root_device(root)) { ui_print("Error format %s\n", root); return -1; } // mount $root if (0 != ensure_root_path_mounted(root)) { ui_print("Can't mount %s for backup\n", root); return -1; } // restore $root ui_show_progress(0.65, root_fsize*500/(140*1024*1024)); ui_print("Restoring %s...\n", root); if (0 != __system("tar -x -f /sdcard/ebrecovery/tmp/ctmp.tar")) { ui_print("Can't restore backup file\n"); return -1; } // check size of $root ? // delete temp backup files (delete tmp folder) ui_show_indeterminate_progress(); if (0 != __system("rm /sdcard/ebrecovery/tmp/ctmp.tar")) { ui_print("Can't remove backup file\n"); return -1; } return 0; } else { // without if (!confirm_selection(confirm_convert, confirm)) return 1; // change file system to new ui_print("Change fs type %s -> %s\n", get_type_internal_fs(root), tfs[sel_fs[chosen_item]]); if (0 != set_type_internal_fs(root, tfs[sel_fs[chosen_item]])) { ui_print("Error change type of file system to %s for %s\n", tfs[sel_fs[chosen_item]], root); return -1; } // format ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); ui_print("Formatting %s...\n", root); return format_root_device(root); } return -1; }
int nandroid_rest_exe() { SetDataState("", "", 0, 0); const char* nan_dir = DataManager_GetStrValue("phx_restore"); if (ensure_path_mounted(SDCARD_ROOT) != 0) { ui_print("-- Could not mount: %s.\n-- Aborting.\n",SDCARD_ROOT); return 1; } int total = 0; total += (DataManager_GetIntValue(VAR_RESTORE_SYSTEM_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_DATA_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_CACHE_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_RECOVERY_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_SP1_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_SP2_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_SP3_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_BOOT_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_ANDSEC_VAR) == 1 ? 1 : 0); total += (DataManager_GetIntValue(VAR_RESTORE_SDEXT_VAR) == 1 ? 1 : 0); float sections = 1.0 / total; time_t rStart, rStop; time(&rStart); ui_print("\n[RESTORE STARTED]\n\n"); if (DataManager_GetIntValue(VAR_RESTORE_SYSTEM_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(sys,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_DATA_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(dat,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_BOOT_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(boo,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_RECOVERY_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(rec,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_CACHE_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(cac,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_SP1_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(sp1,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_SP2_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(sp2,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_SP3_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(sp3,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_ANDSEC_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(ase,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } if (DataManager_GetIntValue(VAR_RESTORE_SDEXT_VAR) == 1) { ui_show_progress(sections, 150); if (phx_restore(sde,nan_dir) == 1) { ui_print("-- Error occured, check recovery.log. Aborting.\n"); SetDataState("Restore failed", "", 1, 1); return 1; } } time(&rStop); ui_print("[RESTORE COMPLETED IN %d SECONDS]\n\n",(int)difftime(rStop,rStart)); __system("sync"); LOGI("=> Let's update filesystem types.\n"); verifyFst(); LOGI("=> And update our fstab also.\n"); createFstab(); SetDataState("Restore Succeeded", "", 0, 1); return 0; }
/* New backup function ** Condensed all partitions into one function */ int tw_backup(struct dInfo bMnt, char *bDir) { if (ensure_path_mounted(SDCARD_ROOT) != 0) { ui_print("-- Could not mount: %s.\n-- Aborting.\n",SDCARD_ROOT); return 1; } int bDiv; char bTarArg[10]; if (DataManager_GetIntValue(TW_USE_COMPRESSION_VAR)) { // set compression or not strcpy(bTarArg,"-czvf"); bDiv = 512; } else { strcpy(bTarArg,"-cvf"); bDiv = 2048; } FILE *bFp; int bPartSize; char *bImage = malloc(sizeof(char)*50); char *bMount = malloc(sizeof(char)*50); char *bCommand = malloc(sizeof(char)*255); if (strcmp(bMnt.mnt,"system") == 0 || strcmp(bMnt.mnt,"data") == 0 || strcmp(bMnt.mnt,"cache") == 0 || strcmp(bMnt.mnt,"sd-ext") == 0 || strcmp(bMnt.mnt,"efs") == 0 || strcmp(bMnt.mnt,".android_secure") == 0) { // detect mountable partitions if (strcmp(bMnt.mnt,".android_secure") == 0) { // if it's android secure, add sdcard to prefix strcpy(bMount,"/sdcard/"); strcat(bMount,bMnt.mnt); sprintf(bImage,"and-sec.%s.win",bMnt.fst); // set image name based on filesystem, should always be vfat for android_secure } else { strcpy(bMount,"/"); strcat(bMount,bMnt.mnt); sprintf(bImage,"%s.%s.win",bMnt.mnt,bMnt.fst); // anything else that is mountable, will be partition.filesystem.win ui_print("\n-- Mounting %s, please wait...\n",bMount); if (tw_mount(bMnt)) { ui_print("-- Could not mount: %s\n-- Aborting.\n",bMount); free(bCommand); free(bMount); free(bImage); return 1; } ui_print("-- Done.\n\n",bMount); } sprintf(bCommand,"du -sk %s | awk '{ print $1 }'",bMount); // check for partition/folder size bFp = __popen(bCommand, "r"); fscanf(bFp,"%d",&bPartSize); __pclose(bFp); sprintf(bCommand,"cd %s && tar %s %s%s ./*",bMount,bTarArg,bDir,bImage); // form backup command } else { strcpy(bMount,bMnt.mnt); bPartSize = bMnt.sze / 1024; sprintf(bImage,"%s.%s.win",bMnt.mnt,bMnt.fst); // non-mountable partitions such as boot/wimax/recovery if (strcmp(bMnt.fst,"mtd") == 0) { sprintf(bCommand,"dump_image %s %s%s",bMnt.mnt,bDir,bImage); // if it's mtd, we use dump image } else if (strcmp(bMnt.fst,"emmc") == 0) { sprintf(bCommand,"dd bs=%s if=%s of=%s%s",bs_size,bMnt.blk,bDir,bImage); // if it's emmc, use dd } ui_print("\n"); } LOGI("=> Filename: %s\n",bImage); LOGI("=> Size of %s is %d KB.\n\n",bMount,bPartSize); int i; char bUppr[20]; strcpy(bUppr,bMnt.mnt); for (i = 0; i < strlen(bUppr); i++) { // make uppercase of mount name bUppr[i] = toupper(bUppr[i]); } ui_print("[%s (%d MB)]\n",bUppr,bPartSize/1024); // show size in MB int bProgTime; time_t bStart, bStop; char bOutput[512]; if (sdSpace > bPartSize) { // Do we have enough space on sdcard? time(&bStart); // start timer bProgTime = bPartSize / bDiv; // not very accurate but better than nothing progress time for progress bar ui_show_progress(1,bProgTime); ui_print("...Backing up %s partition.\n",bMount); bFp = __popen(bCommand, "r"); // sending backup command formed earlier above if(DataManager_GetIntValue(TW_SHOW_SPAM_VAR) == 2) { // if twrp spam is on, show all lines while (fgets(bOutput,sizeof(bOutput),bFp) != NULL) { ui_print_overwrite("%s",bOutput); } } else { // else just show single line while (fscanf(bFp,"%s",bOutput) == 1) { if(DataManager_GetIntValue(TW_SHOW_SPAM_VAR) == 1) ui_print_overwrite("%s",bOutput); } } ui_print_overwrite("....Done.\n"); __pclose(bFp); int pFileSize; ui_print("...Double checking backup file size.\n"); sprintf(bCommand,"ls -l %s%s | awk '{ print $5 }'",bDir,bImage); // double checking to make sure we backed up something bFp = __popen(bCommand, "r"); fscanf(bFp,"%d",&pFileSize); __pclose(bFp); ui_print("....File size: %d bytes.\n",pFileSize); // file size if (pFileSize > 0) { // larger than 0 bytes? if (strcmp(bMnt.fst,"mtd") == 0 || strcmp(bMnt.fst,"emmc") == 0) { // if it's an unmountable partition, we can make sure LOGI("=> Expected size: %d Got: %d\n",bMnt.sze,pFileSize); // partition size matches file image size (they should match!) if (pFileSize != bMnt.sze) { ui_print("....File size is incorrect. Aborting...\n\n"); // they dont :( free(bCommand); free(bMount); free(bImage); return 1; } else { ui_print("....File size matches partition size.\n"); // they do, yay! } } ui_print("...Generating %s md5...\n", bMnt.mnt); makeMD5(bDir,bImage); // make md5 file ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", bMnt.mnt); checkMD5(bDir,bImage); // test the md5 we just made, just in case ui_print("....Done.\n"); time(&bStop); // stop timer ui_reset_progress(); // stop progress bar output_time(bUppr, "DONE", (int)difftime(bStop,bStart)); tw_unmount(bMnt); // unmount partition we just restored to (if it's not a mountable partition, it will just bypass) sdSpace -= bPartSize; // minus from sd space number (not accurate but, it's more than the real count so it will suffice) } else { ui_print("...File size is zero bytes. Aborting...\n\n"); // oh noes! file size is 0, abort! abort! tw_unmount(bMnt); free(bCommand); free(bMount); free(bImage); return 1; } } else { ui_print("...Not enough space on /sdcard. Aborting.\n"); // oh noes! no space left on sdcard, abort! abort! tw_unmount(bMnt); free(bCommand); free(bMount); free(bImage); return 1; } free(bCommand); free(bMount); free(bImage); return 0; }
int runve(char* filename, char** argv, char** envp, int secs) { int opipe[2]; int ipipe[2]; pipe(opipe); pipe(ipipe); pid_t pid = fork(); int status = 0; if (pid == 0) { dup2(opipe[1],1); dup2(ipipe[0],0); close(opipe[0]); close(ipipe[1]); execve(filename,argv,envp); char* error_msg = calloc(strlen(filename)+20,sizeof(char)); sprintf(error_msg,"Could not execute %s\n",filename); ui_print(error_msg); free(error_msg); return(9999); } close(opipe[1]); close(ipipe[0]); FILE* from = fdopen(opipe[0],"r"); FILE* to = fdopen(ipipe[1],"w"); char* cur_line = calloc(100,sizeof(char)); char* tok; int total_lines; int cur_lines; int num_items; int num_headers; int num_chks; float cur_progress; char** items = NULL; char** headers = NULL; char** chks = NULL; int i = 0; // iterator for menu items int j = 0; // iterator for menu headers int k = 0; // iterator for check menu items int l = 0; // iterator for outputting flags from check menu int flags = INT_MAX; int choice; while (fgets(cur_line,100,from)!=NULL) { printf(cur_line); tok=strtok(cur_line," \n"); if(tok==NULL) {continue;} if(strcmp(tok,"*")==0) { tok=strtok(NULL," \n"); if(tok==NULL) {continue;} if(strcmp(tok,"ptotal")==0) { ui_set_progress(0.0); ui_show_progress(1.0,0); total_lines=atoi(strtok(NULL," ")); } else if (strcmp(tok,"print")==0) { ui_print(strtok(NULL,"")); } else if (strcmp(tok,"items")==0) { num_items=atoi(strtok(NULL," \n")); if(items!=NULL) free(items); items=calloc((num_items+1),sizeof(char*)); items[num_items]=NULL; i=0; } else if (strcmp(tok,"item")==0) { if (i < num_items) { tok=strtok(NULL,"\n"); items[i]=calloc((strlen(tok)+1),sizeof(char)); strcpy(items[i],tok); i++; } } else if (strcmp(tok,"headers")==0) { num_headers=atoi(strtok(NULL," \n")); if(headers!=NULL) free(headers); headers=calloc((num_headers+1),sizeof(char*)); headers[num_headers]=NULL; j=0; } else if (strcmp(tok,"header")==0) { if (j < num_headers) { tok=strtok(NULL,"\n"); if (tok) { headers[j]=calloc((strlen(tok)+1),sizeof(char)); strcpy(headers[j],tok); } else { headers[j]=""; } j++; } } else if (strcmp(tok,"show_menu")==0) { choice=get_menu_selection(headers,items,0,0); fprintf(to, "%d\n", choice); fflush(to); } else if (strcmp(tok,"pcur")==0) { cur_lines=atoi(strtok(NULL,"\n")); if (cur_lines%10==0 || total_lines-cur_lines<10) { cur_progress=(float)cur_lines/((float)total_lines); ui_set_progress(cur_progress); } if (cur_lines==total_lines) ui_reset_progress(); } else if (strcmp(tok,"check_items")==0) { num_chks=atoi(strtok(NULL," \n")); if(chks!=NULL) free(chks); chks=calloc((num_chks+1),sizeof(char*)); chks[num_chks]=NULL; k = 0; } else if (strcmp(tok,"check_item")==0) { if (k < num_chks) { tok=strtok(NULL,"\n"); chks[k]=calloc(strlen(tok)+1,sizeof(char)); strcpy(chks[k],tok); k++; } } else if (strcmp(tok,"show_check_menu")==0) { show_check_menu(headers,chks,&flags); for(l=0;l<num_chks;l++) { fprintf(to, "%d\n", !!(flags&(1<<l))); } fflush(to); } else if (strcmp(tok,"show_indeterminate_progress")==0) { ui_show_indeterminate_progress(); } else {ui_print("unrecognized command "); ui_print(tok); ui_print("\n");} } } while (waitpid(pid, &status, WNOHANG) == 0) { sleep(1); } ui_print("\n"); free(cur_line); return status; }
// If the package contains an update binary, extract it and run it. static int try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) { const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME); if (binary_entry == NULL) { mzCloseZipArchive(zip); return INSTALL_CORRUPT; } const char* binary = "/tmp/update_binary"; unlink(binary); int fd = creat(binary, 0755); if (fd < 0) { mzCloseZipArchive(zip); LOGE("Can't make %s\n", binary); return INSTALL_ERROR; } bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd); close(fd); mzCloseZipArchive(zip); if (!ok) { LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME); return INSTALL_ERROR; } /* Make sure the update binary is compatible with this recovery * * We're building this against 4.4's (or above) bionic, which * has a different property namespace structure. If "set_perm_" * is found, it's probably a regular updater instead of a custom * one. If "set_metadata_" isn't there, it's pre-4.4, which * makes it incompatible. * * Also, I hate matching strings in binary blobs */ FILE *updaterfile = fopen(binary, "rb"); char tmpbuf; char setpermmatch[9] = { 's','e','t','_','p','e','r','m','_' }; char setmetamatch[13] = { 's','e','t','_','m','e','t','a','d','a','t','a','_' }; size_t pos = 0; bool foundsetperm = false; bool foundsetmeta = false; if (updaterfile == NULL) { LOGE("Can't find %s for validation\n", ASSUMED_UPDATE_BINARY_NAME); return INSTALL_ERROR; } fseek(updaterfile, 0, SEEK_SET); while (!feof(updaterfile)) { fread(&tmpbuf, 1, 1, updaterfile); if (!foundsetperm && pos < sizeof(setpermmatch) && tmpbuf == setpermmatch[pos]) { pos++; if (pos == sizeof(setpermmatch)) { foundsetperm = true; pos = 0; } continue; } if (!foundsetmeta && tmpbuf == setmetamatch[pos]) { pos++; if (pos == sizeof(setmetamatch)) { foundsetmeta = true; pos = 0; } continue; } /* None of the match loops got a continuation, reset the counter */ pos = 0; } fclose(updaterfile); /* Set legacy properties */ if (foundsetperm && !foundsetmeta) { ui_print("Using legacy property environment for update-binary...\n"); ui_print("Please upgrade to latest binary...\n"); if (set_legacy_props() != 0) { LOGE("Legacy property environment did not init successfully. Properties may not be detected.\n"); } else { LOGI("Legacy property environment initialized.\n"); } } int pipefd[2]; pipe(pipefd); // When executing the update binary contained in the package, the // arguments passed are: // // - the version number for this interface // // - an fd to which the program can write in order to update the // progress bar. The program can write single-line commands: // // progress <frac> <secs> // fill up the next <frac> part of of the progress bar // over <secs> seconds. If <secs> is zero, use // set_progress commands to manually control the // progress of this segment of the bar // // set_progress <frac> // <frac> should be between 0.0 and 1.0; sets the // progress bar within the segment defined by the most // recent progress command. // // firmware <"hboot"|"radio"> <filename> // arrange to install the contents of <filename> in the // given partition on reboot. // // (API v2: <filename> may start with "PACKAGE:" to // indicate taking a file from the OTA package.) // // (API v3: this command no longer exists.) // // ui_print <string> // display <string> on the screen. // // - the name of the package zip file. // const char** args = (const char**)malloc(sizeof(char*) * 5); args[0] = binary; args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk char* temp = (char*)malloc(10); sprintf(temp, "%d", pipefd[1]); args[2] = temp; args[3] = (char*)path; args[4] = NULL; pid_t pid = fork(); if (pid == 0) { // set the env for UPDATE_PACKAGE (the source zip) for update-binary. This allows shell scripts to use the source zip. // https://github.com/CyanogenMod/android_bootable_recovery/commit/20b516a408adebcad06e03f12516e70b8998c38f setenv("UPDATE_PACKAGE", path, 1); close(pipefd[0]); execve(binary, (char* const*)args, environ); fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno)); _exit(-1); } close(pipefd[1]); *wipe_cache = 0; char buffer[1024]; FILE* from_child = fdopen(pipefd[0], "r"); while (fgets(buffer, sizeof(buffer), from_child) != NULL) { char* command = strtok(buffer, " \n"); if (command == NULL) { continue; } else if (strcmp(command, "progress") == 0) { char* fraction_s = strtok(NULL, " \n"); char* seconds_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); int seconds = strtol(seconds_s, NULL, 10); ui_show_progress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds); } else if (strcmp(command, "set_progress") == 0) { char* fraction_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); ui_set_progress(fraction); } else if (strcmp(command, "ui_print") == 0) { char* str = strtok(NULL, "\n"); if (str) { ui_print("%s", str); } else { ui_print("\n"); } fflush(stdout); } else if (strcmp(command, "wipe_cache") == 0) { *wipe_cache = 1; } else if (strcmp(command, "clear_display") == 0) { // not needed in PhilZ Touch; } else { LOGE("unknown command [%s]\n", command); } } fclose(from_child); int status; waitpid(pid, &status, 0); /* Unset legacy properties */ if (legacy_props_path_modified) { if (unset_legacy_props() != 0) { LOGE("Legacy property environment did not disable successfully. Legacy properties may still be in use.\n"); } else { LOGI("Legacy property environment disabled.\n"); } } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status)); return INSTALL_ERROR; } return INSTALL_SUCCESS; }
// If the package contains an update binary, extract it and run it. static int try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) { const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME); if (binary_entry == NULL) { mzCloseZipArchive(zip); return INSTALL_CORRUPT; } fprintf(stderr, "try_update_binary(path(%s))\n",path); radio_diff = mzFindZipEntry(zip, RADIO_DIFF_NAME); if (radio_diff == NULL) { fprintf(stderr, "%s not found\n", RADIO_DIFF_NAME); } else { char* diff_file = RADIO_DIFF_OUTPUT; int fd_diff = creat(diff_file, 0777); fprintf(stderr, "%s found\n", RADIO_DIFF_NAME); if (fd_diff < 0) { fprintf(stderr, "Can't make %s\n", diff_file); } else { bool ok_diff = mzExtractZipEntryToFile(zip, radio_diff, fd_diff); close(fd_diff); if (!ok_diff) { fprintf(stderr, "Can't copy %s\n", RADIO_DIFF_NAME); } } } char* binary = "/tmp/update_binary"; unlink(binary); int fd = creat(binary, 0755); if (fd < 0) { mzCloseZipArchive(zip); LOGE("Can't make %s\n", binary); return INSTALL_ERROR; } bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd); close(fd); mzCloseZipArchive(zip); if (!ok) { LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME); return INSTALL_ERROR; } int pipefd[2]; pipe(pipefd); // When executing the update binary contained in the package, the // arguments passed are: // // - the version number for this interface // // - an fd to which the program can write in order to update the // progress bar. The program can write single-line commands: // // progress <frac> <secs> // fill up the next <frac> part of of the progress bar // over <secs> seconds. If <secs> is zero, use // set_progress commands to manually control the // progress of this segment of the bar // // set_progress <frac> // <frac> should be between 0.0 and 1.0; sets the // progress bar within the segment defined by the most // recent progress command. // // firmware <"hboot"|"radio"> <filename> // arrange to install the contents of <filename> in the // given partition on reboot. // // (API v2: <filename> may start with "PACKAGE:" to // indicate taking a file from the OTA package.) // // (API v3: this command no longer exists.) // // ui_print <string> // display <string> on the screen. // // - the name of the package zip file. // char** args = malloc(sizeof(char*) * 5); args[0] = binary; args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk args[2] = malloc(10); sprintf(args[2], "%d", pipefd[1]); args[3] = (char*)path; args[4] = NULL; pid_t pid = fork(); if (pid == 0) { close(pipefd[0]); execv(binary, args); fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno)); _exit(-1); } close(pipefd[1]); *wipe_cache = 0; char buffer[1024]; FILE* from_child = fdopen(pipefd[0], "r"); while (fgets(buffer, sizeof(buffer), from_child) != NULL) { char* command = strtok(buffer, " \n"); if (command == NULL) { continue; } else if (strcmp(command, "progress") == 0) { char* fraction_s = strtok(NULL, " \n"); char* seconds_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); int seconds = strtol(seconds_s, NULL, 10); ui_show_progress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds); } else if (strcmp(command, "set_progress") == 0) { char* fraction_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); ui_set_progress(fraction); } else if (strcmp(command, "ui_print") == 0) { char* str = strtok(NULL, "\n"); if (str) { ui_print("%s", str); } else { ui_print("\n"); } } else if (strcmp(command, "wipe_cache") == 0) { *wipe_cache = 1; } else { LOGE("unknown command [%s]\n", command); } } fclose(from_child); int status; waitpid(pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status)); return INSTALL_ERROR; } return INSTALL_SUCCESS; }
void nandroid_back_exe() { ensure_path_mounted(SDCARD_ROOT); FILE *fp; int isContinue = 1; int progTime; unsigned long sdSpace; unsigned long sdSpaceFinal; unsigned long imgSpace; char tmpOutput[150]; char tmpString[15]; char tmpChar; char exe[255]; char tw_image_base[100]; char tw_image[255]; char timestamp[14]; char tar_arg[5]; struct stat st; struct tm * t; time_t seconds; time_t nan_ttime; time_t nan_ctime; seconds = time(0); t = localtime(&seconds); sprintf(timestamp,"%02d%02d%d%02d%02d",t->tm_mon+1,t->tm_mday,t->tm_year+1900,t->tm_hour,t->tm_min); // get timestamp for nandroid if (stat(backup_folder,&st) != 0) { if(mkdir(backup_folder,0777) == -1) { LOGI("=> Can not create directory: %s\n", backup_folder); } else { LOGI("=> Created directory: %s\n", backup_folder); } } sprintf(tw_image_base, "%s/%s/", backup_folder, device_id); if (stat(tw_image_base,&st) != 0) { if(mkdir(tw_image_base,0777) == -1) { LOGI("=> Can not create directory: %s\n", tw_image_base); } else { LOGI("=> Created directory: %s\n", tw_image_base); } } strcat(tw_image_base,timestamp); strcat(tw_image_base,"/"); if(mkdir(tw_image_base,0777) == -1) { LOGI("=> Can not create directory: %s\n", tw_image_base); } else { LOGI("=> Created directory: %s\n", tw_image_base); } fp = __popen("df -k /sdcard| grep sdcard | awk '{ print $4 }'", "r"); LOGI("=> Checking SDCARD Disk Space.\n"); while (fgets(tmpString,15,fp) != NULL) { tmpChar = tmpString[strlen(tmpString)-2]; } __pclose(fp); if(tmpChar == '%') { fp = __popen("df -k /sdcard| grep sdcard | awk '{ print $3 }'", "r"); LOGI("=> Not the response we were looking for, trying again.\n"); fgets(tmpString,15,fp); __pclose(fp); } sscanf(tmpString,"%lu",&sdSpace); sdSpaceFinal = sdSpace; LOGI("=> Space Left on SDCARD: %lu\n\n",sdSpaceFinal); int div; if (is_true(tw_use_compression_val) == 1) { strcpy(tar_arg,"czvpf"); div = 500; } else { strcpy(tar_arg,"cvpf"); div = 1000; } ui_print("\nStarting Backup...\n\n"); nan_ttime = time(0); if (is_true(tw_nan_system_val)) { ensure_path_mounted("/system"); fp = __popen("du -sk /system", "r"); LOGI("=> Checking size of /system.\n"); fscanf(fp,"%lu %*s",&imgSpace); progTime = imgSpace / div; ui_print("[SYSTEM (%d MB)]\n",imgSpace/1024); __pclose(fp); if (sdSpace > imgSpace) { nan_ctime = time(0); strcpy(tw_image,tw_image_base); strcat(tw_image,tw_nan_system); sprintf(exe,"cd /%s && tar -%s %s ./*", sys.mnt, tar_arg, tw_image); ui_print("...Backing up system partition.\n"); ui_show_progress(1,progTime); fp = __popen(exe, "r"); while (fscanf(fp,"%s",tmpOutput) != EOF) { if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } ui_print_overwrite("....Done.\n"); __pclose(fp); ui_print("...Generating %s md5...\n", sys.mnt); makeMD5(tw_image_base,tw_nan_system); ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", sys.mnt); checkMD5(tw_image_base,tw_nan_system); ui_print("...Done.\n"); ui_reset_progress(); ui_print("Backed up in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("\nNot enough space left on /sdcard... Aborting.\n\n"); isContinue = 0; } ensure_path_unmounted("/system"); sdSpace -= imgSpace; } if (isContinue) { if (is_true(tw_nan_data_val)) { ensure_path_mounted("/data"); fp = __popen("du -sk /data", "r"); LOGI("=> Checking size of /data.\n"); fscanf(fp,"%lu %*s",&imgSpace); progTime = imgSpace / div; ui_print("[DATA (%d MB)]\n",imgSpace/1024); __pclose(fp); if (sdSpace > imgSpace) { nan_ctime = time(0); strcpy(tw_image,tw_image_base); strcat(tw_image,tw_nan_data); sprintf(exe,"cd /%s && tar -%s %s ./*", dat.mnt, tar_arg, tw_image); ui_print("...Backing up data partition.\n"); ui_show_progress(1,progTime); fp = __popen(exe, "r"); while (fscanf(fp,"%s",tmpOutput) != EOF) { if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } ui_print_overwrite("....Done.\n"); __pclose(fp); ui_print("...Generating %s md5...\n", dat.mnt); makeMD5(tw_image_base,tw_nan_data); ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", dat.mnt); checkMD5(tw_image_base,tw_nan_data); ui_print("...Done.\n"); ui_reset_progress(); ui_print("Backed up in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("\nNot enough space left on /sdcard... Aborting.\n\n"); isContinue = 0; } ensure_path_unmounted("/data"); sdSpace -= imgSpace; } } if (isContinue) { if (is_true(tw_nan_boot_val)) { imgSpace = boo.sze / 1024; ui_print("[BOOT (%i MB)]\n",imgSpace/1024); if (sdSpace > imgSpace) { nan_ctime = time(0); strcpy(tw_image,tw_image_base); strcat(tw_image,tw_nan_boot); if (strcmp(boo.fst,"mtd") == 0) { sprintf(exe,"dump_image %s %s", boo.mnt, tw_image); } else { sprintf(exe,"dd bs=%s if=%s of=%s", bs_size, boo.dev, tw_image); } ui_print("...Backing up boot partition.\n"); ui_show_progress(1,5); __system(exe); LOGI("=> %s\n", exe); ui_print("....Done.\n"); ui_print("...Generating %s md5...\n", boo.mnt); makeMD5(tw_image_base,tw_nan_boot); ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", boo.mnt); checkMD5(tw_image_base,tw_nan_boot); ui_print("...Done.\n"); ui_reset_progress(); ui_print("Backed up in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("\nNot enough space left on /sdcard... Aborting.\n\n"); isContinue = 0; } sdSpace -= imgSpace; } } if (isContinue) { if (is_true(tw_nan_recovery_val)) { imgSpace = rec.sze / 1024; ui_print("[RECOVERY (%i MB)]\n",imgSpace/1024); if (sdSpace > imgSpace) { nan_ctime = time(0); strcpy(tw_image,tw_image_base); strcat(tw_image,tw_nan_recovery); if (strcmp(rec.fst,"mtd") == 0) { sprintf(exe,"dump_image %s %s", rec.mnt, tw_image); } else { sprintf(exe,"dd bs=%s if=%s of=%s", bs_size, rec.dev, tw_image); } ui_print("...Backing up recovery partition.\n"); ui_show_progress(1,5); __system(exe); LOGI("=> %s\n", exe); ui_print("....Done.\n"); ui_print("...Generating %s md5...\n", rec.mnt); makeMD5(tw_image_base,tw_nan_recovery); ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", rec.mnt); checkMD5(tw_image_base,tw_nan_recovery); ui_print("...Done.\n"); ui_reset_progress(); ui_print("Backed up in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("\nNot enough space left on /sdcard... Aborting.\n\n"); isContinue = 0; } sdSpace -= imgSpace; } } if (isContinue) { if (is_true(tw_nan_cache_val)) { ensure_path_mounted("/cache"); fp = __popen("du -sk /cache", "r"); LOGI("=> Checking size of /cache.\n"); fscanf(fp,"%lu %*s",&imgSpace); progTime = imgSpace / div; ui_print("[CACHE (%d MB)]\n",imgSpace/1024); __pclose(fp); if (sdSpace > imgSpace) { nan_ctime = time(0); strcpy(tw_image,tw_image_base); strcat(tw_image,tw_nan_cache); sprintf(exe,"cd /%s && tar -%s %s ./*", cac.mnt, tar_arg, tw_image); ui_print("...Backing up cache partition.\n"); ui_show_progress(1,progTime); fp = __popen(exe, "r"); while (fscanf(fp,"%s",tmpOutput) != EOF) { if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } ui_print_overwrite("....Done.\n"); __pclose(fp); ui_print("...Generating %s md5...\n", cac.mnt); makeMD5(tw_image_base,tw_nan_cache); ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", cac.mnt); checkMD5(tw_image_base,tw_nan_cache); ui_print("...Done.\n"); ui_reset_progress(); ui_print("Backed up in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("\nNot enough space left on /sdcard... Aborting.\n\n"); isContinue = 0; } ensure_path_unmounted("/cache"); sdSpace -= imgSpace; } } if (isContinue) { if (is_true(tw_nan_wimax_val)) { if (strcmp(wim.mnt,"wimax") == 0) { imgSpace = wim.sze / 1024; ui_print("[WIMAX (%d MB)]\n",imgSpace/1024); } else { __system("mount /efs"); fp = __popen("du -sk /efs", "r"); LOGI("=> Checking size of /efs.\n"); fscanf(fp,"%lu %*s",&imgSpace); ui_print("[EFS (%d MB)]\n",imgSpace/1024); __pclose(fp); } if (sdSpace > imgSpace) { nan_ctime = time(0); strcpy(tw_image,tw_image_base); strcat(tw_image,tw_nan_wimax); ui_print("...Backing up %s partition.\n", wim.mnt); ui_show_progress(1,5); if (strcmp(wim.mnt,"efs") == 0) { sprintf(exe,"cd /%s && tar -%s %s ./*", wim.mnt, tar_arg, tw_image); } else { if (strcmp(wim.fst,"mtd") == 0) { sprintf(exe,"dump_image %s %s", wim.mnt, tw_image); fp = __popen(exe, "r"); while (fscanf(fp,"%s",tmpOutput) != EOF) { if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); } else { sprintf(exe,"dd bs=%s if=%s of=%s", bs_size, wim.dev, tw_image); __system(exe); LOGI("=> %s\n", exe); } } ui_print_overwrite("....Done.\n"); ui_print("...Generating %s md5...\n", wim.mnt); makeMD5(tw_image_base,tw_nan_wimax); ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", wim.mnt); checkMD5(tw_image_base,tw_nan_wimax); ui_print("...Done.\n"); ui_reset_progress(); ui_print("Backed up in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("\nNot enough space left on /sdcard... Aborting.\n\n"); isContinue = 0; } if (strcmp(wim.mnt,"efs") == 0) { __system("umount /efs"); } sdSpace -= imgSpace; } } if (isContinue) { if (is_true(tw_nan_andsec_val)) { ensure_path_mounted(ase.dev); fp = __popen("du -sk /sdcard/.android_secure", "r"); LOGI("=> Checking size of .android_secure.\n"); fscanf(fp,"%lu %*s",&imgSpace); progTime = imgSpace / div; ui_print("[ANDROID_SECURE (%d MB)]\n",imgSpace/1024); __pclose(fp); if (sdSpace > imgSpace) { nan_ctime = time(0); strcpy(tw_image,tw_image_base); strcat(tw_image,tw_nan_andsec); sprintf(exe,"cd %s && tar -%s %s ./*", ase.dev, tar_arg, tw_image); ui_print("...Backing up .android_secure.\n"); ui_show_progress(1,progTime); fp = __popen(exe, "r"); while (fscanf(fp,"%s",tmpOutput) != EOF) { if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); ui_print_overwrite("....Done.\n"); ui_print("...Generating %s md5...\n", ase.mnt); makeMD5(tw_image_base,tw_nan_andsec); ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", ase.mnt); checkMD5(tw_image_base,tw_nan_andsec); ui_print("...Done.\n"); ui_reset_progress(); ui_print("Backed up in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("\nNot enough space left on /sdcard... Aborting.\n\n"); isContinue = 0; } sdSpace -= imgSpace; } } if (isContinue) { if (is_true(tw_nan_sdext_val)) { __system("mount /sd-ext"); fp = __popen("du -sk /sd-ext", "r"); LOGI("=> Checking size of /sd-ext.\n"); fscanf(fp,"%lu %*s",&imgSpace); progTime = imgSpace / div; ui_print("[SD-EXT (%d MB)]\n",imgSpace/1024); __pclose(fp); if (sdSpace > imgSpace) { nan_ctime = time(0); strcpy(tw_image,tw_image_base); strcat(tw_image,tw_nan_sdext); sprintf(exe,"cd %s && tar -%s %s ./*", sde.mnt, tar_arg, tw_image); ui_print("...Backing up sd-ext partition.\n"); ui_show_progress(1,progTime); fp = __popen(exe, "r"); while (fscanf(fp,"%s",tmpOutput) != EOF) { if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); ui_print_overwrite("....Done.\n"); ui_print("...Generating %s md5...\n", sde.mnt); makeMD5(tw_image_base,tw_nan_sdext); ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", sde.mnt); checkMD5(tw_image_base,tw_nan_sdext); ui_print("...Done.\n"); ui_reset_progress(); ui_print("Backed up in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("\nNot enough space left on /sdcard... Aborting.\n\n"); isContinue = 0; } __system("umount /sd-ext"); sdSpace -= imgSpace; } } fp = __popen("df -k /sdcard| grep sdcard | awk '{ print $4 }'", "r"); while (fgets(tmpString,15,fp) != NULL) { tmpChar = tmpString[strlen(tmpString)-2]; } __pclose(fp); if(tmpChar == '%') { fp = __popen("df -k /sdcard| grep sdcard | awk '{ print $3 }'", "r"); LOGI("=> Not the response we were looking for, trying again.\n"); fgets(tmpString,15,fp); __pclose(fp); } sscanf(tmpString,"%lu",&sdSpace); int totalBackedUp = (int)(sdSpaceFinal - sdSpace) / 1024; ui_print("[ %d MB TOTAL BACKED UP TO SDCARD ]\n[ BACKUP COMPLETED IN %d SECONDS ]\n\n", totalBackedUp, time(0) - nan_ttime); }
void nandroid_rest_exe() { ensure_path_mounted(SDCARD_ROOT); FILE *fp; char tmpBuffer[1024]; char *tmpOutput; int tmpSize; int numErrors = 0; char exe[255]; char* tmp_file = (char*)malloc(255); time_t nan_ttime; time_t nan_ctime; ui_print("\nStarting Restore...\n\n"); nan_ttime = time(0); if (tw_nan_system_x == 1) { ui_print("...Verifying md5 hash for %s.\n",tw_nan_system); ui_show_progress(1,150); nan_ctime = time(0); if(checkMD5(nan_dir,tw_nan_system)) { ensure_path_mounted("/system"); strcpy(tmp_file,nan_dir); strcat(tmp_file,tw_nan_system); ui_print("...Wiping %s.\n",sys.mnt); sprintf(exe,"rm -rf /%s/* && rm -rf /%s/.* ", sys.mnt, sys.mnt); __system(exe); ui_print("....Done.\n"); sprintf(exe,"cd /%s && tar xzvpf %s", sys.mnt, tmp_file); ui_print("...Restoring system partition.\n"); fp = __popen(exe, "r"); while (fgets(tmpBuffer,sizeof(tmpBuffer),fp) != NULL) { tmpBuffer[strlen(tmpBuffer)-1] = '\0'; tmpOutput = tmpBuffer; if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); ui_print_overwrite("....Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); ensure_path_unmounted("/system"); } else { ui_print("...Failed md5 check. Aborted.\n\n"); numErrors++; } ui_reset_progress(); } if (tw_nan_data_x == 1) { ui_print("...Verifying md5 hash for %s.\n",tw_nan_data); ui_show_progress(1,150); nan_ctime = time(0); if(checkMD5(nan_dir,tw_nan_data)) { ensure_path_mounted("/data"); strcpy(tmp_file,nan_dir); strcat(tmp_file,tw_nan_data); ui_print("...Wiping %s.\n",dat.mnt); sprintf(exe,"rm -rf /%s/* && rm -rf /%s/.* ", dat.mnt, dat.mnt); __system(exe); ui_print("....Done.\n"); sprintf(exe,"cd /%s && tar xzvpf %s", dat.mnt, tmp_file); ui_print("...Restoring data partition.\n"); fp = __popen(exe, "r"); while (fgets(tmpBuffer,sizeof(tmpBuffer),fp) != NULL) { tmpBuffer[strlen(tmpBuffer)-1] = '\0'; tmpOutput = tmpBuffer; if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); ui_print_overwrite("....Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); ensure_path_unmounted("/data"); } else { ui_print("...Failed md5 check. Aborted.\n\n"); numErrors++; } ui_reset_progress(); } if (tw_nan_boot_x == 1) { ui_print("...Verifying md5 hash for %s.\n",tw_nan_boot); ui_show_progress(1,5); nan_ctime = time(0); if(checkMD5(nan_dir,tw_nan_boot)) { strcpy(tmp_file,nan_dir); strcat(tmp_file,tw_nan_boot); ui_print("...Double checking, by checking file size.\n"); sprintf(exe,"ls -l %s",tmp_file); fp = __popen(exe, "r"); fscanf(fp,"%*s %*i %*s %*s %i",&tmpSize); if (tmpSize == boo.sze) { ui_print("....File size matched partition size.\n"); if (strcmp(boo.fst,"mtd") == 0) { sprintf(exe,"flash_image %s %s", boo.mnt, tmp_file); } else { sprintf(exe,"dd bs=%s if=%s of=%s", bs_size, tmp_file, boo.dev); } LOGI("=> %s\n", exe); ui_print("...Restoring boot partition.\n"); __system(exe); ui_print("...Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("...Failed file size check. Aborted.\n\n"); numErrors++; } __pclose(fp); } else { ui_print("...Failed md5 check. Aborted.\n\n"); numErrors++; } ui_reset_progress(); } if (tw_nan_recovery_x == 1) { ui_print("...Verifying md5 hash for %s.\n",tw_nan_recovery); ui_show_progress(1,5); nan_ctime = time(0); if(checkMD5(nan_dir,tw_nan_recovery)) { strcpy(tmp_file,nan_dir); strcat(tmp_file,tw_nan_recovery); ui_print("...Double checking, by checking file size.\n"); sprintf(exe,"ls -l %s",tmp_file); fp = __popen(exe, "r"); fscanf(fp,"%*s %*i %*s %*s %i",&tmpSize); if (tmpSize == rec.sze) { ui_print("....File size matched partition size.\n"); if (strcmp(rec.fst,"mtd") == 0) { sprintf(exe,"flash_image %s %s", rec.mnt, tmp_file); } else { sprintf(exe,"dd bs=%s if=%s of=%s", bs_size, tmp_file, rec.dev); } LOGI("=> %s\n", exe); ui_print("...Restoring recovery partition.\n"); __system(exe); ui_print("...Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("...Failed file size check. Aborted.\n\n"); numErrors++; } __pclose(fp); } else { ui_print("...Failed md5 check. Aborted.\n\n"); numErrors++; } ui_reset_progress(); } if (tw_nan_cache_x == 1) { ui_print("...Verifying md5 hash for %s.\n",tw_nan_cache); ui_show_progress(1,100); nan_ctime = time(0); if(checkMD5(nan_dir,tw_nan_cache)) { ensure_path_mounted("/cache"); strcpy(tmp_file,nan_dir); strcat(tmp_file,tw_nan_cache); ui_print("...Wiping %s.\n",cac.mnt); sprintf(exe,"rm -rf /%s/* && rm -rf /%s/.* ", cac.mnt, cac.mnt); __system(exe); ui_print("....Done.\n"); sprintf(exe,"cd /%s && tar xzvpf %s", cac.mnt, tmp_file); ui_print("...Restoring cache partition.\n"); fp = __popen(exe, "r"); while (fgets(tmpBuffer,sizeof(tmpBuffer),fp) != NULL) { tmpBuffer[strlen(tmpBuffer)-1] = '\0'; tmpOutput = tmpBuffer; if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); ui_print_overwrite("....Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); ensure_path_unmounted("/cache"); } else { ui_print("...Failed md5 check. Aborted.\n\n"); numErrors++; } ui_reset_progress(); } if (tw_nan_wimax_x == 1) { ui_print("...Verifying md5 hash for %s.\n",tw_nan_wimax); ui_show_progress(1,5); nan_ctime = time(0); if(checkMD5(nan_dir,tw_nan_wimax)) { strcpy(tmp_file,nan_dir); strcat(tmp_file,tw_nan_wimax); if (strcmp(wim.mnt,"efs") == 0) { __system("mount /efs"); ui_print("...Wiping %s.\n",wim.mnt); sprintf(exe,"rm -rf /%s/* && rm -rf /%s/.*", wim.mnt); __system(exe); ui_print("....Done.\n"); sprintf(exe,"cd /%s && tar xzvpf %s", wim.mnt, tmp_file); ui_print("...Restoring efs partition.\n"); fp = __popen(exe, "r"); while (fgets(tmpBuffer,sizeof(tmpBuffer),fp) != NULL) { tmpBuffer[strlen(tmpBuffer)-1] = '\0'; tmpOutput = tmpBuffer; if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); ui_print_overwrite("....Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); __system("umount /efs"); } else { ui_print("...Double checking, by checking file size.\n"); sprintf(exe,"ls -l %s",tmp_file); fp = __popen(exe, "r"); fscanf(fp,"%*s %*i %*s %*s %i",&tmpSize); if (tmpSize == wim.sze) { ui_print("....File size matched partition size.\n"); if (strcmp(rec.fst,"mtd") == 0) { sprintf(exe,"flash_image %s %s", wim.mnt, tmp_file); } else { sprintf(exe,"dd bs=%s if=%s of=%s", bs_size, tmp_file, wim.dev); } LOGI("=> %s\n", exe); ui_print("...Restoring wimax partition.\n"); __system(exe); ui_print("...Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("...Failed file size check. Aborted.\n\n"); numErrors++; } __pclose(fp); } } else { ui_print("...Failed md5 check. Aborted.\n\n"); numErrors++; } ui_reset_progress(); } if (tw_nan_andsec_x == 1) { ui_print("...Verifying md5 hash for %s.\n",tw_nan_andsec); ui_show_progress(1,25); nan_ctime = time(0); if(checkMD5(nan_dir,tw_nan_andsec)) { ensure_path_mounted(ase.dev); strcpy(tmp_file,nan_dir); strcat(tmp_file,tw_nan_andsec); ui_print("...Wiping %s.\n",ase.dev); sprintf(exe,"rm -rf %s/* && rm -rf %s/.* ", ase.dev, ase.dev); __system(exe); ui_print("....Done.\n"); sprintf(exe,"cd %s && tar xzvpf %s", ase.dev, tmp_file); ui_print("...Restoring .android-secure.\n"); fp = __popen(exe, "r"); while (fgets(tmpBuffer,sizeof(tmpBuffer),fp) != NULL) { tmpBuffer[strlen(tmpBuffer)-1] = '\0'; tmpOutput = tmpBuffer; if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); ui_print_overwrite("....Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); } else { ui_print("...Failed md5 check. Aborted.\n\n"); numErrors++; } ui_reset_progress(); } if (tw_nan_sdext_x == 1) { ui_print("...Verifying md5 hash for %s.\n",tw_nan_sdext); ui_show_progress(1,25); nan_ctime = time(0); if(checkMD5(nan_dir,tw_nan_sdext)) { __system("mount /sd-ext"); strcpy(tmp_file,nan_dir); strcat(tmp_file,tw_nan_sdext); ui_print("...Wiping %s.\n",sde.mnt); sprintf(exe,"rm -rf /%s/* && rm -rf /%s/.* ", sde.mnt, sde.mnt); __system(exe); ui_print("....Done.\n"); sprintf(exe,"cd /%s && tar xzvpf %s", sde.mnt, tmp_file); ui_print("...Restoring sd-ext partition.\n"); fp = __popen(exe, "r"); while (fgets(tmpBuffer,sizeof(tmpBuffer),fp) != NULL) { tmpBuffer[strlen(tmpBuffer)-1] = '\0'; tmpOutput = tmpBuffer; if(is_true(tw_show_spam_val)) { ui_print("%s\n",tmpOutput); } else { ui_print_overwrite("%s",tmpOutput); } } __pclose(fp); ui_print_overwrite("....Done.\n"); ui_print("Restored in %d Seconds\n\n", time(0) - nan_ctime); __system("umount /sd-ext"); } else { ui_print("...Failed md5 check. Aborted.\n\n"); numErrors++; } ui_reset_progress(); } if (numErrors > 0) { ui_print("[ %d ERROR(S), PLEASE CHECK LOGS ]\n", numErrors); } ui_print("[ RESTORE COMPLETED IN %d SECONDS ]\n\n", time(0) - nan_ttime); __system("sync"); free(tmp_file); }