Add wipe functions, compiles in CM7, text shows in UI, zips install

Zip install works, had to move mincrypt code into TWRP to prevent
a crash when checking the zip signature.
Added wipe functions
Made it compile in CM7
Made text show up in console and logging
diff --git a/Android.mk b/Android.mk
index 6d3be1d..6c6ee9b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -38,7 +38,8 @@
     mtdutils/mtdutils.c \
     twinstall.cpp \
     twmincrypt/twrsa.c \
-    twmincrypt/twsha.c
+    twmincrypt/twsha.c \
+    twrp-functions.cpp
 
 ifeq ($(TARGET_RECOVERY_REBOOT_SRC),)
   LOCAL_SRC_FILES += reboot.c
diff --git a/data.cpp b/data.cpp
index 8b717f5..896bb1b 100644
--- a/data.cpp
+++ b/data.cpp
@@ -50,8 +50,6 @@
 
 	void gui_notifyVarChange(const char *name, const char* value);
 
-    int get_battery_level(void);
-
 	int __system(const char *command);
 }
 
@@ -761,8 +759,36 @@
     if (varName == "tw_battery")
     {
         char tmp[16];
+		static char charging = ' ';
+		static int lastVal = -1;
+		static time_t nextSecCheck = 0;
 
-        sprintf(tmp, "%i%%", get_battery_level());
+		struct timeval curTime;
+		gettimeofday(&curTime, NULL);
+		if (curTime.tv_sec > nextSecCheck)
+		{
+			char cap_s[4];
+			FILE * cap = fopen("/sys/class/power_supply/battery/capacity","rt");
+			if (cap){
+				fgets(cap_s, 4, cap);
+				fclose(cap);
+				lastVal = atoi(cap_s);
+				if (lastVal > 100)  lastVal = 101;
+				if (lastVal < 0)    lastVal = 0;
+			}
+			cap = fopen("/sys/class/power_supply/battery/status","rt");
+			if (cap) {
+				fgets(cap_s, 2, cap);
+				fclose(cap);
+				if (cap_s[0] == 'C')
+					charging = '+';
+				else
+					charging = ' ';
+			}
+			nextSecCheck = curTime.tv_sec + 60;
+		}
+
+		sprintf(tmp, "%i%%%c", lastVal, charging);
         value = tmp;
         return 0;
     }
diff --git a/extra-functions.c b/extra-functions.c
index e01ab83..952c091 100644
--- a/extra-functions.c
+++ b/extra-functions.c
@@ -339,102 +339,6 @@
     return 0;
 }
 
-void wipe_dalvik_cache()
-{
-        //ui_set_background(BACKGROUND_ICON_WIPE);
-        ensure_path_mounted("/data");
-        ensure_path_mounted("/cache");
-        ui_print("\n-- Wiping Dalvik Cache Directories...\n");
-        __system("rm -rf /data/dalvik-cache");
-        ui_print("Cleaned: /data/dalvik-cache...\n");
-        __system("rm -rf /cache/dalvik-cache");
-        ui_print("Cleaned: /cache/dalvik-cache...\n");
-        __system("rm -rf /cache/dc");
-        ui_print("Cleaned: /cache/dc\n");
-
-        struct stat st;
-		LOGE("TODO: Re-implement wipe dalvik into Partition Manager!\n");
-        if (1) //if (0 != stat(sde.blk, &st))
-        {
-            ui_print("/sd-ext not present, skipping\n");
-        } else {
-        	__system("mount /sd-ext");
-    	    LOGI("Mounting /sd-ext\n");
-    	    if (stat("/sd-ext/dalvik-cache",&st) == 0)
-    	    {
-                __system("rm -rf /sd-ext/dalvik-cache");
-        	    ui_print("Cleaned: /sd-ext/dalvik-cache...\n");
-    	    }
-        }
-        ensure_path_unmounted("/data");
-        ui_print("-- Dalvik Cache Directories Wipe Complete!\n\n");
-        //ui_set_background(BACKGROUND_ICON_MAIN);
-        //if (!ui_text_visible()) return;
-}
-
-// BATTERY STATS
-void wipe_battery_stats()
-{
-    ensure_path_mounted("/data");
-    struct stat st;
-    if (0 != stat("/data/system/batterystats.bin", &st))
-    {
-        ui_print("No Battery Stats Found. No Need To Wipe.\n");
-    } else {
-        //ui_set_background(BACKGROUND_ICON_WIPE);
-        remove("/data/system/batterystats.bin");
-        ui_print("Cleared: Battery Stats...\n");
-        ensure_path_unmounted("/data");
-    }
-}
-
-// ROTATION SETTINGS
-void wipe_rotate_data()
-{
-    //ui_set_background(BACKGROUND_ICON_WIPE);
-    ensure_path_mounted("/data");
-    __system("rm -r /data/misc/akmd*");
-    __system("rm -r /data/misc/rild*");
-    ui_print("Cleared: Rotatation Data...\n");
-    ensure_path_unmounted("/data");
-}   
-
-void fix_perms()
-{
-	ensure_path_mounted("/data");
-	ensure_path_mounted("/system");
-	//ui_show_progress(1,30);
-    ui_print("\n-- Fixing Permissions\n");
-	ui_print("This may take a few minutes.\n");
-	__system("./sbin/fix_permissions.sh");
-	ui_print("-- Done.\n\n");
-	//ui_reset_progress();
-}
-
-int get_battery_level(void)
-{
-    static int lastVal = -1;
-    static time_t nextSecCheck = 0;
-
-    struct timeval curTime;
-    gettimeofday(&curTime, NULL);
-    if (curTime.tv_sec > nextSecCheck)
-    {
-        char cap_s[4];
-        FILE * cap = fopen("/sys/class/power_supply/battery/capacity","rt");
-        if (cap)
-        {
-            fgets(cap_s, 4, cap);
-            fclose(cap);
-            lastVal = atoi(cap_s);
-            if (lastVal > 100)  lastVal = 101;
-            if (lastVal < 0)    lastVal = 0;
-        }
-        nextSecCheck = curTime.tv_sec + 60;
-    }
-    return lastVal;
-}
-
 void update_tz_environment_variables() {
     setenv("TZ", DataManager_GetStrValue(TW_TIME_ZONE_VAR), 1);
     tzset();
@@ -478,56 +382,6 @@
 		//if (!ui_text_visible()) return;
 }
 
