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; }
bool MROMInstaller::extractDir(const std::string& name, const std::string& dest) { ZipArchive zip; MemMapping map; if (sysMapFile(m_file.c_str(), &map) != 0) { LOGERR("Failed to sysMapFile '%s'\n", m_file.c_str()); return false; } if (mzOpenZipArchive(map.addr, map.length, &zip) != 0) { gui_print("Failed to open ZIP file %s\n", m_file.c_str()); sysReleaseMap(&map); return false; } // To create a consistent system image, never use the clock for timestamps. struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default bool success = mzExtractRecursive(&zip, name.c_str(), dest.c_str(), MZ_EXTRACT_FILES_ONLY, ×tamp, NULL, NULL, NULL); mzCloseZipArchive(&zip); sysReleaseMap(&map); if(!success) { gui_print("Failed to extract dir %s from zip %s\n", name.c_str(), m_file.c_str()); return false; } return true; }
bool MROMInstaller::hasEntry(const std::string& name) { ZipArchive zip; #if (ANDROID_VERSION >= 5) MemMapping map; if (sysMapFile(m_file.c_str(), &map) != 0) { LOGERR("Failed to sysMapFile '%s'\n", m_file.c_str()); return false; } if (mzOpenZipArchive(map.addr, map.length, &zip) != 0) #else if (mzOpenZipArchive(m_file.c_str(), &zip) != 0) #endif { gui_print("Failed to open ZIP file %s\n", m_file.c_str()); #if (ANDROID_VERSION >= 5) sysReleaseMap(&map); #endif return false; } // Check also for entry with / - according to minzip, folders // usually (but not always) end with / const ZipEntry *entry1 = mzFindZipEntry(&zip, name.c_str()); const ZipEntry *entry2 = mzFindZipEntry(&zip, (name + "/").c_str()); mzCloseZipArchive(&zip); #if (ANDROID_VERSION >= 5) sysReleaseMap(&map); #endif return entry1 || entry2; }
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 (strcmp(root_path, ":") == 0) { if (ensure_root_path_mounted(root_path) != 0) { LOGE("Can't mount %s\n", root_path); return INSTALL_CORRUPT; } if (translate_root_path(root_path, path, sizeof(path)) == NULL) { LOGE("Bad path %s\n", root_path); return INSTALL_CORRUPT; } } else { path = strndup(path, root_path); } */ 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); */ /* Try to open the package. */ ZipArchive zip; int 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, loadedKeys, numKeys); int status = handle_update_package(path, &zip); mzCloseZipArchive(&zip); // free(loadedKeys); return status; }
int extract_deltaupdate_binary(const char *path) { int err; ZipArchive zip; // Try to open the package. err = mzOpenZipArchive(path, &zip); if (err != 0) { LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); return INSTALL_ERROR; } const ZipEntry* dua_entry = mzFindZipEntry(&zip, ASSUMED_DELTAUPDATE_BINARY_NAME); if (dua_entry == NULL) { mzCloseZipArchive(&zip); LOGE("Can't find %s\n", ASSUMED_DELTAUPDATE_BINARY_NAME); return INSTALL_ERROR; } char* deltaupdate_agent = RUN_DELTAUPDATE_AGENT; unlink(deltaupdate_agent); int fd = creat(deltaupdate_agent, 0755); if (fd < 0) { mzCloseZipArchive(&zip); LOGE("Can't make %s\n", deltaupdate_agent); return INSTALL_ERROR; } bool ok = mzExtractZipEntryToFile(&zip, dua_entry, fd); close(fd); mzCloseZipArchive(&zip); if (!ok) { LOGE("Can't copy %s\n", ASSUMED_DELTAUPDATE_BINARY_NAME); return INSTALL_ERROR; } return 0; }
bool MROMInstaller::extractFile(const std::string& name, const std::string& dest) { ZipArchive zip; #if (ANDROID_VERSION >= 5) MemMapping map; if (sysMapFile(m_file.c_str(), &map) != 0) { LOGERR("Failed to sysMapFile '%s'\n", m_file.c_str()); return false; } if (mzOpenZipArchive(map.addr, map.length, &zip) != 0) #else if (mzOpenZipArchive(m_file.c_str(), &zip) != 0) #endif { gui_print("Failed to open ZIP file %s\n", m_file.c_str()); #if (ANDROID_VERSION >= 5) sysReleaseMap(&map); #endif return false; } bool res = false; FILE* f = NULL; const ZipEntry* entry = mzFindZipEntry(&zip, name.c_str()); if (entry == NULL) { gui_print("Could not find file %s in zip %s\n", name.c_str(), m_file.c_str()); goto exit; } f = fopen(dest.c_str(), "wb"); if(!f) { gui_print("Could not open dest file %s for writing!\n", dest.c_str()); goto exit; } res = mzExtractZipEntryToFile(&zip, entry, fileno(f)); if(!res) gui_print("Failed to extract file %s from the ZIP!", name.c_str()); fclose(f); exit: mzCloseZipArchive(&zip); #if (ANDROID_VERSION >= 5) sysReleaseMap(&map); #endif return res; }
int open_ota_package(const char *root_path) { int status = INSTALL_SUCCESS; int recovery_status = 0; ui_print("Opening OTA upgrade package...\n"); char *c = root_path; const char *p; int len = strlen(root_path); int i; c = c + len-2; for(i=1;i<len-1;i++) { --c; } c[len-1] = '\0'; p = c; int err; ZipArchive zip; err = mzOpenZipArchive(p, &zip); if (err != 0) { ui_print("Can't open '%s'\n(%s)\n", p, err != -1 ? strerror(err) : "bad"); status = INSTALL_CORRUPT; goto exit; } ui_print("start update package file\n"); status = handle_update_package(p, &zip); ui_print("install_success!!!\n"); mzCloseZipArchive(&zip); exit: if (status != INSTALL_SUCCESS) recovery_status = 1; else recovery_status = 0; return status; }
int install_package(const char *root_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_print("Finding update package...\n"); 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); /* Try to open the package. */ int err; 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; }
int install_package(const char *root_path) { ui_set_background(BACKGROUND_ICON_INSTALLING); ui_print("查找升级包中...\n"); LOGI("升级点: %s\n", root_path); if (ensure_root_path_mounted(root_path) != 0) { LOGE("无法挂载 %s\n", root_path); return INSTALL_CORRUPT; } char path[PATH_MAX] = ""; if (translate_root_path(root_path, path, sizeof(path)) == NULL) { LOGE("错误路径 %s\n", root_path); return INSTALL_CORRUPT; } ui_print("打开升级包中...\n"); LOGI("升级文件路径: %s\n", path); /* Try to open the package. */ int err; ZipArchive zip; err = mzOpenZipArchive(path, &zip); if (err != 0) { LOGE("无法打开%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; }
std::string MROMInstaller::open(const std::string& file) { char* manifest = NULL; const ZipEntry *script_entry; ZipArchive zip; #if (ANDROID_VERSION >= 5) MemMapping map; if (sysMapFile(file.c_str(), &map) != 0) { LOGERR("Failed to sysMapFile '%s'\n", file.c_str()); return false; } if (mzOpenZipArchive(map.addr, map.length, &zip) != 0) #else if (mzOpenZipArchive(file.c_str(), &zip) != 0) #endif return "Failed to open installer file!"; script_entry = mzFindZipEntry(&zip, "manifest.txt"); if(!script_entry) { mzCloseZipArchive(&zip); #if (ANDROID_VERSION >= 5) sysReleaseMap(&map); #endif return "Failed to find manifest.txt"; } int res = read_data(&zip, script_entry, &manifest, NULL); mzCloseZipArchive(&zip); #if (ANDROID_VERSION >= 5) sysReleaseMap(&map); #endif if(res < 0) return "Failed to read manifest.txt!"; int line_cnt = 1; for(char *line = strtok(manifest, "\r\n"); line; line = strtok(NULL, "\r\n"), ++line_cnt) { if(line[0] == '#') continue; char *val = strchr(line, '='); if(!val) continue; std::string key = std::string(line, val-line); ++val; // skip '=' char char *start = strchr(val, '"'); char *end = strrchr(val, '"'); if(!start || start == end || start+1 == end) gui_print("Line %d: failed to parse string\n", line_cnt); else { ++start; m_vals[key] = std::string(start, end-start); LOGI("MROMInstaller: got tag %s=%s\n", key.c_str(), m_vals[key].c_str()); } } free(manifest); static const char* needed[] = { "manifest_ver", "devices", "base_folders" }; for(uint32_t i = 0; i < sizeof(needed)/sizeof(needed[0]); ++i) { std::map<std::string, std::string>::const_iterator itr = m_vals.find(needed[i]); if(itr == m_vals.end()) return std::string("Required key not found in manifest: ") + needed[i]; } m_file = file; return std::string(); }
// 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; } 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) { close(pipefd[0]); execv(binary, (char* const*)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->ShowProgress(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->SetProgress(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) { ui->SetBackground(RecoveryUI::NONE); } 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; }
/* * Function : libaroma_zip_release * Return Value: void * Descriptions: release zip file */ void libaroma_zip_release( LIBAROMA_ZIP zip) { mzCloseZipArchive((ZipArchive *) zip); free(zip); } /* End of libaroma_zip_release */
int GUIAction::flash_zip(std::string filename, std::string pageName, const int simulate) { int ret_val = 0; DataManager::SetValue("ui_progress", 0); if (filename.empty()) { LOGE("No file specified.\n"); return -1; } // We're going to jump to this page first, like a loading page gui_changePage(pageName); int fd = -1; ZipArchive zip; if (mzOpenZipArchive(filename.c_str(), &zip)) { LOGE("Unable to open zip file.\n"); return -1; } // Check the zip to see if it has a custom installer theme const ZipEntry* twrp = mzFindZipEntry(&zip, "META-INF/teamwin/twrp.zip"); if (twrp != NULL) { unlink("/tmp/twrp.zip"); fd = creat("/tmp/twrp.zip", 0666); } if (fd >= 0 && twrp != NULL && mzExtractZipEntryToFile(&zip, twrp, fd) && !PageManager::LoadPackage("install", "/tmp/twrp.zip")) { mzCloseZipArchive(&zip); PageManager::SelectPackage("install"); gui_changePage("main"); } else { // In this case, we just use the default page mzCloseZipArchive(&zip); gui_changePage(pageName); } if (fd >= 0) close(fd); if (simulate) { simulate_progress_bar(); } else { ret_val = install_zip_package(filename.c_str()); // Now, check if we need to ensure TWRP remains installed... struct stat st; if (stat("/sbin/installTwrp", &st) == 0) { DataManager::SetValue("tw_operation", "Configuring TWRP"); DataManager::SetValue("tw_partition", ""); ui_print("Configuring TWRP...\n"); if (__system("/sbin/installTwrp reinstall") < 0) { ui_print("Unable to configure TWRP with this kernel.\n"); } } } // Done DataManager::SetValue("ui_progress", 100); DataManager::SetValue("ui_progress", 0); return ret_val; }
static int Run_Update_Binary(const char *path, ZipArchive *Zip, int* wipe_cache) { const ZipEntry* binary_location = mzFindZipEntry(Zip, ASSUMED_UPDATE_BINARY_NAME); string Temp_Binary = "/tmp/updater"; int binary_fd, ret_val, pipe_fd[2], status, zip_verify; char buffer[1024]; const char** args = (const char**)malloc(sizeof(char*) * 5); FILE* child_data; if (binary_location == NULL) { mzCloseZipArchive(Zip); return INSTALL_CORRUPT; } // Delete any existing updater if (TWFunc::Path_Exists(Temp_Binary) && unlink(Temp_Binary.c_str()) != 0) { LOGINFO("Unable to unlink '%s'\n", Temp_Binary.c_str()); } binary_fd = creat(Temp_Binary.c_str(), 0755); if (binary_fd < 0) { mzCloseZipArchive(Zip); LOGERR("Could not create file for updater extract in '%s'\n", Temp_Binary.c_str()); return INSTALL_ERROR; } ret_val = mzExtractZipEntryToFile(Zip, binary_location, binary_fd); close(binary_fd); if (!ret_val) { mzCloseZipArchive(Zip); LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME); return INSTALL_ERROR; } // If exists, extract file_contexts from the zip file const ZipEntry* selinx_contexts = mzFindZipEntry(Zip, "file_contexts"); if (selinx_contexts == NULL) { mzCloseZipArchive(Zip); LOGINFO("Zip does not contain SELinux file_contexts file in its root.\n"); } else { string output_filename = "/file_contexts"; LOGINFO("Zip contains SELinux file_contexts file in its root. Extracting to %s\n", output_filename.c_str()); // Delete any file_contexts if (TWFunc::Path_Exists(output_filename) && unlink(output_filename.c_str()) != 0) { LOGINFO("Unable to unlink '%s'\n", output_filename.c_str()); } int file_contexts_fd = creat(output_filename.c_str(), 0644); if (file_contexts_fd < 0) { mzCloseZipArchive(Zip); LOGERR("Could not extract file_contexts to '%s'\n", output_filename.c_str()); return INSTALL_ERROR; } ret_val = mzExtractZipEntryToFile(Zip, selinx_contexts, file_contexts_fd); close(file_contexts_fd); if (!ret_val) { mzCloseZipArchive(Zip); LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME); return INSTALL_ERROR; } } mzCloseZipArchive(Zip); pipe(pipe_fd); args[0] = Temp_Binary.c_str(); args[1] = EXPAND(RECOVERY_API_VERSION); char* temp = (char*)malloc(10); sprintf(temp, "%d", pipe_fd[1]); args[2] = temp; args[3] = (char*)path; args[4] = NULL; pid_t pid = fork(); if (pid == 0) { close(pipe_fd[0]); execv(Temp_Binary.c_str(), (char* const*)args); printf("E:Can't execute '%s'\n", Temp_Binary.c_str()); _exit(-1); } close(pipe_fd[1]); *wipe_cache = 0; DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify); child_data = fdopen(pipe_fd[0], "r"); while (fgets(buffer, sizeof(buffer), child_data) != NULL) { char* command = strtok(buffer, " \n"); if (command == NULL) { continue; } else if (strcmp(command, "progress") == 0) { char* fraction_char = strtok(NULL, " \n"); char* seconds_char = strtok(NULL, " \n"); float fraction_float = strtof(fraction_char, NULL); int seconds_float = strtol(seconds_char, NULL, 10); if (zip_verify) DataManager::ShowProgress(fraction_float * (1 - VERIFICATION_PROGRESS_FRACTION), seconds_float); else DataManager::ShowProgress(fraction_float, seconds_float); } else if (strcmp(command, "set_progress") == 0) { char* fraction_char = strtok(NULL, " \n"); float fraction_float = strtof(fraction_char, NULL); DataManager::SetProgress(fraction_float); } else if (strcmp(command, "ui_print") == 0) { char* display_value = strtok(NULL, "\n"); if (display_value) { gui_print("%s", display_value); } else { gui_print("\n"); } } else if (strcmp(command, "wipe_cache") == 0) { *wipe_cache = 1; } else if (strcmp(command, "clear_display") == 0) { // Do nothing, not supported by TWRP } else { LOGERR("unknown command [%s]\n", command); } } fclose(child_data); waitpid(pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGERR("Error executing updater binary in zip '%s'\n", path); 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; } 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; }
Value *FlashIfwiFn(const char *name, State * state, int argc, Expr * argv[]) { Value *ret = NULL; char *filename = NULL; int err, ifwi_bin_fd, dnx_bin_fd, i, num; char ifwi_name[128], dnx_name[128]; ZipArchive ifwi_za; const ZipEntry *dnx_entry, *ifwi_entry; unsigned char *file_buf = NULL; size_t file_size; if (ReadArgs(state, argv, 1, &filename) < 0) { return NULL; } if (filename == NULL || strlen(filename) == 0) { ErrorAbort(state, "filename argument to %s can't be empty", name); goto done; } err = file_read(filename, (void **)&file_buf, &file_size); if (err) { ErrorAbort(state, "Failed to open zip archive file %s\n", filename); goto done; } err = mzOpenZipArchive(file_buf, file_size, &ifwi_za); if (err) { ErrorAbort(state, "Failed to open zip archive\n"); goto done; } num = mzZipEntryCount(&ifwi_za); for (i = 0; i < num; i++) { ifwi_entry = mzGetZipEntryAt(&ifwi_za, i); if ((ifwi_entry->fileNameLen + 1) < sizeof(ifwi_name)) { strncpy(ifwi_name, ifwi_entry->fileName, ifwi_entry->fileNameLen); ifwi_name[ifwi_entry->fileNameLen] = '\0'; } else { ErrorAbort(state, "ifwi file name is too big. Size max is:%d.\n", sizeof(ifwi_name)); goto error; } if (strncmp(ifwi_name, IFWI_NAME, strlen(IFWI_NAME))) continue; if ((ifwi_bin_fd = open(IFWI_BIN_PATH, O_RDWR | O_TRUNC | O_CREAT, FILEMODE)) < 0) { ErrorAbort(state, "unable to create Extracted file:%s.\n", IFWI_BIN_PATH); goto error; } if ((dnx_bin_fd = open(DNX_BIN_PATH, O_RDWR | O_TRUNC | O_CREAT, FILEMODE)) < 0) { ErrorAbort(state, "unable to create Extracted file:%s.\n", IFWI_BIN_PATH); close(ifwi_bin_fd); goto error; } strcpy(dnx_name, "dnx_fwr"); strncat(dnx_name, &(ifwi_name[strlen(IFWI_NAME)]), sizeof(dnx_name) - strlen("dnx_fwr") - 1); dnx_entry = mzFindZipEntry(&ifwi_za, dnx_name); if (dnx_entry == NULL) { ErrorAbort(state, "Could not find DNX entry"); close(ifwi_bin_fd); close(dnx_bin_fd); goto error; } err = mzExtractZipEntryToFile(&ifwi_za, dnx_entry, dnx_bin_fd); if (!err) { ErrorAbort(state, "Failed to unzip %s\n", DNX_BIN_PATH); close(ifwi_bin_fd); close(dnx_bin_fd); goto error; } close(dnx_bin_fd); err = mzExtractZipEntryToFile(&ifwi_za, ifwi_entry, ifwi_bin_fd); if (!err) { ErrorAbort(state, "Failed to unzip %s\n", DNX_BIN_PATH); close(ifwi_bin_fd); goto error; } close(ifwi_bin_fd); int update_ifwi_file_scu_ipc(const char *dnx, const char *ifwi); update_ifwi_file_scu_ipc(DNX_BIN_PATH, IFWI_BIN_PATH); } ret = StringValue(strdup("t")); error: mzCloseZipArchive(&ifwi_za); done: free(file_buf); if (filename) free(filename); return ret; }
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; }
int main(int argc, char** argv) { // Various things log information to stdout or stderr more or less // at random (though we've tried to standardize on stdout). The // log file makes more sense if buffering is turned off so things // appear in the right order. setbuf(stdout, NULL); setbuf(stderr, NULL); if (argc != 4) { printf("unexpected number of arguments (%d)\n", argc); return 1; } char* version = argv[1]; if ((version[0] != '1' && version[0] != '2' && version[0] != '3') || version[1] != '\0') { // We support version 1, 2, or 3. printf("wrong updater binary API; expected 1, 2, or 3; " "got %s\n", argv[1]); return 2; } // Set up the pipe for sending commands back to the parent process. int fd = atoi(argv[2]); FILE* cmd_pipe = fdopen(fd, "wb"); setlinebuf(cmd_pipe); // Extract the script from the package. const char* package_filename = argv[3]; MemMapping map; if (sysMapFile(package_filename, &map) != 0) { printf("failed to map package %s\n", argv[3]); return 3; } ZipArchive za; int err; err = mzOpenZipArchive(map.addr, map.length, &za); if (err != 0) { printf("failed to open package %s: %s\n", argv[3], strerror(err)); return 3; } const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME); if (script_entry == NULL) { printf("failed to find %s in %s\n", SCRIPT_NAME, package_filename); return 4; } char* script = malloc(script_entry->uncompLen+1); if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) { printf("failed to read script from package\n"); return 5; } script[script_entry->uncompLen] = '\0'; const ZipEntry* file_contexts_entry = mzFindZipEntry(&za, SELINUX_CONTEXTS_ZIP); if (file_contexts_entry != NULL) { int file_contexts_fd = creat(SELINUX_CONTEXTS_TMP, 0644); if (file_contexts_fd < 0) { fprintf(stderr, "Could not extract %s to '%s'\n", SELINUX_CONTEXTS_ZIP, SELINUX_CONTEXTS_TMP); return 3; } int ret_val = mzExtractZipEntryToFile(&za, file_contexts_entry, file_contexts_fd); close(file_contexts_fd); if (!ret_val) { fprintf(stderr, "Could not extract '%s'\n", SELINUX_CONTEXTS_ZIP); return 3; } } // Configure edify's functions. RegisterBuiltins(); RegisterInstallFunctions(); RegisterBlockImageFunctions(); RegisterDeviceExtensions(); FinishRegistration(); // Parse the script. Expr* root; int error_count = 0; int error = parse_string(script, &root, &error_count); if (error != 0 || error_count > 0) { printf("%d parse errors\n", error_count); return 6; } if (access(SELINUX_CONTEXTS_TMP, R_OK) == 0) { struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, SELINUX_CONTEXTS_TMP } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); } else { struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); } if (!sehandle) { fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n"); } // Evaluate the parsed script. UpdaterInfo updater_info; updater_info.cmd_pipe = cmd_pipe; updater_info.package_zip = &za; updater_info.version = atoi(version); updater_info.package_zip_addr = map.addr; updater_info.package_zip_len = map.length; State state; state.cookie = &updater_info; state.script = script; state.errmsg = NULL; char* result = Evaluate(&state, root); if (result == NULL) { if (state.errmsg == NULL) { printf("script aborted (no error message)\n"); fprintf(cmd_pipe, "ui_print script aborted (no error message)\n"); } else { printf("script aborted: %s\n", state.errmsg); char* line = strtok(state.errmsg, "\n"); while (line) { fprintf(cmd_pipe, "ui_print %s\n", line); line = strtok(NULL, "\n"); } fprintf(cmd_pipe, "ui_print\n"); } free(state.errmsg); return 7; } else { fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result); free(result); } if (updater_info.package_zip) { mzCloseZipArchive(updater_info.package_zip); } sysReleaseMap(&map); free(script); return 0; }
int main(int argc, char** argv) { // Various things log information to stdout or stderr more or less // at random. The log file makes more sense if buffering is // turned off so things appear in the right order. setbuf(stdout, NULL); setbuf(stderr, NULL); if (argc != 4) { fprintf(stderr, "unexpected number of arguments (%d)\n", argc); return 1; } char* version = argv[1]; if ((version[0] != '1' && version[0] != '2' && version[0] != '3') || version[1] != '\0') { // We support version 1, 2, or 3. fprintf(stderr, "wrong updater binary API; expected 1, 2, or 3; " "got %s\n", argv[1]); //printf("Wrong updater binary API; expected 1, 2, or 3; we just got '%s' \n",argv[1]); return 2; } // Set up the pipe for sending commands back to the parent process. int fd = atoi(argv[2]); FILE* cmd_pipe = fdopen(fd, "wb"); setlinebuf(cmd_pipe); // Extract the script from the package. char* package_data = argv[3]; ZipArchive za; int err; err = mzOpenZipArchive(package_data, &za); if (err != 0) { fprintf(stderr, "failed to open package %s: %s\n", package_data, strerror(err)); return 3; } const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME); if (script_entry == NULL) { fprintf(stderr, "failed to find %s in %s\n", SCRIPT_NAME, package_data); return 4; } char* script = malloc(script_entry->uncompLen+1); if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) { fprintf(stderr, "failed to read script from package\n"); return 5; } script[script_entry->uncompLen] = '\0'; // Configure edify's functions. RegisterBuiltins(); RegisterInstallFunctions(); RegisterDeviceExtensions(); FinishRegistration(); // Parse the script. Expr* root; int error_count = 0; yy_scan_string(script); int error = yyparse(&root, &error_count); if (error != 0 || error_count > 0) { fprintf(stderr, "%d parse errors\n", error_count); return 6; } struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { fprintf(stderr, "Warning: No file_contexts\n"); // fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n"); } // Evaluate the parsed script. UpdaterInfo updater_info; updater_info.cmd_pipe = cmd_pipe; updater_info.package_zip = &za; updater_info.version = atoi(version); State state; state.cookie = &updater_info; state.script = script; state.errmsg = NULL; char* result = Evaluate(&state, root); if (result == NULL) { if (state.errmsg == NULL) { fprintf(stderr, "script aborted (no error message)\n"); fprintf(cmd_pipe, "ui_print script aborted (no error message)\n"); } else { fprintf(stderr, "script aborted: %s\n", state.errmsg); char* line = strtok(state.errmsg, "\n"); while (line) { fprintf(cmd_pipe, "ui_print %s\n", line); line = strtok(NULL, "\n"); } fprintf(cmd_pipe, "ui_print\n"); } free(state.errmsg); return 7; } else { fprintf(stderr, "script result was [%s]\n", result); free(result); } if (updater_info.package_zip) { mzCloseZipArchive(updater_info.package_zip); } free(script); return 0; }
//-- AROMA ZIP Close void az_close() { mzCloseZipArchive(&zip); }
Value *FlashIfwiOrBomFn(enum flash_option_type flash_option, const char *name, State * state, int argc, Expr * argv[]) { Value *ret = NULL; char *filename = NULL; int err, i, num, buffsize; char ifwi_name[128]; ZipArchive ifwi_za; const ZipEntry *ifwi_entry; unsigned char *buffer; unsigned char *file_buf = NULL; size_t file_size; #ifdef TEE_FRAMEWORK char bom_token_name[128]; const ZipEntry *bom_token_entry; int bom_token_buffsize; unsigned char *bom_token_buffer; #endif if (ReadArgs(state, argv, 1, &filename) < 0) { return NULL; } if (filename == NULL || strlen(filename) == 0) { ErrorAbort(state, "filename argument to %s can't be empty", name); goto done; } err = file_read(filename, (void **)&file_buf, &file_size); if (err) { ErrorAbort(state, "Failed to open zip archive file %s\n", filename); goto done; } err = mzOpenZipArchive(file_buf, file_size, &ifwi_za); if (err) { ErrorAbort(state, "Failed to open zip archive\n"); goto done; } num = mzZipEntryCount(&ifwi_za); for (i = 0; i < num; i++) { ifwi_entry = mzGetZipEntryAt(&ifwi_za, i); if ((ifwi_entry->fileNameLen + 1) < sizeof(ifwi_name)) { strncpy(ifwi_name, ifwi_entry->fileName, ifwi_entry->fileNameLen); ifwi_name[ifwi_entry->fileNameLen] = '\0'; } else { ErrorAbort(state, "ifwi file name is too big. Size max is:%zd.\n", sizeof(ifwi_name)); goto error; } if (strncmp(ifwi_name, IFWI_NAME, strlen(IFWI_NAME))) continue; buffsize = mzGetZipEntryUncompLen(ifwi_entry); if (buffsize <= 0) { ErrorAbort(state, "Bad ifwi_entry size : %d.\n", buffsize); goto error; } buffer = (unsigned char *)malloc(sizeof(unsigned char) * buffsize); if (buffer == NULL) { ErrorAbort(state, "Unable to alloc ifwi buffer of %d bytes.\n", buffsize); goto error; } err = mzExtractZipEntryToBuffer(&ifwi_za, ifwi_entry, buffer); if (!err) { ErrorAbort(state, "Failed to unzip %s\n", IFWI_BIN_PATH); free(buffer); goto error; } if (check_ifwi_file(buffer, buffsize) < 1) { free(buffer); continue; } if (flash_option == FLASH_BOM_TOKEN_BINARY) { #ifdef TEE_FRAMEWORK strcpy(bom_token_name, BOM_TOKEN_NAME); strncat(bom_token_name, &(ifwi_name[strlen(IFWI_NAME)]), sizeof(bom_token_name) - strlen(BOM_TOKEN_NAME) - 1); bom_token_entry = mzFindZipEntry(&ifwi_za, bom_token_name); if (bom_token_entry != NULL) { bom_token_buffsize = mzGetZipEntryUncompLen(bom_token_entry); if (bom_token_buffsize <= 0) { ErrorAbort(state, "Bad bom_token_entry size : %d.\n", bom_token_buffsize); free(buffer); goto error; } bom_token_buffer = (unsigned char *)malloc(sizeof(unsigned char) * bom_token_buffsize); if (bom_token_buffer == NULL) { ErrorAbort(state, "Unable to alloc bom token buffer of %d bytes.\n", bom_token_buffsize); free(buffer); goto error; } err = mzExtractZipEntryToBuffer(&ifwi_za, bom_token_entry, bom_token_buffer); if (!err) { ErrorAbort(state, "Failed to unzip %s.\n", IFWI_BIN_PATH); free(bom_token_buffer); free(buffer); goto error; } if (write_token(bom_token_buffer, bom_token_buffsize) == 0) { printf("BOM token written\n"); } else { printf("Unable to write BOM token.\n"); cancel_update(0, NULL); free(bom_token_buffer); free(buffer); ret = StringValue(strdup("fail")); goto error; } free(bom_token_buffer); } #else printf("BOM token flashing not supported\n"); #endif } else if (flash_option == FLASH_IFWI_BINARY) { printf("Flashing IFWI\n"); update_ifwi_file(buffer, buffsize); } else { ErrorAbort(state, "Don't know what to do with option %d\n", flash_option); free(buffer); goto error; } free(buffer); } ret = StringValue(strdup("t")); error: mzCloseZipArchive(&ifwi_za); done: free(file_buf); if (filename) free(filename); return ret; }
// 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; }
Value* UpdateFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 7) { return ErrorAbort(state, "%s() expects 7 args, got %d", name, argc); } char* type = strrchr(name, '_'); if (type == NULL || *(type+1) == '\0') { return ErrorAbort(state, "%s() couldn't get type from function name", name); } ++type; Value* image; Value* width_string; Value* height_string; Value* bpp_string; Value* busy; Value* fail; Value* expected_sha1_string; if (ReadValueArgs(state, argv, 7, &image, &width_string, &height_string, &bpp_string, &busy, &fail, &expected_sha1_string) < 0) { return NULL; } // close the package ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; mzCloseZipArchive(za); ((UpdaterInfo*)(state->cookie))->package_zip = NULL; // Try to unmount /cache. If we fail (because we're running in an // older recovery that still has the package file open), try to // remount it read-only. If that fails, abort. sync(); scan_mounted_volumes(); MountedVolume* vol = find_mounted_volume_by_mount_point("/cache"); int result = unmount_mounted_volume(vol); if (result != 0) { printf("%s(): failed to unmount cache (%d: %s)\n", name, result, strerror(errno)); result = remount_read_only(vol); if (result != 0) { printf("%s(): failed to remount cache (%d: %s)\n", name, result, strerror(errno)); return StringValue(strdup("")); } else { printf("%s(): remounted cache\n", name); } sync(); } else { printf("%s(): unmounted cache\n", name); } int width = 0, height = 0, bpp = 0; if (width_string->type != VAL_STRING || (width = strtol(width_string->data, NULL, 10)) == 0) { printf("%s(): bad width argument", name); } if (height_string->type != VAL_STRING || (height = strtol(height_string->data, NULL, 10)) == 0) { printf("%s(): bad height argument", name); } if (bpp_string->type != VAL_STRING || (bpp = strtol(bpp_string->data, NULL, 10)) == 0) { printf("%s(): bad bpp argument", name); } if (image->type != VAL_BLOB) { printf("image argument is not blob (is type %d)\n", image->type); goto done; } uint8_t expected_sha1[SHA_DIGEST_SIZE]; char* data = expected_sha1_string->data; if (expected_sha1_string->type != VAL_STRING || strlen(data) != SHA_DIGEST_SIZE*2) { printf("%s(): bad expected_sha1 argument", name); goto done; } printf("expected sha1 is: "); int i; for (i = 0; i < SHA_DIGEST_SIZE; ++i) { char temp = data[i*2+2]; data[i*2+2] = '\0'; expected_sha1[i] = strtol(data+i*2, NULL, 16); data[i*2+2] = temp; printf("%02x", expected_sha1[i]); } printf("\n"); install_firmware_update( type, image->data, image->size, width, height, bpp, busy->size > 0 ? busy->data : NULL, fail->size > 0 ? fail->data : NULL, "/tmp/recovery.log", expected_sha1); printf("%s: install_firmware_update returned!\n", name); done: FreeValue(image); FreeValue(width_string); FreeValue(height_string); FreeValue(bpp_string); FreeValue(busy); FreeValue(fail); // install_firmware_update should reboot. If it returns, it failed. return StringValue(strdup("")); }