int GUIAction::mountsystemtoggle(std::string arg) { int op_status = 0; bool remount_system = PartitionManager.Is_Mounted_By_Path("/system"); operation_start("Toggle System Mount"); if (!PartitionManager.UnMount_By_Path("/system", true)) { op_status = 1; // fail } else { TWPartition* Part = PartitionManager.Find_Partition_By_Path("/system"); if (Part) { if (arg == "0") { DataManager::SetValue("tw_mount_system_ro", 0); Part->Change_Mount_Read_Only(false); } else { DataManager::SetValue("tw_mount_system_ro", 1); Part->Change_Mount_Read_Only(true); } if (remount_system) { Part->Mount(true); } op_status = 0; // success } else { op_status = 1; // fail } } operation_end(op_status); return 0; }
int GUIAction::checkpartitionlifetimewrites(std::string arg) { int op_status = 0; TWPartition* sys = PartitionManager.Find_Partition_By_Path(arg); operation_start("Check Partition Lifetime Writes"); if (sys) { if (sys->Check_Lifetime_Writes() != 0) DataManager::SetValue("tw_lifetime_writes", 1); else DataManager::SetValue("tw_lifetime_writes", 0); op_status = 0; // success } else { DataManager::SetValue("tw_lifetime_writes", 1); op_status = 1; // fail } operation_end(op_status); return 0; }
int GUIPartitionList::NotifyTouch(TOUCH_STATE state, int x, int y) { if(!isConditionTrue()) return -1; static int lastY = 0, last2Y = 0; int selection = 0; switch (state) { case TOUCH_START: if (scrollingSpeed != 0) startSelection = -1; else startSelection = GetSelection(x,y); isHighlighted = (startSelection > -1); if (isHighlighted) mUpdate = 1; startY = lastY = last2Y = y; scrollingSpeed = 0; break; case TOUCH_DRAG: // Check if we dragged out of the selection window if (GetSelection(x, y) == -1) { last2Y = lastY = 0; if (isHighlighted) { isHighlighted = false; mUpdate = 1; } break; } // Fast scroll if(mFastScrollRectX != -1 && x >= mRenderX + mRenderW - mFastScrollW) { int pct = ((y-mRenderY-mHeaderH)*100)/(mRenderH-mHeaderH); int totalSize = mList.size(); int lines = (mRenderH - mHeaderH) / (actualLineHeight); float l = float((totalSize-lines)*pct)/100; if(l + lines >= totalSize) { mStart = totalSize - lines; scrollingY = 0; } else { mStart = l; scrollingY = -(l - int(l))*actualLineHeight; } startSelection = -1; mUpdate = 1; scrollingSpeed = 0; isHighlighted = false; break; } // Provide some debounce on initial touches if (startSelection != -1 && abs(y - startY) < touchDebounce) { isHighlighted = true; mUpdate = 1; break; } isHighlighted = false; last2Y = lastY; lastY = y; startSelection = -1; // Handle scrolling scrollingY += y - startY; startY = y; while(mStart && scrollingY > 0) { mStart--; scrollingY -= actualLineHeight; } if (mStart == 0 && scrollingY > 0) scrollingY = 0; { int totalSize = mList.size(); int lines = (mRenderH - mHeaderH) / (actualLineHeight); if (totalSize > lines) { int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight); bottom_offset -= actualLineHeight; while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) { mStart++; scrollingY += actualLineHeight; } if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) { mStart = totalSize - lines - 1; scrollingY = bottom_offset; } else if (mStart + lines >= totalSize && scrollingY < 0) { mStart = totalSize - lines; scrollingY = 0; } } else scrollingY = 0; } mUpdate = 1; break; case TOUCH_RELEASE: isHighlighted = false; if (startSelection >= 0) { // We've selected an item! int listSize = mList.size(); int selectY = scrollingY, actualSelection = mStart; // Move the selection to the proper place in the array while (selectY + actualLineHeight < startSelection) { selectY += actualLineHeight; actualSelection++; } if (actualSelection < listSize && ListType == "mount") { DataManager::Vibrate("tw_button_vibrate"); if (!mList.at(actualSelection).selected) { if (PartitionManager.Mount_By_Path(mList.at(actualSelection).Mount_Point, true)) { mList.at(actualSelection).selected = 1; mUpdate = 1; } } else { if (PartitionManager.UnMount_By_Path(mList.at(actualSelection).Mount_Point, true)) { mList.at(actualSelection).selected = 0; mUpdate = 1; } } } else if (actualSelection < listSize && !mVariable.empty()) { DataManager::Vibrate("tw_button_vibrate"); if (ListType == "storage") { int i; std::string str = mList.at(actualSelection).Mount_Point; bool update_size = false; TWPartition* Part = PartitionManager.Find_Partition_By_Path(str); if (Part == NULL) { LOGERR("Unable to locate partition for '%s'\n", str.c_str()); return 0; } if (!Part->Is_Mounted() && Part->Removable) update_size = true; if (!Part->Mount(true)) { // Do Nothing } else if (update_size && !Part->Update_Size(true)) { // Do Nothing } else { for (i=0; i<listSize; i++) mList.at(i).selected = 0; if (update_size) { char free_space[255]; sprintf(free_space, "%llu", Part->Free / 1024 / 1024); mList.at(actualSelection).Display_Name = Part->Storage_Name + " ("; mList.at(actualSelection).Display_Name += free_space; mList.at(actualSelection).Display_Name += "MB)"; } mList.at(actualSelection).selected = 1; mUpdate = 1; DataManager::SetValue(mVariable, str); } } else { if (mList.at(actualSelection).selected) mList.at(actualSelection).selected = 0; else mList.at(actualSelection).selected = 1; int i; string variablelist; for (i=0; i<listSize; i++) { if (mList.at(i).selected) { variablelist += mList.at(i).Mount_Point + ";"; } } mUpdate = 1; if (selectedList.empty()) DataManager::SetValue(mVariable, variablelist); else DataManager::SetValue(selectedList, variablelist); } } } else { // This is for kinetic scrolling scrollingSpeed = lastY - last2Y; if (abs(scrollingSpeed) > SCROLLING_FLOOR) scrollingSpeed *= SCROLLING_MULTIPLIER; else scrollingSpeed = 0; } case TOUCH_REPEAT: case TOUCH_HOLD: break; } return 0; }
int GUIAction::getpartitiondetails(std::string arg) { string Wipe_List, wipe_path; int count = 0; DataManager::GetValue("tw_wipe_list", Wipe_List); LOGINFO("getpartitiondetails list '%s'\n", Wipe_List.c_str()); if (!Wipe_List.empty()) { size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos); while (end_pos != string::npos && start_pos < Wipe_List.size()) { wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos); LOGINFO("getpartitiondetails wipe_path '%s'\n", wipe_path.c_str()); if (wipe_path == "/and-sec" || wipe_path == "DALVIK" || wipe_path == "INTERNAL") { // Do nothing } else { DataManager::SetValue("tw_partition_path", wipe_path); break; } start_pos = end_pos + 1; end_pos = Wipe_List.find(";", start_pos); } if (!wipe_path.empty()) { TWPartition* Part = PartitionManager.Find_Partition_By_Path(wipe_path); if (Part) { unsigned long long mb = 1048576; DataManager::SetValue("tw_partition_name", Part->Display_Name); DataManager::SetValue("tw_partition_mount_point", Part->Mount_Point); DataManager::SetValue("tw_partition_file_system", Part->Current_File_System); DataManager::SetValue("tw_partition_size", Part->Size / mb); DataManager::SetValue("tw_partition_used", Part->Used / mb); DataManager::SetValue("tw_partition_free", Part->Free / mb); DataManager::SetValue("tw_partition_backup_size", Part->Backup_Size / mb); DataManager::SetValue("tw_partition_removable", Part->Removable); DataManager::SetValue("tw_partition_is_present", Part->Is_Present); if (Part->Can_Repair()) DataManager::SetValue("tw_partition_can_repair", 1); else DataManager::SetValue("tw_partition_can_repair", 0); if (Part->Can_Resize()) DataManager::SetValue("tw_partition_can_resize", 1); else DataManager::SetValue("tw_partition_can_resize", 0); if (TWFunc::Path_Exists("/sbin/mkdosfs")) DataManager::SetValue("tw_partition_vfat", 1); else DataManager::SetValue("tw_partition_vfat", 0); if (TWFunc::Path_Exists("/sbin/mkfs.exfat")) DataManager::SetValue("tw_partition_exfat", 1); else DataManager::SetValue("tw_partition_exfat", 0); if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) DataManager::SetValue("tw_partition_f2fs", 1); else DataManager::SetValue("tw_partition_f2fs", 0); if (TWFunc::Path_Exists("/sbin/mke2fs")) DataManager::SetValue("tw_partition_ext", 1); else DataManager::SetValue("tw_partition_ext", 0); return 0; } else { LOGERR("Unable to locate partition: '%s'\n", wipe_path.c_str()); } } } DataManager::SetValue("tw_partition_name", ""); DataManager::SetValue("tw_partition_file_system", ""); return 0; }
int main(int argc, char **argv) { // Recovery needs to install world-readable files, so clear umask // set by init umask(0); Log_Offset = 0; // Set up temporary log file (/tmp/recovery.log) freopen(TMP_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TMP_LOG_FILE, "a", stderr); setbuf(stderr, NULL); signal(SIGPIPE, SIG_IGN); // Handle ADB sideload if (argc == 3 && strcmp(argv[1], "--adbd") == 0) { property_set("ctl.stop", "adbd"); adb_main(argv[2]); return 0; } #ifdef RECOVERY_SDCARD_ON_DATA datamedia = true; #endif char crash_prop_val[PROPERTY_VALUE_MAX]; int crash_counter; property_get("twrp.crash_counter", crash_prop_val, "-1"); crash_counter = atoi(crash_prop_val) + 1; snprintf(crash_prop_val, sizeof(crash_prop_val), "%d", crash_counter); property_set("twrp.crash_counter", crash_prop_val); property_set("ro.twrp.boot", "1"); property_set("ro.twrp.version", TW_VERSION_STR); time_t StartupTime = time(NULL); printf("Starting TWRP %s on %s (pid %d)\n", TW_VERSION_STR, ctime(&StartupTime), getpid()); // Load default values to set DataManager constants and handle ifdefs DataManager::SetDefaultValues(); printf("Starting the UI..."); gui_init(); printf("=> Linking mtab\n"); symlink("/proc/mounts", "/etc/mtab"); if (TWFunc::Path_Exists("/etc/twrp.fstab")) { if (TWFunc::Path_Exists("/etc/recovery.fstab")) { printf("Renaming regular /etc/recovery.fstab -> /etc/recovery.fstab.bak\n"); rename("/etc/recovery.fstab", "/etc/recovery.fstab.bak"); } printf("Moving /etc/twrp.fstab -> /etc/recovery.fstab\n"); rename("/etc/twrp.fstab", "/etc/recovery.fstab"); } printf("=> Processing recovery.fstab\n"); if (!PartitionManager.Process_Fstab("/etc/recovery.fstab", 1)) { LOGERR("Failing out of recovery due to problem with recovery.fstab.\n"); return -1; } PartitionManager.Output_Partition_Logging(); // Load up all the resources gui_loadResources(); #ifdef HAVE_SELINUX if (TWFunc::Path_Exists("/prebuilt_file_contexts")) { if (TWFunc::Path_Exists("/file_contexts")) { printf("Renaming regular /file_contexts -> /file_contexts.bak\n"); rename("/file_contexts", "/file_contexts.bak"); } printf("Moving /prebuilt_file_contexts -> /file_contexts\n"); rename("/prebuilt_file_contexts", "/file_contexts"); } struct selinux_opt selinux_options[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; selinux_handle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1); if (!selinux_handle) printf("No file contexts for SELinux\n"); else printf("SELinux contexts loaded from /file_contexts\n"); { // Check to ensure SELinux can be supported by the kernel char *contexts = NULL; if (PartitionManager.Mount_By_Path("/cache", true) && TWFunc::Path_Exists("/cache/recovery")) { lgetfilecon("/cache/recovery", &contexts); if (!contexts) { lsetfilecon("/cache/recovery", "test"); lgetfilecon("/cache/recovery", &contexts); } } else { LOGINFO("Could not check /cache/recovery SELinux contexts, using /sbin/teamwin instead which may be inaccurate.\n"); lgetfilecon("/sbin/teamwin", &contexts); } if (!contexts) { gui_print_color("warning", "Kernel does not have support for reading SELinux contexts.\n"); } else { free(contexts); gui_print("Full SELinux support is present.\n"); } } #else gui_print_color("warning", "No SELinux support (no libselinux).\n"); #endif PartitionManager.Mount_By_Path("/cache", true); string Zip_File, Reboot_Value; bool Cache_Wipe = false, Factory_Reset = false, Perform_Backup = false, Shutdown = false; { TWPartition* misc = PartitionManager.Find_Partition_By_Path("/misc"); if (misc != NULL) { if (misc->Current_File_System == "emmc") { set_misc_device("emmc", misc->Actual_Block_Device.c_str()); } else if (misc->Current_File_System == "mtd") { set_misc_device("mtd", misc->MTD_Name.c_str()); } else { LOGERR("Unknown file system for /misc\n"); } } get_args(&argc, &argv); int index, index2, len; char* argptr; char* ptr; printf("Startup Commands: "); for (index = 1; index < argc; index++) { argptr = argv[index]; printf(" '%s'", argv[index]); len = strlen(argv[index]); if (*argptr == '-') {argptr++; len--;} if (*argptr == '-') {argptr++; len--;} if (*argptr == 'u') { ptr = argptr; index2 = 0; while (*ptr != '=' && *ptr != '\n') ptr++; // skip the = before grabbing Zip_File while (*ptr == '=') ptr++; if (*ptr) { Zip_File = ptr; } else LOGERR("argument error specifying zip file\n"); } else if (*argptr == 'w') { if (len == 9) Factory_Reset = true; else if (len == 10) Cache_Wipe = true; } else if (*argptr == 'n') { Perform_Backup = true; } else if (*argptr == 'p') { Shutdown = true; } else if (*argptr == 's') { ptr = argptr; index2 = 0; while (*ptr != '=' && *ptr != '\n') ptr++; if (*ptr) { Reboot_Value = *ptr; } } } printf("\n"); } if(crash_counter == 0) { property_list(Print_Prop, NULL); printf("\n"); } else { printf("twrp.crash_counter=%d\n", crash_counter); } // Check for and run startup script if script exists TWFunc::check_and_run_script("/sbin/runatboot.sh", "boot"); TWFunc::check_and_run_script("/sbin/postrecoveryboot.sh", "boot"); #ifdef TW_INCLUDE_INJECTTWRP // Back up TWRP Ramdisk if needed: TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot"); LOGINFO("Backing up TWRP ramdisk...\n"); if (Boot == NULL || Boot->Current_File_System != "emmc") TWFunc::Exec_Cmd("injecttwrp --backup /tmp/backup_recovery_ramdisk.img"); else { string injectcmd = "injecttwrp --backup /tmp/backup_recovery_ramdisk.img bd=" + Boot->Actual_Block_Device; TWFunc::Exec_Cmd(injectcmd); } LOGINFO("Backup of TWRP ramdisk done.\n"); #endif bool Keep_Going = true; if (Perform_Backup) { DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)"); if (!OpenRecoveryScript::Insert_ORS_Command("backup BSDCAE\n")) Keep_Going = false; } if (Keep_Going && !Zip_File.empty()) { string ORSCommand = "install " + Zip_File; if (!OpenRecoveryScript::Insert_ORS_Command(ORSCommand)) Keep_Going = false; } if (Keep_Going) { if (Factory_Reset) { if (!OpenRecoveryScript::Insert_ORS_Command("wipe data\n")) Keep_Going = false; } else if (Cache_Wipe) { if (!OpenRecoveryScript::Insert_ORS_Command("wipe cache\n")) Keep_Going = false; } } TWFunc::Update_Log_File(); // Offer to decrypt if the device is encrypted if (DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0) { LOGINFO("Is encrypted, do decrypt page first\n"); if (gui_startPage("decrypt", 1, 1) != 0) { LOGERR("Failed to start decrypt GUI page.\n"); } else { // Check for and load custom theme if present gui_loadCustomResources(); } } else if (datamedia) { if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) { LOGINFO("Failed to get default contexts and file mode for storage files.\n"); } else { LOGINFO("Got default contexts and file mode for storage files.\n"); } } // Read the settings file #ifdef TW_HAS_MTP // We unmount partitions sometimes during early boot which may override // the default of MTP being enabled by auto toggling MTP off. This // will force it back to enabled then get overridden by the settings // file, assuming that an entry for tw_mtp_enabled is set. DataManager::SetValue("tw_mtp_enabled", 1); #endif DataManager::ReadSettingsFile(); // Fixup the RTC clock on devices which require it if(crash_counter == 0) TWFunc::Fixup_Time_On_Boot(); // Run any outstanding OpenRecoveryScript if (DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0 && (TWFunc::Path_Exists(SCRIPT_FILE_TMP) || TWFunc::Path_Exists(SCRIPT_FILE_CACHE))) { OpenRecoveryScript::Run_OpenRecoveryScript(); } #ifdef TW_HAS_MTP // Enable MTP? char mtp_crash_check[PROPERTY_VALUE_MAX]; property_get("mtp.crash_check", mtp_crash_check, "0"); if (strcmp(mtp_crash_check, "0") == 0) { property_set("mtp.crash_check", "1"); if (DataManager::GetIntValue("tw_mtp_enabled") == 1 && ((DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0 && DataManager::GetIntValue(TW_IS_DECRYPTED) != 0) || DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0)) { LOGINFO("Enabling MTP during startup\n"); if (!PartitionManager.Enable_MTP()) PartitionManager.Disable_MTP(); else gui_print("MTP Enabled\n"); } else { PartitionManager.Disable_MTP(); } property_set("mtp.crash_check", "0"); } else { gui_print_color("warning", "MTP Crashed, not starting MTP on boot.\n"); DataManager::SetValue("tw_mtp_enabled", 0); PartitionManager.Disable_MTP(); } #else PartitionManager.Disable_MTP(); #endif #ifndef TW_OEM_BUILD // Check if system has never been changed TWPartition* sys = PartitionManager.Find_Partition_By_Path("/system"); if (sys) { if ((DataManager::GetIntValue("tw_mount_system_ro") == 0 && sys->Check_Lifetime_Writes() == 0) || DataManager::GetIntValue("tw_mount_system_ro") == 2) { if (DataManager::GetIntValue("tw_never_show_system_ro_page") == 0) { DataManager::SetValue("tw_back", "main"); if (gui_startPage("system_readonly", 1, 1) != 0) { LOGERR("Failed to start system_readonly GUI page.\n"); } } else if (DataManager::GetIntValue("tw_mount_system_ro") == 0) { sys->Change_Mount_Read_Only(false); } } else if (DataManager::GetIntValue("tw_mount_system_ro") == 1) { // Do nothing, user selected to leave system read only } else { sys->Change_Mount_Read_Only(false); } } #endif // Launch the main GUI gui_start(); #ifndef TW_OEM_BUILD // Disable flashing of stock recovery TWFunc::Disable_Stock_Recovery_Replace(); // Check for su to see if the device is rooted or not if (PartitionManager.Mount_By_Path("/system", false) && DataManager::GetIntValue("tw_mount_system_ro") == 0) { if (TWFunc::Path_Exists("/supersu/su") && !TWFunc::Path_Exists("/system/bin/su") && !TWFunc::Path_Exists("/system/xbin/su") && !TWFunc::Path_Exists("/system/bin/.ext/.su")) { // Device doesn't have su installed DataManager::SetValue("tw_busy", 1); if (gui_startPage("installsu", 1, 1) != 0) { LOGERR("Failed to start SuperSU install page.\n"); } } sync(); PartitionManager.UnMount_By_Path("/system", false); } #endif // Reboot TWFunc::Update_Intent_File(Reboot_Value); TWFunc::Update_Log_File(); gui_print("Rebooting...\n"); string Reboot_Arg; DataManager::GetValue("tw_reboot_arg", Reboot_Arg); if (Reboot_Arg == "recovery") TWFunc::tw_reboot(rb_recovery); else if (Reboot_Arg == "poweroff") TWFunc::tw_reboot(rb_poweroff); else if (Reboot_Arg == "bootloader") TWFunc::tw_reboot(rb_bootloader); else if (Reboot_Arg == "download") TWFunc::tw_reboot(rb_download); else TWFunc::tw_reboot(rb_system); return 0; }