-void install_htc_dumlock(void)
-{
-	struct statfs fs1, fs2;
-	int need_libs = 0;
-
-	ui_print("Installing HTC Dumlock to system...\n");
-	ensure_path_mounted("/system");
-	__system("cp /res/htcd/htcdumlocksys /system/bin/htcdumlock && chmod 755 /system/bin/htcdumlock");
-	if (statfs("/system/bin/flash_image", &fs1) != 0) {
-		ui_print("Installing flash_image...\n");
-		__system("cp /res/htcd/flash_imagesys /system/bin/flash_image && chmod 755 /system/bin/flash_image");
-		need_libs = 1;
-	} else
-		ui_print("flash_image is already installed, skipping...\n");
-	if (statfs("/system/bin/dump_image", &fs2) != 0) {
-		ui_print("Installing dump_image...\n");
-		__system("cp /res/htcd/dump_imagesys /system/bin/dump_image && chmod 755 /system/bin/dump_image");
-		need_libs = 1;
-	} else
-		ui_print("dump_image is already installed, skipping...\n");
-	if (need_libs) {
-		ui_print("Installing libs needed for flash_image and dump_image...\n");
-		__system("cp /res/htcd/libbmlutils.so /system/lib && chmod 755 /system/lib/libbmlutils.so");
-		__system("cp /res/htcd/libflashutils.so /system/lib && chmod 755 /system/lib/libflashutils.so");
-		__system("cp /res/htcd/libmmcutils.so /system/lib && chmod 755 /system/lib/libmmcutils.so");
-		__system("cp /res/htcd/libmtdutils.so /system/lib && chmod 755 /system/lib/libmtdutils.so");
-	}
-	ui_print("Installing HTC Dumlock app...\n");
-	ensure_path_mounted("/data");
-	mkdir("/data/app", 0777);
-	__system("rm /data/app/com.teamwin.htcdumlock*");
-	__system("cp /res/htcd/HTCDumlock.apk /data/app/com.teamwin.htcdumlock.apk");
-	sync();
-	ui_print("HTC Dumlock is installed.\n");
-}
-
-void htc_dumlock_restore_original_boot(void)
-{
-	ui_print("Restoring original boot...\n");
-	__system("htcdumlock restore");
-	ui_print("Original boot restored.\n");
-}
-
-void htc_dumlock_reflash_recovery_to_boot(void)
-{
-	ui_print("Reflashing recovery to boot...\n");
-	__system("htcdumlock recovery noreboot");
-	ui_print("Recovery is flashed to boot.\n");
-}
-
 void check_and_run_script(const char* script_file, const char* display_name)
 {
 	// Check for and run startup script if script exists
diff --git a/extra-functions.h b/extra-functions.h
index 6145e77..664ca33 100644
--- a/extra-functions.h
+++ b/extra-functions.h
@@ -8,22 +8,12 @@
 FILE * __popen(const char *program, const char *type);
 int __pclose(FILE *iop);
 
-void wipe_dalvik_cache();
-void wipe_battery_stats();
-void wipe_rotate_data();
-
 static long tmplog_offset = 0;
 
 void update_tz_environment_variables();
 
-void fix_perms();
-
 void run_script(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5, const char *str6, const char *str7, int request_confirm);
 
-void install_htc_dumlock(void);
-void htc_dumlock_restore_original_boot(void);
-void htc_dumlock_reflash_recovery_to_boot(void);
-
 void check_and_run_script(const char* script_file, const char* display_name);
 int check_backup_name(int show_error);
 void twfinish_recovery(const char *send_intent);
diff --git a/gui/action.cpp b/gui/action.cpp
index a1f7dd3..b050feb 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -19,6 +19,7 @@
 #include <string>
 #include <sstream>
 #include "../partitions.hpp"
+#include "../twrp-functions.hpp"
 
 extern "C" {
 #include "../common.h"
@@ -31,7 +32,6 @@
 #include "../twinstall.h"
 
 int TWinstall_zip(const char* path, int* wipe_cache);
-void fix_perms();
 void wipe_dalvik_cache(void);
 int check_backup_name(int show_error);
 void wipe_battery_stats(void);
@@ -667,62 +667,57 @@
             operation_start("Format");
             DataManager::SetValue("tw_partition", arg);
 
-			int ret_val = 0;
+			int ret_val = false;
 
 			if (simulate) {
 				simulate_progress_bar();
 			} else {
 				if (arg == "data")
-					PartitionManager.Factory_Reset();
+					ret_val = PartitionManager.Factory_Reset();
 				else if (arg == "battery")
-					wipe_battery_stats();
+					ret_val = PartitionManager.Wipe_Battery_Stats();
 				else if (arg == "rotate")
-					wipe_rotate_data();
+					ret_val = PartitionManager.Wipe_Rotate_Data();
 				else if (arg == "dalvik")
-					wipe_dalvik_cache();
+					ret_val = PartitionManager.Wipe_Dalvik_Cache();
 				else if (arg == "DATAMEDIA") {
-					LOGE("TODO: Implement formatting of datamedia device!\n");
-					ret_val = 1; //format_data_media();
-					int has_datamedia, dual_storage;
-
-					DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
-					DataManager::GetValue(TW_HAS_DUAL_STORAGE, dual_storage);
-					if (has_datamedia && !dual_storage) {
-						system("umount /sdcard");
-						system("mount /data/media /sdcard");
-					}
+					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) {
-						PartitionManager.Mount_By_Path("/data", 1);
-						__system("rm -rf /data/media");
-						__system("cd /data && mkdir media && chmod 775 media");
-						DataManager::GetValue(TW_HAS_DUAL_STORAGE, dual_storage);
-						if (!dual_storage) {
-							system("umount /sdcard");
-							system("mount /data/media /sdcard");
-						}
+						ret_val = PartitionManager.Wipe_Media_From_Data();
 					} else {
-						ret_val = 0;
-						LOGE("Wipe not implemented yet!\n");
+						ret_val = PartitionManager.Wipe_By_Path(DataManager::GetSettingsStoragePath());
 					}
 				} else if (arg == "EXTERNAL") {
-					ret_val = 0;
-					LOGE("Wipe not implemented yet!\n");
-				} else
-					PartitionManager.Wipe_By_Path(arg);
+					string External_Path;
 
-				if (arg == "/sdcard") {
-					PartitionManager.Mount_By_Path("/sdcard", 1);
-					mkdir("/sdcard/TWRP", 0777);
-					DataManager::Flush();
+					DataManager::GetValue(TW_EXTERNAL_PATH, External_Path);
+					ret_val = PartitionManager.Wipe_By_Path(External_Path);
+				} else
+					ret_val = PartitionManager.Wipe_By_Path(arg);
+
+				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)) {
+						LOGI("Making TWRP folder and saving settings.\n");
+						Storage_Path += "/TWRP";
+						mkdir(Storage_Path.c_str(), 0777);
+						DataManager::Flush();
+					} else {
+						LOGE("Unable to recreate TWRP folder and save settings.\n");
+					}
 				}
 			}
 			PartitionManager.Update_System_Details();
-			if (ret_val != 0)
-				ret_val = 1;
+			if (ret_val)
+				ret_val = 0; // 0 is success
+			else
+				ret_val = 1; // 1 is failure
             operation_end(ret_val, simulate);
             return 0;
         }
@@ -770,7 +765,7 @@
 			if (simulate) {
 				simulate_progress_bar();
 			} else
-				fix_perms();
+				PartitionManager.Fix_Permissions();
 
 			LOGI("fix permissions DONE!\n");
 			operation_end(0, simulate);
@@ -870,7 +865,7 @@
 			if (simulate) {
 				simulate_progress_bar();
 			} else
-				install_htc_dumlock();
+				TWFunc::install_htc_dumlock();
 
 			operation_end(0, simulate);
 			return 0;
@@ -881,7 +876,7 @@
 			if (simulate) {
 				simulate_progress_bar();
 			} else
-				htc_dumlock_restore_original_boot();
+				TWFunc::htc_dumlock_restore_original_boot();
 
 			operation_end(0, simulate);
 			return 0;
@@ -892,7 +887,7 @@
 			if (simulate) {
 				simulate_progress_bar();
 			} else
-				htc_dumlock_reflash_recovery_to_boot();
+				TWFunc::htc_dumlock_reflash_recovery_to_boot();
 
 			operation_end(0, simulate);
 			return 0;
diff --git a/partition.cpp b/partition.cpp
index f3c79f7..f4fa0d8 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -38,6 +38,8 @@
 #include "partitions.hpp"
 #include "data.hpp"
 extern "C" {
+	#include "mtdutils/mtdutils.h"
+	#include "mtdutils/mounts.h"
 	#include "extra-functions.h"
 	int __system(const char *command);
 }
@@ -52,7 +54,8 @@
 	Symlink_Path = "";
 	Symlink_Mount_Point = "";
 	Mount_Point = "";
-	Block_Device = "";
+	Actual_Block_Device = "";
+	Primary_Block_Device = "";
 	Alternate_Block_Device = "";
 	Removable = false;
 	Is_Present = false;
@@ -68,6 +71,7 @@
 	Display_Name = "";
 	Backup_Name = "";
 	Backup_FileName = "";
+	MTD_Name = "";
 	Backup_Method = NONE;
 	Has_Data_Media = false;
 	Is_Storage = false;
