bool MROMInstaller::extractTarballs(const std::string& base) { system("rm -r /tmp/tarballs; mkdir /tmp/tarballs"); if(!hasEntry("rom")) { gui_print("Skippping tarball extractions - no rom folder in the ZIP file\n"); return true; } bool res = false; const MultiROM::baseFolders& folders = MultiROM::getBaseFolders(); MultiROM::baseFolders::const_iterator itr; for(itr = folders.begin(); itr != folders.end(); ++itr) { if(!extractBase(base, itr->first)) { gui_print("Failed to extract base %s\n", itr->first.c_str()); goto exit; } } res = true; exit: system("rm -r /tmp/tarballs"); return res; }
extern "C" int TWinstall_zip(const char* path, int* wipe_cache) { int ret_val, zip_verify, md5_return, key_count; twrpDigest md5sum; string strpath = path; ZipArchive Zip; gui_print("Installing '%s'...\nChecking for MD5 file...\n", path); md5sum.setfn(strpath); md5_return = md5sum.verify_md5digest(); if (md5_return == -2) { // MD5 did not match. LOGERR("Zip MD5 does not match.\nUnable to install zip.\n"); return INSTALL_CORRUPT; } else if (md5_return == -1) { gui_print("Skipping MD5 check: no MD5 file found.\n"); } else if (md5_return == 0) gui_print("Zip MD5 matched.\n"); // MD5 found and matched. DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify); DataManager::SetProgress(0); if (zip_verify) { gui_print("Verifying zip signature...\n"); ret_val = verify_file(path); if (ret_val != VERIFY_SUCCESS) { LOGERR("Zip signature verification failed: %i\n", ret_val); return -1; } } ret_val = mzOpenZipArchive(path, &Zip); if (ret_val != 0) { LOGERR("Zip file is corrupt!\n", path); return INSTALL_CORRUPT; } return Run_Update_Binary(path, &Zip, wipe_cache); }
int GUIAction::flash(std::string arg) { int i, ret_val = 0, wipe_cache = 0; // We're going to jump to this page first, like a loading page gui_changePage(arg); for (i=0; i<zip_queue_index; i++) { operation_start("Flashing"); DataManager::SetValue("tw_filename", zip_queue[i]); DataManager::SetValue(TW_ZIP_INDEX, (i + 1)); TWFunc::SetPerformanceMode(true); ret_val = flash_zip(zip_queue[i], &wipe_cache); TWFunc::SetPerformanceMode(false); if (ret_val != 0) { gui_print("Error flashing zip '%s'\n", zip_queue[i].c_str()); ret_val = 1; break; } } zip_queue_index = 0; if (wipe_cache) { gui_print("One or more zip requested a cache wipe\nWiping cache now.\n"); PartitionManager.Wipe_By_Path("/cache"); } reinject_after_flash(); PartitionManager.Update_System_Details(); operation_end(ret_val); DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index); return 0; }
bool MROMInstaller::runScripts(const std::string& dir, const std::string& base, const std::string& root) { system("rm -r /tmp/script; mkdir /tmp/script"); if(!hasEntry(dir)) { LOGI("Skippping scripts in %s, not in the ZIP\n", dir.c_str()); return true; } if(!extractDir(dir, "/tmp/script/")) return false; if(system("ls /tmp/script/*.sh") == 0) { system("chmod -R 777 /tmp/script/*"); gui_print("Running %s scripts...\n", dir.c_str()); char cmd[512]; sprintf(cmd, "sh -c 'for x in $(ls /tmp/script/*.sh); do echo Running script $x; sh $x %s %s || exit 1; done'", base.c_str(), root.c_str()); if(system(cmd) != 0) { system("rm -r /tmp/script/"); gui_print("One of the ROM scripts returned error status!"); return false; } } else LOGI("Skipping folder %s, no bash scripts\n", dir.c_str()); system("rm -r /tmp/script"); return true; }
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::checkFreeSpace(const std::string& base, bool images) { struct statvfs s; int res = statvfs(base.c_str(), &s); if(res < 0) { gui_print("Check for free space failed: %s %d %d %s!\n", base.c_str(), res, errno, strerror(errno)); return false; } int free = (s.f_bavail * (s.f_bsize/1024) ) / 1024; int req = 0; const MultiROM::baseFolders& folders = MultiROM::getBaseFolders(); MultiROM::baseFolders::const_iterator itr; for(itr = folders.begin(); itr != folders.end(); ++itr) { if(images) req += itr->second.size; else req += itr->second.min_size; } gui_print("Free space check: Required: %d MB, free: %d MB\n", req, free); if(free < req) LOGERR("Not enough free space!\n"); return free >= req; }
void TWFunc::htc_dumlock_reflash_recovery_to_boot(void) { if (!PartitionManager.Mount_By_Path("/sdcard", true)) return; gui_print("Reflashing recovery to boot...\n"); Exec_Cmd("htcdumlock recovery noreboot"); gui_print("Recovery is flashed to boot.\n"); }
void TWFunc::htc_dumlock_restore_original_boot(void) { if (!PartitionManager.Mount_By_Path("/sdcard", true)) return; gui_print("Restoring original boot...\n"); Exec_Cmd("htcdumlock restore"); gui_print("Original boot restored.\n"); }
void TWFunc::check_and_run_script(const char* script_file, const char* display_name) { // Check for and run startup script if script exists struct stat st; if (stat(script_file, &st) == 0) { gui_print("Running %s script...\n", display_name); chmod(script_file, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); TWFunc::Exec_Cmd(script_file); gui_print("\nFinished running %s script.\n", display_name); } }
extern "C" int TWinstall_zip(const char* path, int* wipe_cache) { int ret_val, zip_verify = 1, md5_return, key_count; twrpDigest md5sum; string strpath = path; ZipArchive Zip; if (strcmp(path, "error") == 0) { LOGERR("Failed to get adb sideload file: '%s'\n", path); return INSTALL_CORRUPT; } gui_print("Installing '%s'...\n", path); if (strlen(path) < 9 || strncmp(path, "/sideload", 9) != 0) { gui_print("Checking for MD5 file...\n"); md5sum.setfn(strpath); md5_return = md5sum.verify_md5digest(); if (md5_return == -2) { // md5 did not match LOGERR("Aborting zip install\n"); return INSTALL_CORRUPT; } } #ifndef TW_OEM_BUILD DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify); #endif DataManager::SetProgress(0); MemMapping map; if (sysMapFile(path, &map) != 0) { LOGERR("Failed to sysMapFile '%s'\n", path); return -1; } if (zip_verify) { gui_print("Verifying zip signature...\n"); ret_val = verify_file(map.addr, map.length); if (ret_val != VERIFY_SUCCESS) { LOGERR("Zip signature verification failed: %i\n", ret_val); sysReleaseMap(&map); return -1; } else { gui_print("Zip signature verified successfully.\n"); } } ret_val = mzOpenZipArchive(map.addr, map.length, &Zip); if (ret_val != 0) { LOGERR("Zip file is corrupt!\n", path); sysReleaseMap(&map); return INSTALL_CORRUPT; } ret_val = Run_Update_Binary(path, &Zip, wipe_cache); sysReleaseMap(&map); return ret_val; }
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 GUIAction::unmount(std::string arg) { if (arg == "usb") { if (!simulate) PartitionManager.usb_storage_disable(); else gui_print("Simulating actions...\n"); DataManager::SetValue(TW_ACTION_BUSY, 0); } else if (!simulate) { PartitionManager.UnMount_By_Path(arg, true); } else gui_print("Simulating actions...\n"); return 0; }
int GUIAction::adbsideload(std::string arg) { operation_start("Sideload"); if (simulate) { simulate_progress_bar(); operation_end(0); } else { gui_print("Starting ADB sideload feature...\n"); bool mtp_was_enabled = TWFunc::Toggle_MTP(false); // wait for the adb connection int ret = apply_from_adb("/", &sideload_child_pid); DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui now that the zip install is going to start if (ret != 0) { if (ret == -2) gui_print("You need adb 1.0.32 or newer to sideload to this device.\n"); ret = 1; // failure } else { int wipe_cache = 0; int wipe_dalvik = 0; DataManager::GetValue("tw_wipe_dalvik", wipe_dalvik); if (TWinstall_zip(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache) == 0) { if (wipe_cache || DataManager::GetIntValue("tw_wipe_cache")) PartitionManager.Wipe_By_Path("/cache"); if (wipe_dalvik) PartitionManager.Wipe_Dalvik_Cache(); } else { ret = 1; // failure } } if (sideload_child_pid) { LOGINFO("Signaling child sideload process to exit.\n"); struct stat st; // Calling stat() on this magic filename signals the minadbd // subprocess to shut down. stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st); int status; LOGINFO("Waiting for child sideload process to exit.\n"); waitpid(sideload_child_pid, &status, 0); } property_set("ctl.start", "adbd"); TWFunc::Toggle_MTP(mtp_was_enabled); reinject_after_flash(); operation_end(ret); } return 0; }
int GUIAction::reinjecttwrp(std::string arg) { int op_status = 0; operation_start("ReinjectTWRP"); gui_print("Injecting TWRP into boot image...\n"); if (simulate) { simulate_progress_bar(); } else { TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash"); gui_print("TWRP injection complete.\n"); } operation_end(op_status); return 0; }
int GUIAction::mount(std::string arg) { if (arg == "usb") { DataManager::SetValue(TW_ACTION_BUSY, 1); if (!simulate) PartitionManager.usb_storage_enable(); else gui_print("Simulating actions...\n"); } else if (!simulate) { PartitionManager.Mount_By_Path(arg, true); PartitionManager.Add_MTP_Storage(arg); } else gui_print("Simulating actions...\n"); return 0; }
void GUIAction::simulate_progress_bar(void) { gui_print("Simulating actions...\n"); for (int i = 0; i < 5; i++) { if (PartitionManager.stop_backup.get_value()) { DataManager::SetValue("tw_cancel_backup", 1); gui_print("Backup Canceled.\n"); DataManager::SetValue("ui_progress", 0); PartitionManager.stop_backup.set_value(0); return; } usleep(500000); DataManager::SetValue("ui_progress", i * 20); } }
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; }
void ScreenRecoveryUI::Print(const char *fmt, ...) { char buf[256]; va_list ap; va_start(ap, fmt); vsnprintf(buf, 256, fmt, ap); va_end(ap); gui_print("%s", buf); return; fputs(buf, stdout); // This can get called before ui_init(), so be careful. pthread_mutex_lock(&updateMutex); if (text_rows > 0 && text_cols > 0) { char *ptr; for (ptr = buf; *ptr != '\0'; ++ptr) { if (*ptr == '\n' || text_col >= text_cols) { text[text_row][text_col] = '\0'; text_col = 0; text_row = (text_row + 1) % text_rows; if (text_row == text_top) text_top = (text_top + 1) % text_rows; } if (*ptr != '\n') text[text_row][text_col++] = *ptr; } text[text_row][text_col] = '\0'; update_screen_locked(); } pthread_mutex_unlock(&updateMutex); }
void GUIAction::reinject_after_flash() { if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) { gui_print("Injecting TWRP into boot image...\n"); if (simulate) { simulate_progress_bar(); } else { TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot"); if (Boot == NULL || Boot->Current_File_System != "emmc") TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash"); else { string injectcmd = "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + Boot->Actual_Block_Device; TWFunc::Exec_Cmd(injectcmd); } gui_print("TWRP injection complete.\n"); } } }
int GUIAction::cancelzip(std::string arg) { if (zip_queue_index <= 0) { gui_print("Minimum zip queue reached!\n"); return 0; } else { zip_queue_index--; DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index); } return 0; }
int GUIAction::openrecoveryscript(std::string arg) { int op_status = 1; operation_start("OpenRecoveryScript"); if (simulate) { simulate_progress_bar(); operation_end(0); } else { // Check for the SCRIPT_FILE_TMP first as these are AOSP recovery commands // that we converted to ORS commands during boot in recovery.cpp. // Run those first. int reboot = 0; if (TWFunc::Path_Exists(SCRIPT_FILE_TMP)) { gui_print("Processing AOSP recovery commands...\n"); if (OpenRecoveryScript::run_script_file() == 0) { reboot = 1; op_status = 0; } } // Check for the ORS file in /cache and attempt to run those commands. if (OpenRecoveryScript::check_for_script_file()) { gui_print("Processing OpenRecoveryScript file...\n"); if (OpenRecoveryScript::run_script_file() == 0) { reboot = 1; op_status = 0; } } if (reboot) { // Disable stock recovery reflashing TWFunc::Disable_Stock_Recovery_Replace(); usleep(2000000); // Sleep for 2 seconds before rebooting TWFunc::tw_reboot(rb_system); usleep(5000000); // Sleep for 5 seconds to allow reboot to occur } else { DataManager::SetValue("tw_page_done", 1); } operation_end(op_status); } return 0; }
bool MROMInstaller::extractTarball(const std::string& base, const std::string& name, const std::string& tarball) { gui_print("Extrating tarball %s...\n", tarball.c_str()); system("rm /tmp/tarballs/rom.tar.gz"); if(!extractFile(tarball, "/tmp/tarballs/rom.tar.gz")) return false; bool res = true; char cmd[256]; sprintf(cmd, "gnutar --numeric-owner --overwrite -C \"%s\" -xf /tmp/tarballs/rom.tar.gz", (base + "/" + name).c_str()); if(system(cmd) != 0) { gui_print("Failed to extract tarball %s for folder %s!\n", tarball.c_str(), name.c_str()); res = false; } system("rm /tmp/tarballs/rom.tar.gz"); return res; }
int GUIAction::queuezip(std::string arg) { if (zip_queue_index >= 10) { gui_print("Maximum zip queue reached!\n"); return 0; } DataManager::GetValue("tw_filename", zip_queue[zip_queue_index]); if (strlen(zip_queue[zip_queue_index].c_str()) > 0) { zip_queue_index++; DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index); } return 0; }
int GUIAction::restoredefaultsettings(std::string arg) { operation_start("Restore Defaults"); if (simulate) // Simulated so that people don't accidently wipe out the "simulation is on" setting gui_print("Simulating actions...\n"); else { DataManager::ResetDefaults(); PartitionManager.Update_System_Details(); PartitionManager.Mount_Current_Storage(true); } operation_end(0); return 0; }
int GUIAction::flash_zip(std::string filename, int* wipe_cache) { int ret_val = 0; DataManager::SetValue("ui_progress", 0); if (filename.empty()) { LOGERR("No file specified.\n"); return -1; } if (!PartitionManager.Mount_By_Path(filename, true)) return -1; if (simulate) { simulate_progress_bar(); } else { ret_val = TWinstall_zip(filename.c_str(), wipe_cache); // 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", ""); gui_print("Configuring TWRP...\n"); if (TWFunc::Exec_Cmd("/sbin/installTwrp reinstall") < 0) { gui_print("Unable to configure TWRP with this kernel.\n"); } } } // Done DataManager::SetValue("ui_progress", 100); DataManager::SetValue("ui_progress", 0); return ret_val; }
int GUIAction::nandroid(std::string arg) { if (simulate) { PartitionManager.stop_backup.set_value(0); DataManager::SetValue("tw_partition", "Simulation"); simulate_progress_bar(); operation_end(0); } else { operation_start("Nandroid"); int ret = 0; if (arg == "backup") { string Backup_Name; DataManager::GetValue(TW_BACKUP_NAME, Backup_Name); if (Backup_Name == "(Auto Generate)" || Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name == "(" || PartitionManager.Check_Backup_Name(true) == 0) { ret = PartitionManager.Run_Backup(); } else { operation_end(1); return -1; } DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)"); } else if (arg == "restore") { string Restore_Name; DataManager::GetValue("tw_restore", Restore_Name); ret = PartitionManager.Run_Restore(Restore_Name); } else { operation_end(1); return -1; } DataManager::SetValue("tw_encrypt_backup", 0); if (!PartitionManager.stop_backup.get_value()) { if (ret == false) ret = 1; // 1 for failure else ret = 0; // 0 for success DataManager::SetValue("tw_cancel_backup", 0); } else { DataManager::SetValue("tw_cancel_backup", 1); gui_print("Backup Canceled.\n"); ret = 0; } operation_end(ret); return ret; } return 0; }
int GUIAction::screenshot(std::string arg) { time_t tm; char path[256]; int path_len; uid_t uid = -1; gid_t gid = -1; struct passwd *pwd = getpwnam("media_rw"); if(pwd) { uid = pwd->pw_uid; gid = pwd->pw_gid; } const std::string storage = DataManager::GetCurrentStoragePath(); if(PartitionManager.Is_Mounted_By_Path(storage)) { snprintf(path, sizeof(path), "%s/Pictures/Screenshots/", storage.c_str()); } else { strcpy(path, "/tmp/"); } if(!TWFunc::Create_Dir_Recursive(path, 0666, uid, gid)) return 0; tm = time(NULL); path_len = strlen(path); // Screenshot_2014-01-01-18-21-38.png strftime(path+path_len, sizeof(path)-path_len, "Screenshot_%Y-%m-%d-%H-%M-%S.png", localtime(&tm)); int res = gr_save_screenshot(path); if(res == 0) { chmod(path, 0666); chown(path, uid, gid); gui_print("Screenshot was saved to %s\n", path); // blink to notify that the screenshow was taken gr_color(255, 255, 255, 255); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); gr_flip(); gui_forceRender(); } else { LOGERR("Failed to take a screenshot!\n"); } return 0; }
int GUIAction::copylog(std::string arg) { operation_start("Copy Log"); if (!simulate) { string dst; PartitionManager.Mount_Current_Storage(true); dst = DataManager::GetCurrentStoragePath() + "/recovery.log"; TWFunc::copy_file("/tmp/recovery.log", dst.c_str(), 0755); tw_set_default_metadata(dst.c_str()); sync(); gui_print("Copied recovery log to %s.\n", DataManager::GetCurrentStoragePath().c_str()); } else simulate_progress_bar(); operation_end(0); return 0; }
int TWFunc::Exec_Cmd_Show_Output(const string& cmd) { FILE* exec; char buffer[130]; int ret = 0; exec = __popen(cmd.c_str(), "r"); if (!exec) return -1; while(!feof(exec)) { memset(buffer, 0, sizeof(buffer)); if (fgets(buffer, 128, exec) != NULL) { buffer[128] = '\n'; buffer[129] = NULL; gui_print(buffer); } } ret = __pclose(exec); return ret; }
int GUIAction::partitionsd(std::string arg) { operation_start("Partition SD Card"); int ret_val = 0; if (simulate) { simulate_progress_bar(); } else { int allow_partition; DataManager::GetValue(TW_ALLOW_PARTITION_SDCARD, allow_partition); if (allow_partition == 0) { gui_print("This device does not have a real SD Card!\nAborting!\n"); } else { if (!PartitionManager.Partition_SDCard()) ret_val = 1; // failed } } operation_end(ret_val); return 0; }