Add libtar to TWRP instead of using busybox tar
Add proper mkdosfs tool
Add fuse to TWRP
Add experimental exfat-fuse to TWRP
Convert all system() functions to use new Exec_Cmd function
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index 3a2658e..53a13f6 100644
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -1,15 +1,19 @@
 #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 <errno.h>
+#include <fcntl.h>
+#include <sys/mount.h>
 #include <sys/reboot.h>
-
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <iostream>
+#include <fstream>
 #include "twrp-functions.hpp"
 #include "partitions.hpp"
 #include "common.h"
@@ -17,6 +21,23 @@
 #include "bootloader.h"
 #include "variables.h"
 
+
+/* Execute a command */
+
+int TWFunc::Exec_Cmd(string cmd, string &result) {
+	FILE* exec;
+	char buffer[128];
+	int ret = 0;
+	exec = popen(cmd.c_str(), "r");
+	if (!exec) return -1;
+	while(!feof(exec)) {
+		if (fgets(buffer, 128, exec) != NULL)
+			result += buffer;
+	}
+	ret = pclose(exec);
+	return ret;
+}
+
 /*  Checks md5 for a path
     Return values:
         -1 : MD5 does not exist
@@ -27,28 +48,20 @@
 	string Command, DirPath, MD5_File, Sline, Filename, MD5_File_Filename, OK;
 	char line[255];
 	size_t pos;
+	string result;
 
 	MD5_File = File + ".md5";
 	if (Path_Exists(MD5_File)) {
 		DirPath = Get_Path(File);
 		MD5_File = Get_Filename(MD5_File);
-		Command = "cd '" + DirPath + "' && /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);
-		fclose(cs);
-
-		Sline = line;
-		pos = Sline.find(":");
+		chdir(DirPath.c_str());
+		Command = "/sbin/busybox md5sum -c " + MD5_File;
+		Exec_Cmd(Command, result);
+		pos = result.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);
+			MD5_File_Filename = result.substr(0, pos);
+			OK = result.substr(pos + 2, result.size() - pos - 2);
 			if (Filename == MD5_File_Filename && (OK == "OK" || OK == "OK\n")) {
 				//MD5 is good, return 1
 				ret = 1;
@@ -116,49 +129,50 @@
 		return;
 
 	ui_print("Installing HTC Dumlock to system...\n");
-	system("cp /res/htcd/htcdumlocksys /system/bin/htcdumlock && chmod 755 /system/bin/htcdumlock");
+	copy_file("/res/htcd/htcdumlocksys", "/system/bin/htcdumlock", 0755);
 	if (!Path_Exists("/system/bin/flash_image")) {
 		ui_print("Installing flash_image...\n");
-		system("cp /res/htcd/flash_imagesys /system/bin/flash_image && chmod 755 /system/bin/flash_image");
+		copy_file("/res/htcd/flash_imagesys", "/system/bin/flash_image", 0755);
 		need_libs = 1;
 	} else
 		ui_print("flash_image is already installed, skipping...\n");
 	if (!Path_Exists("/system/bin/dump_image")) {
 		ui_print("Installing dump_image...\n");
-		system("cp /res/htcd/dump_imagesys /system/bin/dump_image && chmod 755 /system/bin/dump_image");
+		copy_file("/res/htcd/dump_imagesys", "/system/bin/dump_image", 0755);
 		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");
+		copy_file("/res/htcd/libbmlutils.so", "/system/lib/libbmlutils.so", 0755);
+		copy_file("/res/htcd/libflashutils.so", "/system/lib/libflashutils.so", 0755);
+		copy_file("/res/htcd/libmmcutils.so", "/system/lib/libmmcutils.so", 0755);
+		copy_file("/res/htcd/libmtdutils.so", "/system/lib/libmtdutils.so", 0755);
 	}
 	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");
+	unlink("/data/app/com.teamwin.htcdumlock*");
+	copy_file("/res/htcd/HTCDumlock.apk", "/data/app/com.teamwin.htcdumlock.apk", 0777);
 	sync();
 	ui_print("HTC Dumlock is installed.\n");
 }
 
 void TWFunc::htc_dumlock_restore_original_boot(void) {
+	string status;
 	if (!PartitionManager.Mount_By_Path("/sdcard", true))
 		return;
 
 	ui_print("Restoring original boot...\n");
-	system("htcdumlock restore");
+	Exec_Cmd("htcdumlock restore", status);
 	ui_print("Original boot restored.\n");
 }
 
 void TWFunc::htc_dumlock_reflash_recovery_to_boot(void) {
+	string status;
 	if (!PartitionManager.Mount_By_Path("/sdcard", true))
 		return;
-
 	ui_print("Reflashing recovery to boot...\n");
-	system("htcdumlock recovery noreboot");
+	Exec_Cmd("htcdumlock recovery noreboot", status);
 	ui_print("Recovery is flashed to boot.\n");
 }
 
@@ -188,7 +202,7 @@
 	struct stat st;
 	char path2[4096], filename[4096];
 	unsigned long long dusize = 0;
-
+	unsigned long long dutemp = 0;
 	// Make a copy of path in case the data in the pointer gets overwritten later
 	strcpy(path2, Path.c_str());
 
@@ -196,6 +210,7 @@
 	if (d == NULL)
 	{
 		LOGE("error opening '%s'\n", path2);
+		LOGE("error: %s\n", strerror(errno));
 		return 0;
 	}
 
@@ -206,7 +221,9 @@
 			strcpy(filename, path2);
 			strcat(filename, "/");
 			strcat(filename, de->d_name);
-			dusize += Get_Folder_Size(filename, Display_Error);
+			dutemp = Get_Folder_Size(filename, Display_Error);
+			dusize += dutemp;
+			dutemp = 0;
 		}
 		else if (de->d_type == DT_REG)
 		{
@@ -218,14 +235,12 @@
 		}
 	}
 	closedir(d);
-
 	return dusize;
 }
 
 bool TWFunc::Path_Exists(string Path) {
 	// Check to see if the Path exists
 	struct stat st;
-
 	if (stat(Path.c_str(), &st) != 0)
 		return false;
 	else
@@ -305,39 +320,38 @@
 // record any intent we were asked to communicate back to the system.
 // this function is idempotent: call it as many times as you like.
 void TWFunc::twfinish_recovery(const char *send_intent) {
-    // By this point, we're ready to return to the main system...
-    if (send_intent != NULL) {
-        FILE *fp = fopen_path(INTENT_FILE, "w");
-        if (fp == NULL) {
-            LOGE("Can't open %s\n", INTENT_FILE);
-        } else {
-            fputs(send_intent, fp);
-            check_and_fclose(fp, INTENT_FILE);
-        }
-    }
+	// By this point, we're ready to return to the main system...
+	if (send_intent != NULL) {
+	FILE *fp = fopen_path(INTENT_FILE, "w");
+	if (fp == NULL) {
+	    LOGE("Can't open %s\n", INTENT_FILE);
+	} else {
+	    fputs(send_intent, fp);
+	    check_and_fclose(fp, INTENT_FILE);
+	}
+	}
 
-    // Copy logs to cache so the system can find out what happened.
-    copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true);
-    copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false);
-    copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false);
-    chmod(LOG_FILE, 0600);
-    chown(LOG_FILE, 1000, 1000);   // system user
-    chmod(LAST_LOG_FILE, 0640);
-    chmod(LAST_INSTALL_FILE, 0644);
+	// Copy logs to cache so the system can find out what happened.
+	copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true);
+	copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false);
+	copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false);
+	chmod(LOG_FILE, 0600);
+	chown(LOG_FILE, 1000, 1000);   // system user
+	chmod(LAST_LOG_FILE, 0640);
+	chmod(LAST_INSTALL_FILE, 0644);
 
-    // Reset to normal system boot so recovery won't cycle indefinitely.
-    struct bootloader_message boot;
-    memset(&boot, 0, sizeof(boot));
-    set_bootloader_message(&boot);
+	// Reset to normal system boot so recovery won't cycle indefinitely.
+	struct bootloader_message boot;
+	memset(&boot, 0, sizeof(boot));
+	set_bootloader_message(&boot);
 
-    // Remove the command file, so recovery won't repeat indefinitely.
-    if (system("mount /cache") != 0 ||
-        (unlink(COMMAND_FILE) && errno != ENOENT)) {
-        LOGW("Can't unlink %s\n", COMMAND_FILE);
-    }
+	// Remove the command file, so recovery won't repeat indefinitely.
+	if (!PartitionManager.Mount_By_Path("/system", true) || (unlink(COMMAND_FILE) && errno != ENOENT)) {
+        	LOGW("Can't unlink %s\n", COMMAND_FILE);
+	}
 
-    system("umount /cache");
-    sync();  // For good measure.
+	PartitionManager.UnMount_By_Path("/cache", true);
+	sync();  // For good measure.
 }
 
 // reboot: Reboot the system. Return -1 on error, no return on success
@@ -377,13 +391,65 @@
 {
 	// Check for and run startup script if script exists
 	struct stat st;
+	string result;
 	if (stat(script_file, &st) == 0) {
 		ui_print("Running %s script...\n", display_name);
-		char command[255];
-		strcpy(command, "chmod 755 ");
-		strcat(command, script_file);
-		system(command);
-		system(script_file);
+		chmod(script_file, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+		TWFunc::Exec_Cmd(script_file, result);
 		ui_print("\nFinished running %s script.\n", display_name);
 	}
 }
+
+int TWFunc::removeDir(const string path, bool skipParent) {
+        DIR *d = opendir(path.c_str());
+        int r = 0;
+        string new_path;
+
+        if (d == NULL) {
+                LOGE("Error opening '%s'\n", path.c_str());
+                return -1;
+        }
+
+        if (d) {
+                struct dirent *p;
+                while (!r && (p = readdir(d))) {
+			LOGI("checking :%s\n", p->d_name);
+                        if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
+                                continue;
+                        new_path = path + "/";
+                        new_path.append(p->d_name);
+                        if (p->d_type == DT_DIR) {
+                                r = removeDir(new_path, true);
+                                if (!r) {
+					if (p->d_type == DT_DIR) 
+						r = rmdir(new_path.c_str());
+					else
+						LOGI("Unable to removeDir '%s': %s\n", new_path.c_str(), strerror(errno));
+				}
+                        } else {
+                                r = unlink(new_path.c_str());
+                                if (!r)
+                                        LOGI("Unable to unlink '%s'\n", new_path.c_str());
+                        }
+                }
+                closedir(d);
+
+		if (!r) { 
+			if (skipParent)
+				return 0;
+			else
+				r = rmdir(path.c_str());
+		}
+        }
+        return r;
+}
+
+int TWFunc::copy_file(string src, string dst, int mode) {
+	LOGI("Copying file %s to %s\n", src.c_str(), dst.c_str());
+	ifstream srcfile(src.c_str(), ios::binary);
+	ofstream dstfile(dst.c_str(), ios::binary);
+	dstfile << srcfile.rdbuf();
+	srcfile.close();
+	dstfile.close();
+	return 0;
+}