@@ -109,15 +113,19 @@
 			item_index++;
 		} else if (item_index == 1) {
 			// Primary Block Device
-			if (*ptr != '/') {
+			if (Fstab_File_System == "mtd" || Fstab_File_System == "yaffs2") {
+				Primary_Block_Device = ptr;
+				Find_MTD_Block_Device(Primary_Block_Device);
+			} else if (*ptr != '/') {
 				if (Display_Error)
 					LOGE("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
 				else
 					LOGI("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
 				return 0;
+			} else {
+				Primary_Block_Device = ptr;
+				Find_Real_Block_Device(Primary_Block_Device, Display_Error);
 			}
-			Block_Device = ptr;
-			Find_Real_Block_Device(Block_Device, Display_Error);
 			item_index++;
 		} else if (item_index > 1) {
 			if (*ptr == '/') {
@@ -132,6 +140,8 @@
 				// Custom flags, save for later so that new values aren't overwritten by defaults
 				ptr += 6;
 				Flags = ptr;
+			} else if (strlen(ptr) == 4 && (strncmp(ptr, "NULL", 4) == 0 || strncmp(ptr, "null", 4) == 0 || strncmp(ptr, "null", 4) == 0)) {
+				// Do nothing
 			} else {
 				// Unhandled data
 				LOGI("Unhandled fstab information: '%s', %i\n", ptr, index);
@@ -148,14 +158,17 @@
 			LOGI("Unknown File System: '%s'\n", Fstab_File_System.c_str());
 		return 0;
 	} else if (Is_File_System(Fstab_File_System)) {
+		Find_Actual_Block_Device();
 		Setup_File_System(Display_Error);
 		if (Mount_Point == "/system") {
 			Display_Name = "System";
 			Wipe_Available_in_GUI = true;
+			MTD_Name = "system";
 		} else if (Mount_Point == "/data") {
 			Display_Name = "Data";
 			Wipe_Available_in_GUI = true;
 			Wipe_During_Factory_Reset = true;
+			MTD_Name = "userdata";
 #ifdef RECOVERY_SDCARD_ON_DATA
 			Has_Data_Media = true;
 			Is_Storage = true;
@@ -175,7 +188,7 @@
 			char crypto_blkdev[255];
 			property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
 			if (strcmp(crypto_blkdev, "error") != 0) {
-				DataManager::SetValue(TW_DATA_BLK_DEVICE, Block_Device);
+				DataManager::SetValue(TW_DATA_BLK_DEVICE, Primary_Block_Device);
 				DataManager::SetValue(TW_IS_DECRYPTED, 1);
 				Is_Encrypted = true;
 				Is_Decrypted = true;
@@ -194,6 +207,7 @@
 			Wipe_Available_in_GUI = true;
 			Wipe_During_Factory_Reset = true;
 			Update_Size(Display_Error);
+			MTD_Name = "cache";
 		} else if (Mount_Point == "/datadata") {
 			Wipe_During_Factory_Reset = true;
 			Display_Name = "DataData";
@@ -207,8 +221,10 @@
 		} else
 			Update_Size(Display_Error);
 	} else if (Is_Image(Fstab_File_System)) {
+		Find_Actual_Block_Device();
 		Setup_Image(Display_Error);
 		if (Mount_Point == "/boot") {
+			MTD_Name = "boot";
 			int backup_display_size = (int)(Backup_Size / 1048576LLU);
 			DataManager::SetValue(TW_BACKUP_BOOT_SIZE, backup_display_size);
 			if (Backup_Size == 0) {
@@ -217,6 +233,7 @@
 			} else
 				DataManager::SetValue(TW_HAS_BOOT_PARTITION, 1);
 		} else if (Mount_Point == "/recovery") {
+			MTD_Name = "recovery";
 			int backup_display_size = (int)(Backup_Size / 1048576LLU);
 			DataManager::SetValue(TW_BACKUP_RECOVERY_SIZE, backup_display_size);
 			if (Backup_Size == 0) {
@@ -337,13 +354,6 @@
 	Can_Be_Mounted = true;
 	Can_Be_Wiped = true;
 
-	// Check to see if the block device exists
-	if (Path_Exists(Block_Device)) {
-		Is_Present = true;
-	} else if (!Alternate_Block_Device.empty() && Path_Exists(Alternate_Block_Device)) {
-		Flip_Block_Device();
-		Is_Present = true;
-	}
 	// Make the mount point folder if it doesn't exist
 	Make_Dir(Mount_Point, Display_Error);
 	Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
@@ -352,12 +362,6 @@
 }
 
 void TWPartition::Setup_Image(bool Display_Error) {
-	if (Path_Exists(Block_Device)) {
-		Is_Present = true;
-	} else if (!Alternate_Block_Device.empty() && Path_Exists(Alternate_Block_Device)) {
-		Flip_Block_Device();
-		Is_Present = true;
-	}
 	Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
 	Backup_Name = Display_Name;
 	if (Fstab_File_System == "emmc")
@@ -371,9 +375,9 @@
 		Backup_Size = Size;
 	} else {
 		if (Display_Error)
-			LOGE("Unable to find parition size for '%s'\n", Block_Device.c_str());
+			LOGE("Unable to find parition size for '%s'\n", Mount_Point.c_str());
 		else
-			LOGI("Unable to find parition size for '%s'\n", Block_Device.c_str());
+			LOGI("Unable to find parition size for '%s'\n", Mount_Point.c_str());
 	}
 }
 
@@ -400,6 +404,47 @@
 	}
 }
 
+bool TWPartition::Find_MTD_Block_Device(string MTD_Name) {
+	FILE *fp = NULL;
+	char line[255];
+
+	fp = fopen("/proc/mtd", "rt");
+	if (fp == NULL) {
+		LOGE("Device does not support /proc/mtd\n");
+		return false;
+	}
+
+	while (fgets(line, sizeof(line), fp) != NULL)
+	{
+		char device[32], label[32];
+		unsigned long size = 0;
+		char* fstype = NULL;
+		int deviceId;
+
+		sscanf(line, "%s %lx %*s %*c%s", device, &size, label);
+
+		// Skip header and blank lines
+		if ((strcmp(device, "dev:") == 0) || (strlen(line) < 8))
+			continue;
+
+		// Strip off the trailing " from the label
+		label[strlen(label)-1] = '\0';
+
+		if (strcmp(label, MTD_Name.c_str()) == 0) {
+			// We found our device
+			// Strip off the trailing : from the device
+			device[strlen(device)-1] = '\0';
+			if (sscanf(device,"mtd%d", &deviceId) == 1) {
+				sprintf(device, "/dev/block/mtdblock%d", deviceId);
+				Primary_Block_Device = device;
+			}
+		}
+	}
+	fclose(fp);
+
+	return false;
+}
+
 bool TWPartition::Get_Size_Via_statfs(bool Display_Error) {
 	struct statfs st;
 	string Local_Path = Mount_Point + "/.";
@@ -432,7 +477,7 @@
 	if (!Mount(Display_Error))
 		return false;
 
-	min_len = Block_Device.size() + 2;
+	min_len = Actual_Block_Device.size() + 2;
 	sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
 	__system(command);
 	fp = fopen("/tmp/dfoutput.txt", "rt");
@@ -534,7 +579,7 @@
 
 		tmpdevice = "/dev/block/";
 		tmpdevice += device;
-		if (tmpdevice == Block_Device || tmpdevice == Alternate_Block_Device) {
+		if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
 			// Adjust block size to byte size
 			Size = blocks * 1024ULL;
 			fclose(fp);
@@ -559,7 +604,7 @@
 	string temp;
 
 	temp = Alternate_Block_Device;
-	Block_Device = Alternate_Block_Device;
+	Primary_Block_Device = Alternate_Block_Device;
 	Alternate_Block_Device = temp;
 }
 
@@ -590,55 +635,30 @@
 	} else if (!Can_Be_Mounted) {
 		return false;
 	}
-	if (Removable)
-		Check_FS_Type();
-	if (Is_Decrypted) {
-		if (mount(Decrypted_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
-			Check_FS_Type();
-			if (mount(Decrypted_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
-				if (Display_Error)
-					LOGE("Unable to mount decrypted block device '%s' to '%s'\n", Decrypted_Block_Device.c_str(), Mount_Point.c_str());
-				else
-					LOGI("Unable to mount decrypted block device '%s' to '%s'\n", Decrypted_Block_Device.c_str(), Mount_Point.c_str());
-				return false;
-			} else {
-				if (Removable)
-					Update_Size(Display_Error);
-				return true;
-			}
-		} else {
-			if (Removable)
-				Update_Size(Display_Error);
-			return true;
+
+	Find_Actual_Block_Device();
+
+	// Check the current file system before mounting
+	Check_FS_Type();
+
+	if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
+		if (Display_Error)
+			LOGE("Unable to mount '%s'\n", Mount_Point.c_str());
+		else
+			LOGI("Unable to mount '%s'\n", Mount_Point.c_str());
+		return false;
+	} else {
+		if (Removable)
+			Update_Size(Display_Error);
+
+		if (!Symlink_Mount_Point.empty()) {
+			string Command;
+
+			Command = "mount " + Symlink_Path + " " + Symlink_Mount_Point;
+			__system(Command.c_str());
 		}
+		return true;
 	}
-	if (mount(Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
-		Check_FS_Type();
-		if (mount(Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
-			if (!Alternate_Block_Device.empty() && Path_Exists(Alternate_Block_Device)) {
-				Flip_Block_Device();
-				Check_FS_Type();
-				if (mount(Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
-					if (Display_Error)
-						LOGE("Unable to mount '%s'\n", Mount_Point.c_str());
-					else
-						LOGI("Unable to mount '%s'\n", Mount_Point.c_str());
-					return false;
-				} else {
-					if (Removable)
-						Update_Size(Display_Error);
-					return true;
-				}
-			} else
-				return false;
-		} else {
-			if (Removable)
-				Update_Size(Display_Error);
-			return true;
-		}
-	}
-	if (Removable)
-		Update_Size(Display_Error);
 	return true;
 }
 
@@ -650,6 +670,9 @@
 		if (never_unmount_system == 1 && Mount_Point == "/system")
 			return true; // Never unmount system if you're not supposed to unmount it
 
+		if (!Symlink_Mount_Point.empty())
+			umount(Symlink_Mount_Point.c_str());
+
 		if (umount(Mount_Point.c_str()) != 0) {
 			if (Display_Error)
 				LOGE("Unable to unmount '%s'\n", Mount_Point.c_str());
@@ -664,33 +687,100 @@
 }
 
 bool TWPartition::Wipe() {
-	LOGI("STUB TWPartition::Wipe\n");
-	return 1;
+	if (!Can_Be_Wiped) {
+		LOGE("Partition '%s' cannot be wiped.\n", Mount_Point.c_str());
+		return false;
+	}
+
+	if (Has_Data_Media)
+		return Wipe_Data_Without_Wiping_Media();
+
+	int check;
+	DataManager::GetValue(TW_RM_RF_VAR, check);
+	if (check)
+		return Wipe_RMRF();
+
+	if (Current_File_System == "ext4")
+		return Wipe_EXT4();
+
+	if (Current_File_System == "ext2" || Current_File_System == "ext3")
+		return Wipe_EXT23();
+
+	if (Current_File_System == "vfat")
+		return Wipe_FAT();
+
+	if (Current_File_System == "yaffs2")
+		return Wipe_MTD();
+
+	LOGE("Unable to wipe '%s' -- unknown file system '%s'\n", Mount_Point.c_str(), Current_File_System.c_str());
+	return false;
 }
 
 bool TWPartition::Backup(string backup_folder) {
-	LOGI("STUB TWPartition::Backup, backup_folder: '%s'\n", backup_folder.c_str());
-	return 1;
+	if (Backup_Method == FILES)
+		return Backup_Tar(backup_folder);
+	else if (Backup_Method == DD)
+		return Backup_DD(backup_folder);
+	else if (Backup_Method == FLASH_UTILS)
+		return Backup_Dump_Image(backup_folder);
+	LOGE("Unknown backup method for '%s'\n", Mount_Point.c_str());
+	return false;
 }
 
 bool TWPartition::Restore(string restore_folder) {
-	LOGI("STUB TWPartition::Restore, restore_folder: '%s'\n", restore_folder.c_str());
-	return 1;
+	if (Backup_Method == FILES)
+		return Restore_Tar(restore_folder);
+	else if (Backup_Method == DD)
+		return Restore_DD(restore_folder);
+	else if (Backup_Method == FLASH_UTILS)
+		return Restore_Flash_Image(restore_folder);
+	LOGE("Unknown restore method for '%s'\n", Mount_Point.c_str());
+	return false;
 }
 
 string TWPartition::Backup_Method_By_Name() {
-	LOGI("STUB TWPartition::Backup_Method_By_Name\n");
-	return "STUB";
+	if (Backup_Method == NONE)
+		return "none";
+	else if (Backup_Method == FILES)
+		return "files";
+	else if (Backup_Method == DD)
+		return "dd";
+	else if (Backup_Method == FLASH_UTILS)
+		return "flash_utils";
+	else
+		return "undefined";
+	return "ERROR!";
 }
 
 bool TWPartition::Decrypt(string Password) {
 	LOGI("STUB TWPartition::Decrypt, password: '%s'\n", Password.c_str());
+	// Is this needed?
 	return 1;
 }
 
 bool TWPartition::Wipe_Encryption() {
-	LOGI("STUB TWPartition::Wipe_Encryption\n");
-	return 1;
+	bool Save_Data_Media = Has_Data_Media;
+
+	if (!UnMount(true))
+		return false;
+
+	Current_File_System = Fstab_File_System;
+	Is_Encrypted = false;
+	Is_Decrypted = false;
+	Decrypted_Block_Device = "";
+	Has_Data_Media = false;
+	if (Wipe()) {
+		Has_Data_Media = Save_Data_Media;
+		if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
+			Recreate_Media_Folder();
+		}
+		return true;
+	} else {
+		Has_Data_Media = Save_Data_Media;
+		LOGE("Unable to format to remove encryption.\n");
+		return false;
+	}
+	return false;
 }
 
 void TWPartition::Check_FS_Type() {
@@ -704,10 +794,8 @@
 	if (Fstab_File_System == "yaffs2" || Fstab_File_System == "mtd")
 		return; // Running blkid on some mtd devices causes a massive crash
 
-	if (Is_Decrypted)
-		blkCommand = "blkid " + Decrypted_Block_Device + " > /tmp/blkidoutput.txt";
-	else
-		blkCommand = "blkid " + Block_Device + " > /tmp/blkidoutput.txt";
+	Find_Actual_Block_Device();
+	blkCommand = "blkid " + Actual_Block_Device + " > /tmp/blkidoutput.txt";
 
 	__system(blkCommand.c_str());
 	fp = fopen("/tmp/blkidoutput.txt", "rt");
@@ -764,33 +852,165 @@
 }
 
 bool TWPartition::Wipe_EXT23() {
-	LOGI("STUB TWPartition::Wipe_EXT23\n");
-	return 1;
+	if (!UnMount(true))
+		return false;
+
+	if (Path_Exists("/sbin/mke2fs")) {
+		char command[512];
+
+		ui_print("Formatting %s using mke2fs...\n", Display_Name.c_str());
+		Find_Actual_Block_Device();
+		sprintf(command, "mke2fs -t %s -m 0 %s", Current_File_System.c_str(), Actual_Block_Device.c_str());
+		LOGI("mke2fs command: %s\n", command);
+		if (__system(command) == 0) {
+			ui_print("Done.\n");
+			return true;
+		} else {
+			LOGE("Unable to wipe '%s'.\n", Mount_Point.c_str());
+			return false;
+		}
+	} else
+		return Wipe_RMRF();
+
+	return false;
 }
 
 bool TWPartition::Wipe_EXT4() {
-	LOGI("STUB TWPartition::Wipe_EXT4\n");
-	return 1;
+	if (!UnMount(true))
+		return false;
+
+	if (Path_Exists("/sbin/make_ext4fs")) {
+		string Command;
+
+		ui_print("Formatting %s using make_ext4fs...\n", Display_Name.c_str());
+		Find_Actual_Block_Device();
+		Command = "make_ext4fs";
+		if (!Is_Decrypted && Length != 0) {
+			// Only use length if we're not decrypted
+			char len[32];
+			sprintf(len, "%i", Length);
+			Command += " -l ";
+			Command += len;
+		}
+		Command += " " + Actual_Block_Device;
+		LOGI("make_ext4fs command: %s\n", Command.c_str());
+		if (__system(Command.c_str()) == 0) {
+			ui_print("Done.\n");
+			return true;
+		} else {
+			LOGE("Unable to wipe '%s'.\n", Mount_Point.c_str());
+			return false;
+		}
+	} else
+		return Wipe_EXT23();
+
+	return false;
 }
 
 bool TWPartition::Wipe_FAT() {
-	LOGI("STUB TWPartition::Wipe_FAT\n");
-	return 1;
+	char command[512];
+
+	if (Backup_Name == "and-sec") // Don't format if it's android secure
+		return Wipe_RMRF();
+
+	if (Path_Exists("/sbin/mkdosfs")) {
+		if (!UnMount(true))
+			return false;
+
+		ui_print("Formatting %s using mkdosfs...\n", Display_Name.c_str());
+		Find_Actual_Block_Device();
+		sprintf(command,"mkdosfs %s", Actual_Block_Device.c_str()); // use mkdosfs to format it
+		if (__system(command) == 0) {
+			ui_print("Done.\n");
+			return true;
+		} else {
+			LOGE("Unable to wipe '%s'.\n", Mount_Point.c_str());
+			return false;
+		}
+		return true;
+	}
+	else
+		return Wipe_RMRF();
+
+	return false;
 }
 
-bool TWPartition::Wipe_YAFFS2() {
-	LOGI("STUB TWPartition::Wipe_YAFFS2\n");
-	return 1;
+bool TWPartition::Wipe_MTD() {
+	if (!UnMount(true))
+		return false;
+
+	ui_print("MTD Formatting \"%s\"\n", MTD_Name.c_str());
+
+    mtd_scan_partitions();
+    const MtdPartition* mtd = mtd_find_partition_by_name(MTD_Name.c_str());
+    if (mtd == NULL) {
+        LOGE("No mtd partition named '%s'", MTD_Name.c_str());
+        return false;
+    }
+
+    MtdWriteContext* ctx = mtd_write_partition(mtd);
+    if (ctx == NULL) {
+        LOGE("Can't write '%s', failed to format.", MTD_Name.c_str());
+        return false;
+    }
+    if (mtd_erase_blocks(ctx, -1) == -1) {
+        mtd_write_close(ctx);
+        LOGE("Failed to format '%s'", MTD_Name.c_str());
+        return false;
+    }
+    if (mtd_write_close(ctx) != 0) {
+        LOGE("Failed to close '%s'", MTD_Name.c_str());
+        return false;
+    }
+	ui_print("Done.\n");
+    return true;
 }
 
 bool TWPartition::Wipe_RMRF() {
-	LOGI("STUB TWPartition::Wipe_RMRF\n");
-	return 1;
+	char cmd[512];
+
+	if (!Mount(true))
+		return false;
+
+	if (Backup_Name == "and-sec") {
+		ui_print("Using rm -rf on .android_secure\n");
+		sprintf(cmd, "rm -rf %s/.android_secure/* && rm -rf %s/.android_secure/.*", Mount_Point.c_str(), Mount_Point.c_str());
+	} else {
+		ui_print("Using rm -rf on '%s'\n", Mount_Point.c_str());
+		sprintf(cmd, "rm -rf %s/* && rm -rf %s/.*", Mount_Point.c_str(), Mount_Point.c_str());
+	}
+
+	LOGI("rm -rf command is: '%s'\n", cmd);
+	__system(cmd);
+    return true;
 }
 
 bool TWPartition::Wipe_Data_Without_Wiping_Media() {
-	LOGI("STUB TWPartition::Wipe_Data_Without_Wiping_Media\n");
-	return 1;
+	char cmd[256];
+
+	// This handles wiping data on devices with "sdcard" in /data/media
+	if (!Mount(true))
+		return false;
+
+	ui_print("Wiping data without wiping /data/media ...\n");
+	__system("rm -f /data/*");
+	__system("rm -f /data/.*");
+
+	DIR* d;
+	d = opendir("/data");
+	if (d != NULL)
+	{
+		struct dirent* de;
+		while ((de = readdir(d)) != NULL) {
+			if (strcmp(de->d_name, "media") == 0)   continue;
+
+			sprintf(cmd, "rm -fr /data/%s", de->d_name);
+			__system(cmd);
+		}
+		closedir(d);
+	}
+	ui_print("Done.\n");
+	return true;
 }
 
 bool TWPartition::Backup_Tar(string backup_folder) {
@@ -820,6 +1040,7 @@
 
 bool TWPartition::Restore_Flash_Image(string restore_folder) {
 	LOGI("STUB TWPartition::Restore_Flash_Image, backup_folder: '%s'\n", restore_folder.c_str());
+	// might erase image first just to ensure that it flashes
 	return 1;
 }
 
@@ -829,7 +1050,10 @@
 	if (!Can_Be_Mounted)
 		return false;
 
-	if (!Mount(Display_Error))
+	if (Removable || Is_Encrypted) {
+		if (!Mount(false))
+			return true;
+	} else if (!Mount(Display_Error))
 		return false;
 
 	ret = Get_Size_Via_statfs(Display_Error);
@@ -854,3 +1078,34 @@
 	}
 	return true;
 }
+
+void TWPartition::Find_Actual_Block_Device(void) {
+	if (Is_Decrypted) {
+		Actual_Block_Device = Decrypted_Block_Device;
+		if (Path_Exists(Primary_Block_Device))
+			Is_Present = true;
+	} else if (Path_Exists(Primary_Block_Device)) {
+		Is_Present = true;
+		Actual_Block_Device = Primary_Block_Device;
+	} else if (!Alternate_Block_Device.empty() && Path_Exists(Alternate_Block_Device)) {
+		Flip_Block_Device();
+		Actual_Block_Device = Primary_Block_Device;
+		Is_Present = true;
+	} else
+		Is_Present = false;
+}
+
+void TWPartition::Recreate_Media_Folder(void) {
+	string Command;
+
+	if (!Mount(true)) {
+		LOGE("Unable to recreate /data/media folder.\n");
+	} else {
+		LOGI("Recreating /data/media folder.\n");
+		__system("cd /data && mkdir media && chmod 755 media");
+		Command = "umount " + Symlink_Mount_Point;
+		__system(Command.c_str());
+		Command = "mount " + Symlink_Path + " " + Symlink_Mount_Point;
+		__system(Command.c_str());
+	}
+}
\ No newline at end of file
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 21752a0..7ff5e8e 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -34,6 +34,12 @@
 #include "common.h"
 #include "partitions.hpp"
 #include "data.hpp"
+#include "twrp-functions.hpp"
+
+extern "C" {
+	#include "extra-functions.h"
+	int __system(const char *command);
+}
 
 #ifdef TW_INCLUDE_CRYPTO
 	#ifdef TW_INCLUDE_JB_CRYPTO
@@ -89,10 +95,7 @@
 	}
 	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
 		if ((*iter)->Can_Be_Mounted) {
-			if ((*iter)->Is_Decrypted)
-				Line = (*iter)->Decrypted_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n";
-			else
-				Line = (*iter)->Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n";
+			Line = (*iter)->Actual_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n";
 			fputs(Line.c_str(), fp);
 			// Handle subpartition tracking
 			if ((*iter)->Is_SubPartition) {
@@ -112,7 +115,7 @@
 	std::vector<TWPartition*>::iterator iter;
 	int ret = false;
 	bool found = false;
-	string Local_Path = Get_Root_Path(Path);
+	string Local_Path = TWFunc::Get_Root_Path(Path);
 
 	// Iterate through all partitions
 	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
@@ -181,7 +184,7 @@
 	std::vector<TWPartition*>::iterator iter;
 	int ret = false;
 	bool found = false;
-	string Local_Path = Get_Root_Path(Path);
+	string Local_Path = TWFunc::Get_Root_Path(Path);
 
 	// Iterate through all partitions
 	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
@@ -294,7 +297,7 @@
 
 TWPartition* TWPartitionManager::Find_Partition_By_Path(string Path) {
 	std::vector<TWPartition*>::iterator iter;
-	string Local_Path = Get_Root_Path(Path);
+	string Local_Path = TWFunc::Get_Root_Path(Path);
 
 	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
 		if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path))
@@ -307,7 +310,7 @@
 	std::vector<TWPartition*>::iterator iter;
 
 	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
-		if ((*iter)->Block_Device == Block || (*iter)->Alternate_Block_Device == Block || ((*iter)->Is_Decrypted && (*iter)->Decrypted_Block_Device == Block))
+		if ((*iter)->Primary_Block_Device == Block || (*iter)->Alternate_Block_Device == Block || ((*iter)->Is_Decrypted && (*iter)->Decrypted_Block_Device == Block))
 			return (*iter);
 	}
 	return NULL;
@@ -331,7 +334,7 @@
 int TWPartitionManager::Run_Restore(string Restore_Name) {
 	int check;
 	TWPartition* Part;
-
+LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
 	DataManager::GetValue(TW_RESTORE_SYSTEM_VAR, check);
 	if (check > 0) {
 		Part = Find_Partition_By_Path("/system");
@@ -389,7 +392,7 @@
 #ifdef SP1_NAME
 	DataManager::GetValue(TW_RESTORE_SP1_VAR, check);
 	if (check > 0) {
-		Part = Find_Partition_By_Path(Get_Root_Path(SP1_NAME));
+		Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP1_NAME));
 		if (Part) {
 			if (!Part->Restore(Restore_Name))
 				return false;
@@ -400,7 +403,7 @@
 #ifdef SP2_NAME
 	DataManager::GetValue(TW_RESTORE_SP2_VAR, check);
 	if (check > 0) {
-		Part = Find_Partition_By_Path(Get_Root_Path(SP2_NAME));
+		Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP2_NAME));
 		if (Part) {
 			if (!Part->Restore(Restore_Name))
 				return false;
@@ -411,7 +414,7 @@
 #ifdef SP3_NAME
 	DataManager::GetValue(TW_RESTORE_SP3_VAR, check);
 	if (check > 0) {
-		Part = Find_Partition_By_Path(Get_Root_Path(SP3_NAME));
+		Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP3_NAME));
 		if (Part) {
 			if (!Part->Restore(Restore_Name))
 				return false;
@@ -518,15 +521,15 @@
 		if (Part->Mount_Point == "/sd-ext")
 			tw_restore_sdext = 1;
 #ifdef SP1_NAME
-		if (Part->Mount_Point == Get_Root_Path(SP1_Name))
+		if (Part->Mount_Point == TWFunc::Get_Root_Path(SP1_Name))
 			tw_restore_sp1 = 1;
 #endif
 #ifdef SP2_NAME
-		if (Part->Mount_Point == Get_Root_Path(SP2_Name))
+		if (Part->Mount_Point == TWFunc::Get_Root_Path(SP2_Name))
 			tw_restore_sp2 = 1;
 #endif
 #ifdef SP3_NAME
-		if (Part->Mount_Point == Get_Root_Path(SP3_Name))
+		if (Part->Mount_Point == TWFunc::Get_Root_Path(SP3_Name))
 			tw_restore_sp3 = 1;
 #endif
 	}
@@ -551,7 +554,7 @@
 	std::vector<TWPartition*>::iterator iter;
 	int ret = false;
 	bool found = false;
-	string Local_Path = Get_Root_Path(Path);
+	string Local_Path = TWFunc::Get_Root_Path(Path);
 
 	// Iterate through all partitions
 	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
@@ -612,7 +615,7 @@
 	int ret = true;
 
 	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
-		if ((*iter)->Wipe_During_Factory_Reset) {
+		if ((*iter)->Wipe_During_Factory_Reset && (*iter)->Is_Present) {
 			if (!(*iter)->Wipe())
 				ret = false;
 		}
@@ -620,6 +623,101 @@
 	return ret;
 }
 
+int TWPartitionManager::Wipe_Dalvik_Cache(void) {
+	struct stat st;
+
+	if (!Mount_By_Path("/data", true))
+		return false;
+
+	if (!Mount_By_Path("/cache", true))
+		return false;
+
+	ui_print("\nWiping Dalvik Cache Directories...\n");
+	__system("rm -rf /data/dalvik-cache");
+	ui_print("Cleaned: /data/dalvik-cache...\n");
+	__system("rm -rf /cache/dalvik-cache");
+	ui_print("Cleaned: /cache/dalvik-cache...\n");
+	__system("rm -rf /cache/dc");
+	ui_print("Cleaned: /cache/dc\n");
+
+	TWPartition* sdext = Find_Partition_By_Path("/sd-ext");
+	if (sdext != NULL) {
+		if (sdext->Is_Present && sdext->Mount(false)) {
+			if (stat("/sd-ext/dalvik-cache", &st) == 0) {
+                __system("rm -rf /sd-ext/dalvik-cache");
+        	    ui_print("Cleaned: /sd-ext/dalvik-cache...\n");
+    	    }
+        }
+	}
+	ui_print("-- Dalvik Cache Directories Wipe Complete!\n\n");
+	return true;
+}
+
+int TWPartitionManager::Wipe_Rotate_Data(void) {
+	if (!Mount_By_Path("/data", true))
+		return false;
+
+	__system("rm -r /data/misc/akmd*");
+	__system("rm -r /data/misc/rild*");
+	ui_print("Rotation data wiped.\n");
+	return true;
+}
+
+int TWPartitionManager::Wipe_Battery_Stats(void) {
+	struct stat st;
+
+	if (!Mount_By_Path("/data", true))
+		return false;
+
+	if (0 != stat("/data/system/batterystats.bin", &st)) {
+		ui_print("No Battery Stats Found. No Need To Wipe.\n");
+	} else {
+		remove("/data/system/batterystats.bin");
+		ui_print("Cleared battery stats.\n");
+	}
+	return true;
+}
+
+int TWPartitionManager::Format_Data(void) {
+	TWPartition* dat = Find_Partition_By_Path("/data");
+
+	if (dat != NULL) {
+		if (!dat->UnMount(true))
+			return false;
+
+		return dat->Wipe_Encryption();
+	} else {
+		LOGE("Unable to locate /data.\n");
+		return false;
+	}
+	return false;
+}
+
+int TWPartitionManager::Wipe_Media_From_Data(void) {
+	TWPartition* dat = Find_Partition_By_Path("/data");
+
+	if (dat != NULL) {
+		if (!dat->Has_Data_Media) {
+			LOGE("This device does not have /data/media\n");
+			return false;
+		}
+		if (!dat->Mount(true))
+			return false;
+
+		ui_print("Wiping internal storage -- /data/media...\n");
+		__system("rm -rf /data/media");
+		__system("cd /data && mkdir media && chmod 775 media");
+		if (dat->Has_Data_Media) {
+			dat->Recreate_Media_Folder();
+		}
+		return true;
+	} else {
+		LOGE("Unable to locate /data.\n");
+		return false;
+	}
+	return false;
+}
+
 void TWPartitionManager::Refresh_Sizes(void) {
 	Update_System_Details();
 	return;
@@ -692,7 +790,7 @@
 	} else {
 		TWPartition* dat = Find_Partition_By_Path("/data");
 		if (dat != NULL) {
-			DataManager::SetValue(TW_DATA_BLK_DEVICE, dat->Block_Device);
+			DataManager::SetValue(TW_DATA_BLK_DEVICE, dat->Primary_Block_Device);
 			DataManager::SetValue(TW_IS_DECRYPTED, 1);
 			dat->Is_Decrypted = true;
 			dat->Decrypted_Block_Device = crypto_blkdev;
@@ -711,17 +809,15 @@
 	return 1;
 }
 
-string TWPartitionManager::Get_Root_Path(string Path) {
-	string Local_Path = Path;
+int TWPartitionManager::Fix_Permissions(void) {
+	if (!Mount_By_Path("/data", true))
+		return false;
 
-	// Make sure that we have a leading slash
-	if (Local_Path.substr(0, 1) != "/")
-		Local_Path = "/" + Local_Path;
+	if (!Mount_By_Path("/system", true))
+		return false;
 
-	// Trim the path to get the root path only
-	size_t position = Local_Path.find("/", 2);
-	if (position != string::npos) {
-		Local_Path.resize(position);
-	}
-	return Local_Path;
-}
+	ui_print("Fixing Permissions\nThis may take a few minutes.\n");
+	__system("./sbin/fix_permissions.sh");
+	ui_print("Done.\n\n");
+	return true;
+}
\ No newline at end of file
diff --git a/partitions.hpp b/partitions.hpp
index 0609712..5b7dc6d 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -57,9 +57,11 @@
 	virtual bool Wipe_Encryption();                                           // Ignores wipe commands for /data/media devices and formats the original block device
 	virtual void Check_FS_Type();                                             // Checks the fs type using blkid, does not do anything on MTD / yaffs2 because this crashes on some devices
 	virtual bool Update_Size(bool Display_Error);                             // Updates size information
+	virtual void Recreate_Media_Folder();                                     // Recreates the /data/media folder
 
 protected:
 	bool Process_Fstab_Line(string Line, bool Display_Error);                 // Processes a fstab line
+	void Find_Actual_Block_Device();                                          // Determines the correct block device and stores it in Actual_Block_Device
 
 protected:
 	bool Can_Be_Mounted;                                                      // Indicates that the partition can be mounted
@@ -72,8 +74,10 @@
 	string Symlink_Path;                                                      // Symlink path (e.g. /data/media)
 	string Symlink_Mount_Point;                                               // /sdcard could be the symlink mount point for /data/media
 	string Mount_Point;                                                       // Mount point for this partition (e.g. /system or /data)
-	string Block_Device;                                                      // Block device (e.g. /dev/block/mmcblk1p1)
+	string Actual_Block_Device;                                               // Actual block device (one of primary, alternate, or decrypted)
+	string Primary_Block_Device;                                              // Block device (e.g. /dev/block/mmcblk1p1)
 	string Alternate_Block_Device;                                            // Alternate block device (e.g. /dev/block/mmcblk1)
+	string Decrypted_Block_Device;                                            // Decrypted block device available after decryption
 	bool Removable;                                                           // Indicates if this partition is removable -- affects how often we check overall size, if present, etc.
 	bool Is_Present;                                                          // Indicates if the partition is currently present as a block device
 	int Length;                                                               // Used by make_ext4fs to leave free space at the end of the partition block for things like a crypto footer
@@ -84,10 +88,10 @@
 	bool Can_Be_Encrypted;                                                    // This partition might be encrypted, affects error handling, can only be true if crypto support is compiled in
 	bool Is_Encrypted;                                                        // This partition is thought to be encrypted -- it wouldn't mount for some reason, only avialble with crypto support
 	bool Is_Decrypted;                                                        // This partition has successfully been decrypted
-	string Decrypted_Block_Device;                                            // Decrypted block device available after decryption
 	string Display_Name;                                                      // Display name for the GUI
 	string Backup_Name;                                                       // Backup name -- used for backup filenames
 	string Backup_FileName;                                                   // Actual backup filename
+	string MTD_Name;                                                          // Name of the partition for MTD devices
 	Backup_Method_enum Backup_Method;                                         // Method used for backup
 	bool Has_Data_Media;                                                      // Indicates presence of /data/media, may affect wiping and backup methods
 	bool Is_Storage;                                                          // Indicates if this partition is used for storage for backup, restore, and installing zips
@@ -110,7 +114,7 @@
 	bool Wipe_EXT23();                                                        // Formats as ext3 or ext2
 	bool Wipe_EXT4();                                                         // Formats using ext4, uses make_ext4fs when present
 	bool Wipe_FAT();                                                          // Formats as FAT except that mkdosfs from busybox usually fails so oftentimes this is actually a rm -rf wipe
-	bool Wipe_YAFFS2();                                                       // Formats as yaffs2 for MTD memory types
+	bool Wipe_MTD();                                                       // Formats as yaffs2 for MTD memory types
 	bool Wipe_RMRF();                                                         // Uses rm -rf to wipe
 	bool Wipe_Data_Without_Wiping_Media();                                    // Uses rm -rf to wipe but does not wipe /data/media
 	bool Backup_Tar(string backup_folder);                                    // Backs up using tar for file systems
@@ -123,6 +127,7 @@
 	bool Get_Size_Via_df(bool Display_Error);                                 // Get Partition size, used, and free space using df command
 	unsigned long long Get_Folder_Size(string Path, bool Display_Error);      // Gets the size of the files in a folder and all of its subfolders
 	bool Make_Dir(string Path, bool Display_Error);                           // Creates a directory if it doesn't already exist
+	bool Find_MTD_Block_Device(string MTD_Name);                              // Finds the mtd block device based on the name from the fstab
 
 friend class TWPartitionManager;
 };
@@ -157,10 +162,15 @@
 	virtual int Wipe_By_Block(string Block);                                  // Wipes a partition based on block device
 	virtual int Wipe_By_Name(string Name);                                    // Wipes a partition based on display name
 	virtual int Factory_Reset();                                              // Performs a factory reset
+	virtual int Wipe_Dalvik_Cache();                                          // Wipes dalvik cache
+	virtual int Wipe_Rotate_Data();                                           // Wipes rotation data -- 
+	virtual int Wipe_Battery_Stats();                                         // Wipe battery stats -- /data/system/batterystats.bin
+	virtual int Format_Data();                                                // Really formats data on /data/media devices -- also removes encryption
+	virtual int Wipe_Media_From_Data();                                       // Removes and recreates the media folder on /data/media devices
 	virtual void Refresh_Sizes();                                             // Refreshes size data of partitions
 	virtual void Update_System_Details();                                     // Updates fstab, file systems, sizes, etc.
 	virtual int Decrypt_Device(string Password);                              // Attempt to decrypt any encrypted partitions
-	virtual string Get_Root_Path(string Path);                                // Trims any trailing folders or filenames from the path, also adds a leading / if not present
+	virtual int Fix_Permissions();                                            // Fixes permissions in /system and /data
 
 private:
 	std::vector<TWPartition*> Partitions;                                     // Vector list of all partitions
diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk
index 8b0f5cf..58268f9 100644
--- a/prebuilt/Android.mk
+++ b/prebuilt/Android.mk
@@ -53,6 +53,9 @@
 ifeq ($(TW_INCLUDE_JB_CRYPTO), true)
     RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcrypto.so
 endif
+ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
+    RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/make_ext4fs
+endif
 
 TWRP_AUTOGEN := $(intermediates)/teamwin
 
diff --git a/reboot.c b/reboot.c
index 0fbda81..9d87ff2 100644
--- a/reboot.c
+++ b/reboot.c
@@ -42,8 +42,6 @@
 	// Always force a sync before we reboot
     sync();
 
-    ensure_path_unmounted("/sdcard");
-
     switch (command)
     {
     case rb_current:
diff --git a/recovery.cpp b/recovery.cpp
index 567a42e..743920c 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -32,7 +32,11 @@
 #include "bootloader.h"
 #include "common.h"
 #include "cutils/properties.h"
+#ifdef ANDROID_RB_RESTART
 #include "cutils/android_reboot.h"
+#else
+#include <sys/reboot.h>
+#endif
 #include "install.h"
 #include "minui/minui.h"
 #include "minzip/DirUtil.h"
@@ -929,6 +933,10 @@
     // Otherwise, get ready to boot the main system...
     finish_recovery(send_intent);
     ui->Print("Rebooting...\n");
+#ifdef ANDROID_RB_RESTART
     android_reboot(ANDROID_RB_RESTART, 0, 0);
+#else
+	reboot(RB_AUTOBOOT);
+#endif
     return EXIT_SUCCESS;
 }
diff --git a/roots.cpp b/roots.cpp
index e747473..69c98fc 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -274,7 +274,11 @@
     }
 
     if (strcmp(v->fs_type, "ext4") == 0) {
+#ifdef USE_EXT4
         int result = make_ext4fs(v->device, v->length, volume, sehandle);
+#else
+        int result = 0;
+#endif
         if (result != 0) {
             LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
             return -1;
diff --git a/twinstall.cpp b/twinstall.cpp
index 0c3d837..967528e 100644
--- a/twinstall.cpp
+++ b/twinstall.cpp
@@ -39,6 +39,7 @@
 #include "variables.h"
 #include "data.hpp"
 #include "partitions.hpp"
+#include "twrp-functions.hpp"
 
 extern "C" {
 #include "extra-functions.h"
@@ -422,98 +423,6 @@
     return NULL;
 }
 
-char* get_path (char* path) {
-        char *s;
-
-        /* Go to the end of the string.  */
-        s = path + strlen(path) - 1;
-
-        /* Strip off trailing /s (unless it is also the leading /).  */
-        while (path < s && s[0] == '/')
-                s--;
-
-        /* Strip the last component.  */
-        while (path <= s && s[0] != '/')
-                s--;
-
-        while (path < s && s[0] == '/')
-                s--;
-
-        if (s < path)
-                return (char*)(".");
-
-        s[1] = '\0';
-	return path;
-}
-
-/*
-    Checks md5 for a path
-    Return values:
-        -1 : MD5 does not exist
-        0 : Failed
-        1 : Success
-*/
-int check_md5(const char* path) {
-	FILE* fp;
-	char command[255], line[512], actual_md5[512], md5[512];
-	char md5file[PATH_MAX + 40];
-	char *ptr;
-	unsigned int line_len, index = 0;
-	struct stat st;
-
-	// Check to see if the filename.zip.md5 file exists
-	strcpy(md5file, path);
-    strcat(md5file, ".md5");
-	if (stat(md5file, &st) != 0)
-		return -1; // no MD5 file found
-
-	// Dump the md5 of the zip to a text file for reading
-	sprintf(command, "md5sum '%s' > /tmp/md5output.txt", path);
-	__system(command);
-	fp = fopen("/tmp/md5output.txt", "rt");
-	if (fp == NULL) {
-		LOGI("Unable to open /tmp/md5output.txt.\n");
-		return false;
-	}
-
-	while (fgets(line, sizeof(line), fp) != NULL)
-	{
-		line_len = strlen(line);
-		for (index = 0; index < line_len; index++) {
-			if (line[index] <= 32)
-				line[index] = '\0';
-		}
-		strcpy(actual_md5, line);
-		break;
-	}
-	fclose(fp);
-
-	// Read the filename.zip.md5 file
-	fp = fopen(md5file, "rt");
-	if (fp == NULL) {
-		LOGI("Unable to open '%s'.\n", md5file);
-		return false;
-	}
-
-	while (fgets(line, sizeof(line), fp) != NULL)
-	{
-		line_len = strlen(line);
-		for (index = 0; index < line_len; index++) {
-			if (line[index] <= 32)
-				line[index] = '\0';
-		}
-		strcpy(md5, line);
-		break;
-	}
-	fclose(fp);
-
-	// Comare the 2 MD5 values
-	if (strcmp(actual_md5, md5) == 0)
-		return 1;
-	LOGI("MD5 did not match: '%s' != '%s'\n", actual_md5, md5);
-	return 0;
-}
-
 extern "C" int TWinstall_zip(const char* path, int* wipe_cache) {
 	int err, zip_verify, md5_return, md5_verify;
 
@@ -525,7 +434,7 @@
 	}
 
 	ui_print("Checking for MD5 file...\n");
-	md5_return = check_md5(path);
+	md5_return = TWFunc::Check_MD5(path);
 	if (md5_return == 0) {
 		// MD5 did not match.
 		LOGE("Zip MD5 does not match.\nUnable to install zip.\n");
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
new file mode 100644
index 0000000..ccf0540
--- /dev/null
+++ b/twrp-functions.cpp
@@ -0,0 +1,164 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+#include <vector>
+#include <dirent.h>
+#include <time.h>
+
+#include "twrp-functions.hpp"
+#include "partitions.hpp"
+#include "common.h"
+extern "C" {
+	#include "extra-functions.h"
+	int __system(const char *command);
+}
+
+/*  Checks md5 for a path
+    Return values:
+        -1 : MD5 does not exist
+        0 : Failed
+        1 : Success */
+int TWFunc::Check_MD5(string File) {
+	int ret;
+	string Command, DirPath, MD5_File, Sline, Filename, MD5_File_Filename, OK;
+	char line[255];
+	size_t pos;
+
+	MD5_File = File + ".md5";
+	if (access(MD5_File.c_str(), F_OK ) != -1) {
+		DirPath = Get_Path(File);
+		chdir(DirPath.c_str());
+		MD5_File = Get_Filename(MD5_File);
+		Command = "/sbin/busybox md5sum -c '" + MD5_File + "' > /tmp/md5output";
+		__system(Command.c_str());
+		FILE * cs = fopen("/tmp/md5output", "r");
+		if (cs == NULL) {
+			LOGE("Unable to open md5 output file.\n");
+			return 0;
+		}
+
+		fgets(line, sizeof(line), cs);
+
+		Sline = line;
+		pos = Sline.find(":");
+		if (pos != string::npos) {
+			Filename = Get_Filename(File);
+			MD5_File_Filename = Sline.substr(0, pos);
+			OK = Sline.substr(pos + 2, Sline.size() - pos - 2);
+			if (Filename == MD5_File_Filename && (OK == "OK" || OK == "OK\n")) {
+				//MD5 is good, return 1
+				ret = 1;
+			} else {
+				// MD5 is bad, return 0
+				ret = 0;
+			}
+		} else {
+			// MD5 is bad, return 0
+			ret = 0;
+		}
+		fclose(cs);
+	} else {
+		//No md5 file, return -1
+		ret = -1;
+	}
+
+    return ret;
+}
+
+// Returns "file.name" from a full /path/to/file.name
+string TWFunc::Get_Filename(string Path) {
+	size_t pos = Path.find_last_of("/");
+	if (pos != string::npos) {
+		string Filename;
+		Filename = Path.substr(pos + 1, Path.size() - pos - 1);
+		return Filename;
+	} else
+		return Path;
+}
+
+// Returns "/path/to/" from a full /path/to/file.name
+string TWFunc::Get_Path(string Path) {
+	size_t pos = Path.find_last_of("/");
+	if (pos != string::npos) {
+		string Pathonly;
+		Pathonly = Path.substr(0, pos + 1);
+		return Pathonly;
+	} else
+		return Path;
+}
+
+// Returns "/path" from a full /path/to/file.name
+string TWFunc::Get_Root_Path(string Path) {
+	string Local_Path = Path;
+
+	// Make sure that we have a leading slash
+	if (Local_Path.substr(0, 1) != "/")
+		Local_Path = "/" + Local_Path;
+
+	// Trim the path to get the root path only
+	size_t position = Local_Path.find("/", 2);
+	if (position != string::npos) {
+		Local_Path.resize(position);
+	}
+	return Local_Path;
+}
+
+void TWFunc::install_htc_dumlock(void) {
+	struct statfs fs1, fs2;
+	int need_libs = 0;
+
+	if (!PartitionManager.Mount_By_Path("/system", true))
+		return;
+
+	if (!PartitionManager.Mount_By_Path("/data", true))
+		return;
+
+	ui_print("Installing HTC Dumlock to system...\n");
+	__system("cp /res/htcd/htcdumlocksys /system/bin/htcdumlock && chmod 755 /system/bin/htcdumlock");
+	if (statfs("/system/bin/flash_image", &fs1) != 0) {
+		ui_print("Installing flash_image...\n");
+		__system("cp /res/htcd/flash_imagesys /system/bin/flash_image && chmod 755 /system/bin/flash_image");
+		need_libs = 1;
+	} else
+		ui_print("flash_image is already installed, skipping...\n");
+	if (statfs("/system/bin/dump_image", &fs2) != 0) {
+		ui_print("Installing dump_image...\n");
+		__system("cp /res/htcd/dump_imagesys /system/bin/dump_image && chmod 755 /system/bin/dump_image");
+		need_libs = 1;
+	} else
+		ui_print("dump_image is already installed, skipping...\n");
+	if (need_libs) {
+		ui_print("Installing libs needed for flash_image and dump_image...\n");
+		__system("cp /res/htcd/libbmlutils.so /system/lib && chmod 755 /system/lib/libbmlutils.so");
+		__system("cp /res/htcd/libflashutils.so /system/lib && chmod 755 /system/lib/libflashutils.so");
+		__system("cp /res/htcd/libmmcutils.so /system/lib && chmod 755 /system/lib/libmmcutils.so");
+		__system("cp /res/htcd/libmtdutils.so /system/lib && chmod 755 /system/lib/libmtdutils.so");
+	}
+	ui_print("Installing HTC Dumlock app...\n");
+	mkdir("/data/app", 0777);
+	__system("rm /data/app/com.teamwin.htcdumlock*");
+	__system("cp /res/htcd/HTCDumlock.apk /data/app/com.teamwin.htcdumlock.apk");
+	sync();
+	ui_print("HTC Dumlock is installed.\n");
+}
+
+void TWFunc::htc_dumlock_restore_original_boot(void) {
+	if (!PartitionManager.Mount_By_Path("/sdcard", true))
+		return;
+
+	ui_print("Restoring original boot...\n");
+	__system("htcdumlock restore");
+	ui_print("Original boot restored.\n");
+}
+
+void TWFunc::htc_dumlock_reflash_recovery_to_boot(void) {
+	if (!PartitionManager.Mount_By_Path("/sdcard", true))
+		return;
+
+	ui_print("Reflashing recovery to boot...\n");
+	__system("htcdumlock recovery noreboot");
+	ui_print("Recovery is flashed to boot.\n");
+}
diff --git a/twrp-functions.hpp b/twrp-functions.hpp
new file mode 100644
index 0000000..19f8eec
--- /dev/null
+++ b/twrp-functions.hpp
@@ -0,0 +1,23 @@
+#ifndef _TWRPFUNCTIONS_HPP
+#define _TWRPFUNCTIONS_HPP
+
+#include <string>
+
+using namespace std;
+
+// Partition class
+class TWFunc
+{
+public:
+	static int Check_MD5(string File);
+	static string Get_Root_Path(string Path);                                // Trims any trailing folders or filenames from the path, also adds a leading / if not present
+	static string Get_Path(string Path);                                     // Trims everything after the last / in the string
+	static string Get_Filename(string Path);                                 // Trims the path off of a filename
+
+	static void install_htc_dumlock(void);                                   // Installs HTC Dumlock
+	static void htc_dumlock_restore_original_boot(void);                     // Restores the backup of boot from HTC Dumlock
+	static void htc_dumlock_reflash_recovery_to_boot(void);                  // Reflashes the current recovery to boot
+
+};
+
+#endif // _TWRPFUNCTIONS_HPP
diff --git a/ui.cpp b/ui.cpp
index bd0fcae..27ecc28 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -28,7 +28,9 @@
 #include <time.h>
 #include <unistd.h>
 
+#ifdef ANDROID_RB_RESTART
 #include <cutils/android_reboot.h>
+#endif
 
 #include "common.h"
 #include "device.h"
@@ -131,7 +133,9 @@
             break;
 
           case RecoveryUI::REBOOT:
+#ifdef ANDROID_RB_RESTART
             android_reboot(ANDROID_RB_RESTART, 0, 0);
+#endif
             break;
 
           case RecoveryUI::ENQUEUE: