int GUIAction::doAction(Action action, int isThreaded /* = 0 */) { static string zip_queue[10]; static int zip_queue_index; int simulate; std::string arg = gui_parse_text(action.mArg); std::string function = gui_parse_text(action.mFunction); DataManager::GetValue(TW_SIMULATE_ACTIONS, simulate); if (function == "reboot") { //curtainClose(); this sometimes causes a crash sync(); if (arg == "recovery") tw_reboot(rb_recovery); else if (arg == "poweroff") tw_reboot(rb_poweroff); else if (arg == "bootloader") tw_reboot(rb_bootloader); else if (arg == "download") tw_reboot(rb_download); else tw_reboot(rb_system); // This should never occur return -1; } if (function == "home") { PageManager::SelectPackage("TWRP"); gui_changePage("main"); return 0; } if (function == "key") { PageManager::NotifyKey(getKeyByName(arg)); return 0; } if (function == "page") { std::string page_name = gui_parse_text(arg); return gui_changePage(page_name); } if (function == "reload") { int check = 0, ret_val = 0; std::string theme_path; operation_start("Reload Theme"); theme_path = DataManager::GetSettingsStoragePath(); if (ensure_path_mounted(theme_path.c_str()) < 0) { LOGE("Unable to mount %s during reload function startup.\n", theme_path.c_str()); check = 1; } theme_path += "/TWRP/theme/ui.zip"; if (check != 0 || PageManager::ReloadPackage("TWRP", theme_path) != 0) { // Loading the custom theme failed - try loading the stock theme LOGI("Attempting to reload stock theme...\n"); if (PageManager::ReloadPackage("TWRP", "/res/ui.xml")) { LOGE("Failed to load base packages.\n"); ret_val = 1; } } operation_end(ret_val, simulate); } if (function == "readBackup") { set_restore_files(); return 0; } if (function == "set") { if (arg.find('=') != string::npos) { string varName = arg.substr(0, arg.find('=')); string value = arg.substr(arg.find('=') + 1, string::npos); DataManager::GetValue(value, value); DataManager::SetValue(varName, value); } else DataManager::SetValue(arg, "1"); return 0; } if (function == "clear") { DataManager::SetValue(arg, "0"); return 0; } if (function == "mount") { if (arg == "usb") { DataManager::SetValue(TW_ACTION_BUSY, 1); if (!simulate) usb_storage_enable(); else ui_print("Simulating actions...\n"); } else if (!simulate) { string cmd; if (arg == "EXTERNAL") cmd = "mount " + DataManager::GetStrValue(TW_EXTERNAL_MOUNT); else if (arg == "INTERNAL") cmd = "mount " + DataManager::GetStrValue(TW_INTERNAL_MOUNT); else cmd = "mount " + arg; __system(cmd.c_str()); if (arg == "/data" && DataManager::GetIntValue(TW_HAS_DATADATA) == 1) __system("mount /datadata"); } else ui_print("Simulating actions...\n"); return 0; } if (function == "umount" || function == "unmount") { if (arg == "usb") { if (!simulate) usb_storage_disable(); else ui_print("Simulating actions...\n"); DataManager::SetValue(TW_ACTION_BUSY, 0); } else if (!simulate) { string cmd; if (arg == "EXTERNAL") cmd = "umount " + DataManager::GetStrValue(TW_EXTERNAL_MOUNT); else if (arg == "INTERNAL") cmd = "umount " + DataManager::GetStrValue(TW_INTERNAL_MOUNT); else if (DataManager::GetIntValue(TW_DONT_UNMOUNT_SYSTEM) == 1 && (arg == "system" || arg == "/system")) return 0; else cmd = "umount " + arg; __system(cmd.c_str()); if (arg == "/data" && DataManager::GetIntValue(TW_HAS_DATADATA) == 1) __system("umount /datadata"); } else ui_print("Simulating actions...\n"); return 0; } if (function == "restoredefaultsettings") { operation_start("Restore Defaults"); if (simulate) // Simulated so that people don't accidently wipe out the "simulation is on" setting ui_print("Simulating actions...\n"); else { DataManager::ResetDefaults(); mount_current_storage(); } operation_end(0, simulate); } if (function == "copylog") { operation_start("Copy Log"); if (!simulate) { char command[255]; mount_current_storage(); sprintf(command, "cp /tmp/recovery.log %s", DataManager::GetCurrentStoragePath().c_str()); __system(command); sync(); ui_print("Copied recovery log to %s.\n", DataManager::GetCurrentStoragePath().c_str()); } else simulate_progress_bar(); operation_end(0, simulate); return 0; } if (function == "compute" || function == "addsubtract") { if (arg.find("+") != string::npos) { string varName = arg.substr(0, arg.find('+')); string string_to_add = arg.substr(arg.find('+') + 1, string::npos); int amount_to_add = atoi(string_to_add.c_str()); int value; DataManager::GetValue(varName, value); DataManager::SetValue(varName, value + amount_to_add); return 0; } if (arg.find("-") != string::npos) { string varName = arg.substr(0, arg.find('-')); string string_to_subtract = arg.substr(arg.find('-') + 1, string::npos); int amount_to_subtract = atoi(string_to_subtract.c_str()); int value; DataManager::GetValue(varName, value); value -= amount_to_subtract; if (value <= 0) value = 0; DataManager::SetValue(varName, value); return 0; } } if (function == "setguitimezone") { string SelectedZone; DataManager::GetValue(TW_TIME_ZONE_GUISEL, SelectedZone); // read the selected time zone into SelectedZone string Zone = SelectedZone.substr(0, SelectedZone.find(';')); // parse to get time zone string DSTZone = SelectedZone.substr(SelectedZone.find(';') + 1, string::npos); // parse to get DST component int dst; DataManager::GetValue(TW_TIME_ZONE_GUIDST, dst); // check wether user chose to use DST string offset; DataManager::GetValue(TW_TIME_ZONE_GUIOFFSET, offset); // pull in offset string NewTimeZone = Zone; if (offset != "0") NewTimeZone += ":" + offset; if (dst != 0) NewTimeZone += DSTZone; DataManager::SetValue(TW_TIME_ZONE_VAR, NewTimeZone); update_tz_environment_variables(); return 0; } if (function == "togglestorage") { if (arg == "internal") { DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 0); DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcint.sze - sdcint.used) / 1048576LLU)); } else if (arg == "external") { DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 1); DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcext.sze - sdcext.used) / 1048576LLU)); } if (mount_current_storage() == 0) { if (arg == "internal") { // Save the current zip location to the external variable DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, DataManager::GetStrValue(TW_ZIP_LOCATION_VAR)); // Change the current zip location to the internal variable DataManager::SetValue(TW_ZIP_LOCATION_VAR, DataManager::GetStrValue(TW_ZIP_INTERNAL_VAR)); } else if (arg == "external") { // Save the current zip location to the internal variable DataManager::SetValue(TW_ZIP_INTERNAL_VAR, DataManager::GetStrValue(TW_ZIP_LOCATION_VAR)); // Change the current zip location to the external variable DataManager::SetValue(TW_ZIP_LOCATION_VAR, DataManager::GetStrValue(TW_ZIP_EXTERNAL_VAR)); } } else { // We weren't able to toggle for some reason, restore original setting if (arg == "internal") { DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 1); DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcext.sze - sdcext.used) / 1048576LLU)); } else if (arg == "external") { DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 0); DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcint.sze - sdcint.used) / 1048576LLU)); } } return 0; } if (function == "overlay") return gui_changeOverlay(arg); if (function == "queuezip") { if (zip_queue_index >= 10) { ui_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; } if (function == "cancelzip") { if (zip_queue_index <= 0) { ui_print("Minimum zip queue reached!\n"); return 0; } else { zip_queue_index--; DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index); } return 0; } if (function == "queueclear") { zip_queue_index = 0; DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index); return 0; } if (function == "sleep") { usleep(atoi(arg.c_str())); return 0; } if (isThreaded) { if (function == "flash") { int i, ret_val = 0; 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)); ret_val = flash_zip(zip_queue[i], arg, simulate); if (ret_val != 0) { ui_print("Error flashing zip '%s'\n", zip_queue[i].c_str()); i = 10; // Error flashing zip - exit queue ret_val = 1; } } zip_queue_index = 0; DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index); if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) { operation_start("ReinjectTWRP"); ui_print("Injecting TWRP into boot image...\n"); if (simulate) { simulate_progress_bar(); } else { __system("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash"); ui_print("TWRP injection complete.\n"); } } operation_end(ret_val, simulate); return 0; } if (function == "wipe") { operation_start("Format"); DataManager::SetValue("tw_partition", arg); if (simulate) { simulate_progress_bar(); } else { if (arg == "data") wipe_data(0); else if (arg == "battery") wipe_battery_stats(); else if (arg == "rotate") wipe_rotate_data(); else if (arg == "dalvik") wipe_dalvik_cache(); else erase_volume(arg.c_str()); if (arg == "/sdcard") { ensure_path_mounted(SDCARD_ROOT); mkdir("/sdcard/TWRP", 0777); DataManager::Flush(); } } update_system_details(); operation_end(0, simulate); return 0; } if (function == "refreshsizes") { operation_start("Refreshing Sizes"); if (simulate) { simulate_progress_bar(); } else update_system_details(); operation_end(0, simulate); } if (function == "nandroid") { operation_start("Nandroid"); if (simulate) { DataManager::SetValue("tw_partition", "Simulation"); simulate_progress_bar(); } else { if (arg == "backup") nandroid_back_exe(); else if (arg == "restore") nandroid_rest_exe(); else { operation_end(1, simulate); return -1; } } operation_end(0, simulate); return 0; } if (function == "fixpermissions") { operation_start("Fix Permissions"); LOGI("fix permissions started!\n"); if (simulate) { simulate_progress_bar(); } else fix_perms(); LOGI("fix permissions DONE!\n"); operation_end(0, simulate); return 0; } if (function == "dd") { operation_start("imaging"); if (simulate) { simulate_progress_bar(); } else { char cmd[512]; sprintf(cmd, "dd %s", arg.c_str()); __system(cmd); } operation_end(0, simulate); return 0; } if (function == "partitionsd") { operation_start("Partition SD Card"); if (simulate) { simulate_progress_bar(); } else { int allow_partition; DataManager::GetValue(TW_ALLOW_PARTITION_SDCARD, allow_partition); if (allow_partition == 0) { ui_print("This device does not have a real SD Card!\nAborting!\n"); } else { // Below seen in Koush's recovery char sddevice[256]; Volume *vol = volume_for_path("/sdcard"); strcpy(sddevice, vol->device); // Just need block not whole partition sddevice[strlen("/dev/block/mmcblkX")] = NULL; char es[64]; std::string ext_format; int ext, swap; DataManager::GetValue("tw_sdext_size", ext); DataManager::GetValue("tw_swap_size", swap); DataManager::GetValue("tw_sdpart_file_system", ext_format); sprintf(es, "/sbin/sdparted -es %dM -ss %dM -efs %s -s > /cache/part.log",ext,swap,ext_format.c_str()); LOGI("\nrunning script: %s\n", es); run_script("\nContinue partitioning?", "\nPartitioning sdcard : ", es, "\nunable to execute parted!\n(%s)\n", "\nOops... something went wrong!\nPlease check the recovery log!\n", "\nPartitioning complete!\n\n", "\nPartitioning aborted!\n\n", 0); // recreate TWRP folder and rewrite settings - these will be gone after sdcard is partitioned ensure_path_mounted(SDCARD_ROOT); mkdir("/sdcard/TWRP", 0777); DataManager::Flush(); DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, "/sdcard"); if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1) DataManager::SetValue(TW_ZIP_LOCATION_VAR, "/sdcard"); update_system_details(); } } operation_end(0, simulate); return 0; } if (function == "installhtcdumlock") { operation_start("Install HTC Dumlock"); if (simulate) { simulate_progress_bar(); } else install_htc_dumlock(); operation_end(0, simulate); return 0; } if (function == "htcdumlockrestoreboot") { operation_start("HTC Dumlock Restore Boot"); if (simulate) { simulate_progress_bar(); } else htc_dumlock_restore_original_boot(); operation_end(0, simulate); return 0; } if (function == "htcdumlockreflashrecovery") { operation_start("HTC Dumlock Reflash Recovery"); if (simulate) { simulate_progress_bar(); } else htc_dumlock_reflash_recovery_to_boot(); operation_end(0, simulate); return 0; } if (function == "cmd") { int op_status = 0; operation_start("Command"); ui_print("Running command: '%s'\n", arg.c_str()); if (simulate) { simulate_progress_bar(); } else { op_status = __system(arg.c_str()); if (op_status != 0) op_status = 1; } operation_end(op_status, simulate); return 0; } if (function == "reinjecttwrp") { int op_status = 0; operation_start("ReinjectTWRP"); ui_print("Injecting TWRP into boot image...\n"); if (simulate) { simulate_progress_bar(); } else { __system("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash"); ui_print("TWRP injection complete.\n"); } operation_end(op_status, simulate); return 0; } } else { pthread_t t; pthread_create(&t, NULL, thread_start, this); return 0; } return -1; }
/* * list_remove -- remove object from list * * pop - pmemobj handle * pe_offset - offset to list entry on user list relative to user data * head - list head * oid - target object ID */ int list_remove(PMEMobjpool *pop, ssize_t pe_offset, struct list_head *head, PMEMoid oid) { LOG(3, NULL); ASSERTne(head, NULL); int ret; struct lane *lane; lane_hold(pop, &lane); if ((ret = pmemobj_mutex_lock(pop, &head->lock))) { errno = ret; LOG(2, "pmemobj_mutex_lock failed"); ret = -1; goto err; } struct operation_context *ctx = lane->external; operation_start(ctx); struct list_entry *entry_ptr = (struct list_entry *)OBJ_OFF_TO_PTR(pop, oid.off + (size_t)pe_offset); struct list_args_remove args = { .pe_offset = (ssize_t)pe_offset, .head = head, .entry_ptr = entry_ptr, .obj_doffset = oid.off, }; struct list_args_common args_common = { .obj_doffset = oid.off, .entry_ptr = entry_ptr, .pe_offset = (ssize_t)pe_offset, }; /* remove element from user list */ list_remove_single(pop, ctx, &args); /* clear next and prev offsets in removing element using redo log */ list_fill_entry_redo_log(pop, ctx, &args_common, 0, 0, 0); operation_finish(ctx); pmemobj_mutex_unlock_nofail(pop, &head->lock); err: lane_release(pop); ASSERT(ret == 0 || ret == -1); return ret; } /* * list_move -- move object between two lists * * pop - pmemobj handle * pe_offset_old - offset to old list entry relative to user data * head_old - old list head * pe_offset_new - offset to new list entry relative to user data * head_new - new list head * dest - destination object ID * before - before/after destination * oid - target object ID */ int list_move(PMEMobjpool *pop, size_t pe_offset_old, struct list_head *head_old, size_t pe_offset_new, struct list_head *head_new, PMEMoid dest, int before, PMEMoid oid) { LOG(3, NULL); ASSERTne(head_old, NULL); ASSERTne(head_new, NULL); int ret; struct lane *lane; lane_hold(pop, &lane); /* * Grab locks in specified order to avoid dead-locks. * * XXX performance improvement: initialize oob locks at pool opening */ if ((ret = list_mutexes_lock(pop, head_new, head_old))) { errno = ret; LOG(2, "list_mutexes_lock failed"); ret = -1; goto err; } struct operation_context *ctx = lane->external; operation_start(ctx); dest = list_get_dest(pop, head_new, dest, (ssize_t)pe_offset_new, before); struct list_entry *entry_ptr_old = (struct list_entry *)OBJ_OFF_TO_PTR(pop, oid.off + pe_offset_old); struct list_entry *entry_ptr_new = (struct list_entry *)OBJ_OFF_TO_PTR(pop, oid.off + pe_offset_new); struct list_entry *dest_entry_ptr = (struct list_entry *)OBJ_OFF_TO_PTR(pop, dest.off + pe_offset_new); if (head_old == head_new) { /* moving within the same list */ if (dest.off == oid.off) goto unlock; if (before && dest_entry_ptr->pe_prev.off == oid.off) { if (head_old->pe_first.off != dest.off) goto unlock; list_update_head(pop, ctx, head_old, oid.off); goto redo_last; } if (!before && dest_entry_ptr->pe_next.off == oid.off) { if (head_old->pe_first.off != oid.off) goto unlock; list_update_head(pop, ctx, head_old, entry_ptr_old->pe_next.off); goto redo_last; } } ASSERT((ssize_t)pe_offset_old >= 0); struct list_args_remove args_remove = { .pe_offset = (ssize_t)pe_offset_old, .head = head_old, .entry_ptr = entry_ptr_old, .obj_doffset = oid.off, }; struct list_args_insert args_insert = { .head = head_new, .dest = dest, .dest_entry_ptr = dest_entry_ptr, .before = before, }; ASSERT((ssize_t)pe_offset_new >= 0); struct list_args_common args_common = { .obj_doffset = oid.off, .entry_ptr = entry_ptr_new, .pe_offset = (ssize_t)pe_offset_new, }; uint64_t next_offset; uint64_t prev_offset; /* remove element from user list */ list_remove_single(pop, ctx, &args_remove); /* insert element to user list */ list_insert_user(pop, ctx, &args_insert, &args_common, &next_offset, &prev_offset); /* offsets differ, move is between different list entries - set uuid */ int set_uuid = pe_offset_new != pe_offset_old ? 1 : 0; /* fill next and prev offsets of moving element using redo log */ list_fill_entry_redo_log(pop, ctx, &args_common, next_offset, prev_offset, set_uuid); redo_last: unlock: operation_finish(ctx); list_mutexes_unlock(pop, head_new, head_old); err: lane_release(pop); ASSERT(ret == 0 || ret == -1); return ret; }
/* * list_insert -- insert object to a single list * * pop - pmemobj handle * pe_offset - offset to list entry on user list relative to user data * head - list head * dest - destination object ID * before - before/after destination * oid - target object ID */ int list_insert(PMEMobjpool *pop, ssize_t pe_offset, struct list_head *head, PMEMoid dest, int before, PMEMoid oid) { LOG(3, NULL); ASSERTne(head, NULL); struct lane *lane; lane_hold(pop, &lane); int ret; if ((ret = pmemobj_mutex_lock(pop, &head->lock))) { errno = ret; LOG(2, "pmemobj_mutex_lock failed"); ret = -1; goto err; } struct operation_context *ctx = lane->external; operation_start(ctx); dest = list_get_dest(pop, head, dest, pe_offset, before); struct list_entry *entry_ptr = (struct list_entry *)OBJ_OFF_TO_PTR(pop, (uintptr_t)((ssize_t)oid.off + pe_offset)); struct list_entry *dest_entry_ptr = (struct list_entry *)OBJ_OFF_TO_PTR(pop, (uintptr_t)((ssize_t)dest.off + pe_offset)); struct list_args_insert args = { .dest = dest, .dest_entry_ptr = dest_entry_ptr, .head = head, .before = before, }; struct list_args_common args_common = { .obj_doffset = oid.off, .entry_ptr = entry_ptr, .pe_offset = (ssize_t)pe_offset, }; uint64_t next_offset; uint64_t prev_offset; /* insert element to user list */ list_insert_user(pop, ctx, &args, &args_common, &next_offset, &prev_offset); /* fill entry of existing element using redo log */ list_fill_entry_redo_log(pop, ctx, &args_common, next_offset, prev_offset, 1); operation_finish(ctx); pmemobj_mutex_unlock_nofail(pop, &head->lock); err: lane_release(pop); ASSERT(ret == 0 || ret == -1); return ret; } /* * list_remove_free -- remove from two lists and free an object * * pop - pmemobj pool handle * oob_head - oob list head * pe_offset - offset to list entry on user list relative to user data * user_head - user list head, *must* be locked if not NULL * oidp - pointer to target object ID */ static void list_remove_free(PMEMobjpool *pop, size_t pe_offset, struct list_head *user_head, PMEMoid *oidp) { LOG(3, NULL); ASSERT(user_head != NULL); #ifdef DEBUG int r = pmemobj_mutex_assert_locked(pop, &user_head->lock); ASSERTeq(r, 0); #endif struct lane *lane; lane_hold(pop, &lane); struct operation_context *ctx = lane->external; operation_start(ctx); struct pobj_action deferred; palloc_defer_free(&pop->heap, oidp->off, &deferred); uint64_t obj_doffset = oidp->off; ASSERT((ssize_t)pe_offset >= 0); struct list_entry *entry_ptr = (struct list_entry *)OBJ_OFF_TO_PTR(pop, obj_doffset + pe_offset); struct list_args_remove args = { .pe_offset = (ssize_t)pe_offset, .head = user_head, .entry_ptr = entry_ptr, .obj_doffset = obj_doffset }; /* remove from user list */ list_remove_single(pop, ctx, &args); /* clear the oid */ if (OBJ_PTR_IS_VALID(pop, oidp)) list_set_oid_redo_log(pop, ctx, oidp, 0, 1); else oidp->off = 0; palloc_publish(&pop->heap, &deferred, 1, ctx); lane_release(pop); } /* * list_remove_free_user -- remove from two lists and free an object * * pop - pmemobj pool handle * oob_head - oob list head * pe_offset - offset to list entry on user list relative to user data * user_head - user list head * oidp - pointer to target object ID */ int list_remove_free_user(PMEMobjpool *pop, size_t pe_offset, struct list_head *user_head, PMEMoid *oidp) { LOG(3, NULL); int ret; if ((ret = pmemobj_mutex_lock(pop, &user_head->lock))) { errno = ret; LOG(2, "pmemobj_mutex_lock failed"); return -1; } list_remove_free(pop, pe_offset, user_head, oidp); pmemobj_mutex_unlock_nofail(pop, &user_head->lock); return 0; }
/* * list_insert_new -- allocate and insert element to oob and user lists * * pop - pmemobj pool handle * pe_offset - offset to list entry on user list relative to user data * user_head - user list head, must be locked if not NULL * dest - destination on user list * before - insert before/after destination on user list * size - size of allocation, will be increased by OBJ_OOB_SIZE * constructor - object's constructor * arg - argument for object's constructor * oidp - pointer to target object ID */ static int list_insert_new(PMEMobjpool *pop, size_t pe_offset, struct list_head *user_head, PMEMoid dest, int before, size_t size, uint64_t type_num, int (*constructor)(void *ctx, void *ptr, size_t usable_size, void *arg), void *arg, PMEMoid *oidp) { LOG(3, NULL); ASSERT(user_head != NULL); int ret; #ifdef DEBUG int r = pmemobj_mutex_assert_locked(pop, &user_head->lock); ASSERTeq(r, 0); #endif struct lane *lane; lane_hold(pop, &lane); struct pobj_action reserved; if (palloc_reserve(&pop->heap, size, constructor, arg, type_num, 0, 0, &reserved) != 0) { ERR("!palloc_reserve"); ret = -1; goto err_pmalloc; } uint64_t obj_doffset = reserved.heap.offset; struct operation_context *ctx = lane->external; operation_start(ctx); ASSERT((ssize_t)pe_offset >= 0); dest = list_get_dest(pop, user_head, dest, (ssize_t)pe_offset, before); struct list_entry *entry_ptr = (struct list_entry *)OBJ_OFF_TO_PTR(pop, obj_doffset + pe_offset); struct list_entry *dest_entry_ptr = (struct list_entry *)OBJ_OFF_TO_PTR(pop, dest.off + pe_offset); struct list_args_insert args = { .dest = dest, .dest_entry_ptr = dest_entry_ptr, .head = user_head, .before = before, }; struct list_args_common args_common = { .obj_doffset = obj_doffset, .entry_ptr = entry_ptr, .pe_offset = (ssize_t)pe_offset, }; uint64_t next_offset; uint64_t prev_offset; /* insert element to user list */ list_insert_user(pop, ctx, &args, &args_common, &next_offset, &prev_offset); /* don't need to use redo log for filling new element */ list_fill_entry_persist(pop, entry_ptr, next_offset, prev_offset); if (oidp != NULL) { if (OBJ_PTR_IS_VALID(pop, oidp)) { list_set_oid_redo_log(pop, ctx, oidp, obj_doffset, 0); } else { oidp->off = obj_doffset; oidp->pool_uuid_lo = pop->uuid_lo; } } palloc_publish(&pop->heap, &reserved, 1, ctx); ret = 0; err_pmalloc: lane_release(pop); ASSERT(ret == 0 || ret == -1); return ret; } /* * list_insert_new_user -- allocate and insert element to oob and user lists * * pop - pmemobj pool handle * oob_head - oob list head * pe_offset - offset to list entry on user list relative to user data * user_head - user list head * dest - destination on user list * before - insert before/after destination on user list * size - size of allocation, will be increased by OBJ_OOB_SIZE * constructor - object's constructor * arg - argument for object's constructor * oidp - pointer to target object ID */ int list_insert_new_user(PMEMobjpool *pop, size_t pe_offset, struct list_head *user_head, PMEMoid dest, int before, size_t size, uint64_t type_num, int (*constructor)(void *ctx, void *ptr, size_t usable_size, void *arg), void *arg, PMEMoid *oidp) { int ret; if ((ret = pmemobj_mutex_lock(pop, &user_head->lock))) { errno = ret; LOG(2, "pmemobj_mutex_lock failed"); return -1; } ret = list_insert_new(pop, pe_offset, user_head, dest, before, size, type_num, constructor, arg, oidp); pmemobj_mutex_unlock_nofail(pop, &user_head->lock); ASSERT(ret == 0 || ret == -1); return ret; }
int GUIAction::terminalcommand(std::string arg) { int op_status = 0; string cmdpath, command; DataManager::GetValue("tw_terminal_location", cmdpath); operation_start("CommandOutput"); gui_print("%s # %s\n", cmdpath.c_str(), arg.c_str()); if (simulate) { simulate_progress_bar(); operation_end(op_status); } else if (arg == "exit") { LOGINFO("Exiting terminal\n"); operation_end(op_status); page("main"); } else { command = "cd \"" + cmdpath + "\" && " + arg + " 2>&1";; LOGINFO("Actual command is: '%s'\n", command.c_str()); DataManager::SetValue("tw_terminal_state", 1); DataManager::SetValue("tw_background_thread_running", 1); FILE* fp; char line[512]; fp = popen(command.c_str(), "r"); if (fp == NULL) { LOGERR("Error opening command to run.\n"); } else { int fd = fileno(fp), has_data = 0, check = 0, keep_going = -1, bytes_read = 0; struct timeval timeout; fd_set fdset; while(keep_going) { FD_ZERO(&fdset); FD_SET(fd, &fdset); timeout.tv_sec = 0; timeout.tv_usec = 400000; has_data = select(fd+1, &fdset, NULL, NULL, &timeout); if (has_data == 0) { // Timeout reached DataManager::GetValue("tw_terminal_state", check); if (check == 0) { keep_going = 0; } } else if (has_data < 0) { // End of execution keep_going = 0; } else { // Try to read output memset(line, 0, sizeof(line)); if(fgets(line, sizeof(line), fp) != NULL) gui_print("%s", line); // Display output else keep_going = 0; // Done executing } } fclose(fp); } DataManager::SetValue("tw_operation_status", 0); DataManager::SetValue("tw_operation_state", 1); DataManager::SetValue("tw_terminal_state", 0); DataManager::SetValue("tw_background_thread_running", 0); DataManager::SetValue(TW_ACTION_BUSY, 0); } return 0; }
int GUIAction::wipe(std::string arg) { operation_start("Format"); DataManager::SetValue("tw_partition", arg); int ret_val = false; if (simulate) { simulate_progress_bar(); } else { if (arg == "data") ret_val = PartitionManager.Factory_Reset(); else if (arg == "battery") ret_val = PartitionManager.Wipe_Battery_Stats(); else if (arg == "rotate") ret_val = PartitionManager.Wipe_Rotate_Data(); else if (arg == "dalvik") ret_val = PartitionManager.Wipe_Dalvik_Cache(); else if (arg == "DATAMEDIA") { ret_val = PartitionManager.Format_Data(); } else if (arg == "INTERNAL") { int has_datamedia, dual_storage; DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia); if (has_datamedia) { ret_val = PartitionManager.Wipe_Media_From_Data(); } else { ret_val = PartitionManager.Wipe_By_Path(DataManager::GetSettingsStoragePath()); } } else if (arg == "EXTERNAL") { string External_Path; DataManager::GetValue(TW_EXTERNAL_PATH, External_Path); ret_val = PartitionManager.Wipe_By_Path(External_Path); } else if (arg == "ANDROIDSECURE") { ret_val = PartitionManager.Wipe_Android_Secure(); } else if (arg == "LIST") { string Wipe_List, wipe_path; bool skip = false; ret_val = true; TWPartition* wipe_part = NULL; DataManager::GetValue("tw_wipe_list", Wipe_List); LOGINFO("wipe 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("wipe_path '%s'\n", wipe_path.c_str()); if (wipe_path == "/and-sec") { if (!PartitionManager.Wipe_Android_Secure()) { LOGERR("Unable to wipe android secure\n"); ret_val = false; break; } else { skip = true; } } else if (wipe_path == "DALVIK") { if (!PartitionManager.Wipe_Dalvik_Cache()) { LOGERR("Failed to wipe dalvik\n"); ret_val = false; break; } else { skip = true; } } else if (wipe_path == "INTERNAL") { if (!PartitionManager.Wipe_Media_From_Data()) { ret_val = false; break; } else { skip = true; } } if (!skip) { if (!PartitionManager.Wipe_By_Path(wipe_path)) { LOGERR("Unable to wipe '%s'\n", wipe_path.c_str()); ret_val = false; break; } else if (wipe_path == DataManager::GetSettingsStoragePath()) { arg = wipe_path; } } else { skip = false; } start_pos = end_pos + 1; end_pos = Wipe_List.find(";", start_pos); } } } else ret_val = PartitionManager.Wipe_By_Path(arg); #ifndef TW_OEM_BUILD if (arg == DataManager::GetSettingsStoragePath()) { // If we wiped the settings storage path, recreate the TWRP folder and dump the settings string Storage_Path = DataManager::GetSettingsStoragePath(); if (PartitionManager.Mount_By_Path(Storage_Path, true)) { LOGINFO("Making TWRP folder and saving settings.\n"); Storage_Path += "/TWRP"; mkdir(Storage_Path.c_str(), 0777); DataManager::Flush(); } else { LOGERR("Unable to recreate TWRP folder and save settings.\n"); } } #endif } PartitionManager.Update_System_Details(); if (ret_val) ret_val = 0; // 0 is success else ret_val = 1; // 1 is failure operation_end(ret_val); return 0; }