Merge "Add vibrations to Checkbox, Fileselect, Listbox and Partitionlist" into android-4.4
diff --git a/Android.mk b/Android.mk
index 4ab358a..c6c7f3c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -353,7 +353,8 @@
     $(commands_recovery_local_path)/minuitwrp/Android.mk \
     $(commands_recovery_local_path)/openaes/Android.mk \
     $(commands_recovery_local_path)/toolbox/Android.mk \
-    $(commands_recovery_local_path)/libmincrypt/Android.mk
+    $(commands_recovery_local_path)/libmincrypt/Android.mk \
+    $(commands_recovery_local_path)/twrpTarMain/Android.mk
 
 ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true)
     include $(commands_recovery_local_path)/crypto/libcrypt_samsung/Android.mk
diff --git a/libtar/Android.mk b/libtar/Android.mk
index f936e96..1972573 100644
--- a/libtar/Android.mk
+++ b/libtar/Android.mk
@@ -1,5 +1,6 @@
 LOCAL_PATH := $(call my-dir)
 
+# Build shared library
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libtar
@@ -19,3 +20,22 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
+# Build static library
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libtar_static
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULES_TAGS = optional
+LOCAL_CFLAGS = 
+LOCAL_SRC_FILES = append.c block.c decode.c encode.c extract.c handle.c output.c util.c wrapper.c basename.c strmode.c libtar_hash.c libtar_list.c dirname.c
+LOCAL_C_INCLUDES += $(LOCAL_PATH) \
+					external/zlib
+LOCAL_STATIC_LIBRARIES += libz libc
+
+ifeq ($(TWHAVE_SELINUX), true)
+	LOCAL_C_INCLUDES += external/libselinux/include
+	LOCAL_STATIC_LIBRARIES += libselinux
+	LOCAL_CFLAGS += -DHAVE_SELINUX
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/libtar/append.c b/libtar/append.c
index dcd8649..514cf54 100644
--- a/libtar/append.c
+++ b/libtar/append.c
@@ -27,6 +27,9 @@
 # include <unistd.h>
 #endif
 
+#ifdef HAVE_SELINUX
+#include "selinux/selinux.h"
+#endif
 
 struct tar_dev
 {
diff --git a/openaes/Android.mk b/openaes/Android.mk
index 1beefda..360cf6c 100644
--- a/openaes/Android.mk
+++ b/openaes/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 ifneq ($(TW_EXCLUDE_ENCRYPTED_BACKUPS), true)
+	# Build shared binary
 	LOCAL_SRC_FILES:= src/oaes.c \
 	LOCAL_C_INCLUDES := \
 		bootable/recovery/openaes/src/isaac \
@@ -14,6 +15,7 @@
 	LOCAL_SHARED_LIBRARIES = libopenaes libc
 	include $(BUILD_EXECUTABLE)
 
+	# Build shared library
 	include $(CLEAR_VARS)
 	LOCAL_MODULE := libopenaes
 	LOCAL_MODULE_TAGS := eng
@@ -23,4 +25,15 @@
 	LOCAL_SRC_FILES = src/oaes_lib.c src/isaac/rand.c
 	LOCAL_SHARED_LIBRARIES = libc
 	include $(BUILD_SHARED_LIBRARY)
+
+	# Build static library
+	include $(CLEAR_VARS)
+	LOCAL_MODULE := libopenaes_static
+	LOCAL_MODULE_TAGS := eng
+	LOCAL_C_INCLUDES := \
+		bootable/recovery/openaes/src/isaac \
+		bootable/recovery/openaes/inc
+	LOCAL_SRC_FILES = src/oaes_lib.c src/isaac/rand.c
+	LOCAL_STATIC_LIBRARIES = libc
+	include $(BUILD_STATIC_LIBRARY)
 endif
diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp
index bede6d7..4479ec9 100644
--- a/openrecoveryscript.cpp
+++ b/openrecoveryscript.cpp
@@ -349,6 +349,10 @@
 					sideload = 1; // Causes device to go to the home screen afterwards
 					gui_print("Sideload finished.\n");
 				}
+			} else if (strcmp(command, "fixperms") == 0 || strcmp(command, "fixpermissions") == 0) {
+				ret_val = PartitionManager.Fix_Permissions();
+				if (ret_val != 0)
+					ret_val = 1; // failure
 			} else {
 				LOGERR("Unrecognized script command: '%s'\n", command);
 				ret_val = 1;
diff --git a/partition.cpp b/partition.cpp
index 3f19b7d..7427192 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -53,6 +53,7 @@
 }
 #ifdef HAVE_SELINUX
 #include "selinux/selinux.h"
+#include <selinux/label.h>
 #endif
 
 using namespace std;
@@ -1344,17 +1345,25 @@
 		return false;
 
 #if defined(HAVE_SELINUX) && defined(USE_EXT4)
+	int ret;
+	char *secontext = NULL;
+
 	gui_print("Formatting %s using make_ext4fs function.\n", Display_Name.c_str());
-	if (make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle) != 0) {
+
+	if (selabel_lookup(selinux_handle, &secontext, Mount_Point.c_str(), S_IFDIR) < 0) {
+		LOGINFO("Cannot lookup security context for '%s'\n", Mount_Point.c_str());
+		ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), NULL);
+	} else {
+		ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle);
+	}
+	if (ret != 0) {
 		LOGERR("Unable to wipe '%s' using function call.\n", Mount_Point.c_str());
 		return false;
 	} else {
-		#ifdef HAVE_SELINUX
 		string sedir = Mount_Point + "/lost+found";
 		PartitionManager.Mount_By_Path(sedir.c_str(), true);
 		rmdir(sedir.c_str());
 		mkdir(sedir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP);
-		#endif
 		return true;
 	}
 #else
@@ -1584,6 +1593,9 @@
 		tar.use_encryption = use_encryption;
 		if (Use_Userdata_Encryption)
 			tar.userdata_encryption = use_encryption;
+		string Password;
+		DataManager::GetValue("tw_backup_password", Password);
+		tar.setpassword(Password);
 	} else {
 		use_encryption = false;
 	}
@@ -1672,37 +1684,18 @@
 		return false;
 
 	Full_FileName = restore_folder + "/" + Backup_FileName;
-	/*if (!TWFunc::Path_Exists(Full_FileName)) {
-		if (!TWFunc::Path_Exists(Full_FileName)) {
-			// Backup is multiple archives
-			LOGINFO("Backup is multiple archives.\n");
-			sprintf(split_index, "%03i", index);
-			Full_FileName = restore_folder + "/" + Backup_FileName + split_index;
-			while (TWFunc::Path_Exists(Full_FileName)) {
-				index++;
-				gui_print("Restoring archive %i...\n", index);
-				LOGINFO("Restoring '%s'...\n", Full_FileName.c_str());
-				twrpTar tar;
-				tar.setdir("/");
-				tar.setfn(Full_FileName);
-				if (tar.extractTarFork() != 0)
-					return false;
-				sprintf(split_index, "%03i", index);
-				Full_FileName = restore_folder + "/" + Backup_FileName + split_index;
-			}
-			if (index == 0) {
-				LOGERR("Error locating restore file: '%s'\n", Full_FileName.c_str());
-				return false;
-			}
-		}
-	} else {*/
-		twrpTar tar;
-		tar.setdir(Backup_Path);
-		tar.setfn(Full_FileName);
-		tar.backup_name = Backup_Name;
-		if (tar.extractTarFork() != 0)
-			return false;
-	//}
+	twrpTar tar;
+	tar.setdir(Backup_Path);
+	tar.setfn(Full_FileName);
+	tar.backup_name = Backup_Name;
+#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
+	string Password;
+	DataManager::GetValue("tw_restore_password", Password);
+	if (!Password.empty())
+		tar.setpassword(Password);
+#endif
+	if (tar.extractTarFork() != 0)
+		return false;
 	return true;
 }
 
diff --git a/prebuilt/install-recovery.sh b/prebuilt/install-recovery.sh
index 9b43745..f62cf0b 100755
--- a/prebuilt/install-recovery.sh
+++ b/prebuilt/install-recovery.sh
@@ -5,15 +5,13 @@
 # to launch it from init.rc
 
 # Launches SuperSU in daemon mode only on Android 4.3+.
-# Nothing will happen on 4.2.x or older.
+# Nothing will happen on 4.2.x or older, unless SELinux+Enforcing.
 # If you want to force loading the daemon, use "--daemon" instead
 
 /system/xbin/daemonsu --auto-daemon &
 
-# Some apps like to run stuff from this script as well, but the
-# installer will have done "chattr +i" on this file to prevent
-# accidental modification and deletion. In your code, just search 
-# this file for "install-recovery-2.sh", and if present, write
-# there instead.
+# Some apps like to run stuff from this script as well, that will 
+# obviously break root - in your code, just search this file
+# for "install-recovery-2.sh", and if present, write there instead.
 
 /system/etc/install-recovery-2.sh
diff --git a/prebuilt/su b/prebuilt/su
index da77f0a..9415427 100755
--- a/prebuilt/su
+++ b/prebuilt/su
Binary files differ
diff --git a/twcommon.h b/twcommon.h
index 2c96d04..69cc7e6 100644
--- a/twcommon.h
+++ b/twcommon.h
@@ -5,9 +5,15 @@
 extern "C" {
 #endif
 
+#ifndef BUILD_TWRPTAR_MAIN
 #include "gui/gui.h"
 #define LOGERR(...) gui_print("E:" __VA_ARGS__)
 #define LOGINFO(...) fprintf(stdout, "I:" __VA_ARGS__)
+#else
+#define LOGERR(...) printf("E:" __VA_ARGS__)
+#define LOGINFO(...) printf("I:" __VA_ARGS__)
+#define gui_print(...) printf( __VA_ARGS__ )
+#endif
 
 #define STRINGIFY(x) #x
 #define EXPAND(x) STRINGIFY(x)
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index df71743..5145b26 100644
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -18,7 +18,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
+#include <string>
 #include <unistd.h>
 #include <vector>
 #include <dirent.h>
@@ -32,18 +32,20 @@
 #include <sys/vfs.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#ifdef ANDROID_RB_POWEROFF
-	#include "cutils/android_reboot.h"
-#endif
 #include <iostream>
 #include <fstream>
 #include <sstream>
 #include "twrp-functions.hpp"
-#include "partitions.hpp"
 #include "twcommon.h"
+#ifndef BUILD_TWRPTAR_MAIN
 #include "data.hpp"
+#include "partitions.hpp"
 #include "variables.h"
 #include "bootloader.h"
+#ifdef ANDROID_RB_POWEROFF
+	#include "cutils/android_reboot.h"
+#endif
+#endif // ndef BUILD_TWRPTAR_MAIN
 #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
 	#include "openaes/inc/oaes_lib.h"
 #endif
@@ -115,6 +117,165 @@
 		return Path;
 }
 
+int TWFunc::Wait_For_Child(pid_t pid, int *status, string Child_Name) {
+	pid_t rc_pid;
+
+	rc_pid = waitpid(pid, status, 0);
+	if (rc_pid > 0) {
+		if (WEXITSTATUS(*status) == 0)
+			LOGINFO("%s process ended with RC=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Success
+		else if (WIFSIGNALED(*status)) {
+			LOGINFO("%s process ended with signal: %d\n", Child_Name.c_str(), WTERMSIG(*status)); // Seg fault or some other non-graceful termination
+			return -1;
+		} else if (WEXITSTATUS(*status) != 0) {
+			LOGINFO("%s process ended with ERROR=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Graceful exit, but there was an error
+			return -1;
+		}
+	} else { // no PID returned
+		if (errno == ECHILD)
+			LOGINFO("%s no child process exist\n", Child_Name.c_str());
+		else {
+			LOGINFO("%s Unexpected error\n", Child_Name.c_str());
+			return -1;
+		}
+	}
+	return 0;
+}
+
+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
+		return true;
+}
+
+int TWFunc::Get_File_Type(string fn) {
+	string::size_type i = 0;
+	int firstbyte = 0, secondbyte = 0;
+	char header[3];
+
+	ifstream f;
+	f.open(fn.c_str(), ios::in | ios::binary);
+	f.get(header, 3);
+	f.close();
+	firstbyte = header[i] & 0xff;
+	secondbyte = header[++i] & 0xff;
+
+	if (firstbyte == 0x1f && secondbyte == 0x8b)
+		return 1; // Compressed
+	else if (firstbyte == 0x4f && secondbyte == 0x41)
+		return 2; // Encrypted
+	else
+		return 0; // Unknown
+
+	return 0;
+}
+
+int TWFunc::Try_Decrypting_File(string fn, string password) {
+#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
+	OAES_CTX * ctx = NULL;
+	uint8_t _key_data[32] = "";
+	FILE *f;
+	uint8_t buffer[4096];
+	uint8_t *buffer_out = NULL;
+	uint8_t *ptr = NULL;
+	size_t read_len = 0, out_len = 0;
+	int firstbyte = 0, secondbyte = 0, key_len;
+	size_t _j = 0;
+	size_t _key_data_len = 0;
+
+	// mostly kanged from OpenAES oaes.c
+	for( _j = 0; _j < 32; _j++ )
+		_key_data[_j] = _j + 1;
+	_key_data_len = password.size();
+	if( 16 >= _key_data_len )
+		_key_data_len = 16;
+	else if( 24 >= _key_data_len )
+		_key_data_len = 24;
+	else
+	_key_data_len = 32;
+	memcpy(_key_data, password.c_str(), password.size());
+
+	ctx = oaes_alloc();
+	if (ctx == NULL) {
+		LOGERR("Failed to allocate OAES\n");
+		return -1;
+	}
+
+	oaes_key_import_data(ctx, _key_data, _key_data_len);
+
+	f = fopen(fn.c_str(), "rb");
+	if (f == NULL) {
+		LOGERR("Failed to open '%s' to try decrypt\n", fn.c_str());
+		return -1;
+	}
+	read_len = fread(buffer, sizeof(uint8_t), 4096, f);
+	if (read_len <= 0) {
+		LOGERR("Read size during try decrypt failed\n");
+		fclose(f);
+		return -1;
+	}
+	if (oaes_decrypt(ctx, buffer, read_len, NULL, &out_len) != OAES_RET_SUCCESS) {
+		LOGERR("Error: Failed to retrieve required buffer size for trying decryption.\n");
+		fclose(f);
+		return -1;
+	}
+	buffer_out = (uint8_t *) calloc(out_len, sizeof(char));
+	if (buffer_out == NULL) {
+		LOGERR("Failed to allocate output buffer for try decrypt.\n");
+		fclose(f);
+		return -1;
+	}
+	if (oaes_decrypt(ctx, buffer, read_len, buffer_out, &out_len) != OAES_RET_SUCCESS) {
+		LOGERR("Failed to decrypt file '%s'\n", fn.c_str());
+		fclose(f);
+		free(buffer_out);
+		return 0;
+	}
+	fclose(f);
+	if (out_len < 2) {
+		LOGINFO("Successfully decrypted '%s' but read length %i too small.\n", fn.c_str(), out_len);
+		free(buffer_out);
+		return 1; // Decrypted successfully
+	}
+	ptr = buffer_out;
+	firstbyte = *ptr & 0xff;
+	ptr++;
+	secondbyte = *ptr & 0xff;
+	if (firstbyte == 0x1f && secondbyte == 0x8b) {
+		LOGINFO("Successfully decrypted '%s' and file is compressed.\n", fn.c_str());
+		free(buffer_out);
+		return 3; // Compressed
+	}
+	if (out_len >= 262) {
+		ptr = buffer_out + 257;
+		if (strncmp((char*)ptr, "ustar", 5) == 0) {
+			LOGINFO("Successfully decrypted '%s' and file is tar format.\n", fn.c_str());
+			free(buffer_out);
+			return 2; // Tar
+		}
+	}
+	free(buffer_out);
+	LOGINFO("No errors decrypting '%s' but no known file format.\n", fn.c_str());
+	return 1; // Decrypted successfully
+#else
+	LOGERR("Encrypted backup support not included.\n");
+	return -1;
+#endif
+}
+
+unsigned long TWFunc::Get_File_Size(string Path) {
+	struct stat st;
+
+	if (stat(Path.c_str(), &st) != 0)
+		return 0;
+	return st.st_size;
+}
+
+#ifndef BUILD_TWRPTAR_MAIN
+
 // Returns "/path" from a full /path/to/file.name
 string TWFunc::Get_Root_Path(string Path) {
 	string Local_Path = Path;
@@ -206,15 +367,6 @@
 	return true;
 }
 
-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
-		return true;
-}
-
 void TWFunc::GUI_Operation_Text(string Read_Value, string Default_Text) {
 	string Display_Text;
 
@@ -237,14 +389,6 @@
 	DataManager::SetValue("tw_partition", Partition_Name);
 }
 
-unsigned long TWFunc::Get_File_Size(string Path) {
-	struct stat st;
-
-	if (stat(Path.c_str(), &st) != 0)
-		return 0;
-	return st.st_size;
-}
-
 void TWFunc::Copy_Log(string Source, string Destination) {
 	PartitionManager.Mount_By_Path(Destination, false);
 	FILE *destination_log = fopen(Destination.c_str(), "a");
@@ -478,30 +622,6 @@
 	return -1;
 }
 
-vector<string> TWFunc::split_string(const string &in, char del, bool skip_empty) {
-	vector<string> res;
-
-	if (in.empty() || del == '\0')
-		return res;
-
-	string field;
-	istringstream f(in);
-	if (del == '\n') {
-		while(getline(f, field)) {
-			if (field.empty() && skip_empty)
-				continue;
-			res.push_back(field);
-		}
-	} else {
-		while(getline(f, field, del)) {
-			if (field.empty() && skip_empty)
-				continue;
-			res.push_back(field);
-		}
-	}
-	return res;
-}
-
 timespec TWFunc::timespec_diff(timespec& start, timespec& end)
 {
 	timespec temp;
@@ -559,13 +679,21 @@
 	if (!PartitionManager.Mount_By_Path("/system", true))
 		return false;
 
+	string propvalue = System_Property_Get("ro.build.version.sdk");
+	string su_perms = "6755";
+	if (!propvalue.empty()) {
+		int sdk_version = atoi(propvalue.c_str());
+		if (sdk_version >= 18)
+			su_perms = "0755";
+	}
+
 	string file = "/system/bin/su";
 	if (TWFunc::Path_Exists(file)) {
 		if (chown(file.c_str(), 0, 0) != 0) {
 			LOGERR("Failed to chown '%s'\n", file.c_str());
 			return false;
 		}
-		if (tw_chmod(file, "6755") != 0) {
+		if (tw_chmod(file, su_perms) != 0) {
 			LOGERR("Failed to chmod '%s'\n", file.c_str());
 			return false;
 		}
@@ -576,7 +704,7 @@
 			LOGERR("Failed to chown '%s'\n", file.c_str());
 			return false;
 		}
-		if (tw_chmod(file, "6755") != 0) {
+		if (tw_chmod(file, su_perms) != 0) {
 			LOGERR("Failed to chmod '%s'\n", file.c_str());
 			return false;
 		}
@@ -587,7 +715,7 @@
 			LOGERR("Failed to chown '%s'\n", file.c_str());
 			return false;
 		}
-		if (tw_chmod(file, "6755") != 0) {
+		if (tw_chmod(file, "0755") != 0) {
 			LOGERR("Failed to chmod '%s'\n", file.c_str());
 			return false;
 		}
@@ -598,7 +726,7 @@
 			LOGERR("Failed to chown '%s'\n", file.c_str());
 			return false;
 		}
-		if (tw_chmod(file, "6755") != 0) {
+		if (tw_chmod(file, su_perms) != 0) {
 			LOGERR("Failed to chmod '%s'\n", file.c_str());
 			return false;
 		}
@@ -802,121 +930,6 @@
 	return true;
 }
 
-int TWFunc::Get_File_Type(string fn) {
-	string::size_type i = 0;
-	int firstbyte = 0, secondbyte = 0;
-	char header[3];
-
-	ifstream f;
-	f.open(fn.c_str(), ios::in | ios::binary);
-	f.get(header, 3);
-	f.close();
-	firstbyte = header[i] & 0xff;
-	secondbyte = header[++i] & 0xff;
-
-	if (firstbyte == 0x1f && secondbyte == 0x8b)
-		return 1; // Compressed
-	else if (firstbyte == 0x4f && secondbyte == 0x41)
-		return 2; // Encrypted
-	else
-		return 0; // Unknown
-
-	return 0;
-}
-
-int TWFunc::Try_Decrypting_File(string fn, string password) {
-#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
-	OAES_CTX * ctx = NULL;
-	uint8_t _key_data[32] = "";
-	FILE *f;
-	uint8_t buffer[4096];
-	uint8_t *buffer_out = NULL;
-	uint8_t *ptr = NULL;
-	size_t read_len = 0, out_len = 0;
-	int firstbyte = 0, secondbyte = 0, key_len;
-	size_t _j = 0;
-	size_t _key_data_len = 0;
-
-	// mostly kanged from OpenAES oaes.c
-	for( _j = 0; _j < 32; _j++ )
-		_key_data[_j] = _j + 1;
-	_key_data_len = password.size();
-	if( 16 >= _key_data_len )
-		_key_data_len = 16;
-	else if( 24 >= _key_data_len )
-		_key_data_len = 24;
-	else
-	_key_data_len = 32;
-	memcpy(_key_data, password.c_str(), password.size());
-
-	ctx = oaes_alloc();
-	if (ctx == NULL) {
-		LOGERR("Failed to allocate OAES\n");
-		return -1;
-	}
-
-	oaes_key_import_data(ctx, _key_data, _key_data_len);
-
-	f = fopen(fn.c_str(), "rb");
-	if (f == NULL) {
-		LOGERR("Failed to open '%s' to try decrypt\n", fn.c_str());
-		return -1;
-	}
-	read_len = fread(buffer, sizeof(uint8_t), 4096, f);
-	if (read_len <= 0) {
-		LOGERR("Read size during try decrypt failed\n");
-		fclose(f);
-		return -1;
-	}
-	if (oaes_decrypt(ctx, buffer, read_len, NULL, &out_len) != OAES_RET_SUCCESS) {
-		LOGERR("Error: Failed to retrieve required buffer size for trying decryption.\n");
-		fclose(f);
-		return -1;
-	}
-	buffer_out = (uint8_t *) calloc(out_len, sizeof(char));
-	if (buffer_out == NULL) {
-		LOGERR("Failed to allocate output buffer for try decrypt.\n");
-		fclose(f);
-		return -1;
-	}
-	if (oaes_decrypt(ctx, buffer, read_len, buffer_out, &out_len) != OAES_RET_SUCCESS) {
-		LOGERR("Failed to decrypt file '%s'\n", fn.c_str());
-		fclose(f);
-		free(buffer_out);
-		return 0;
-	}
-	fclose(f);
-	if (out_len < 2) {
-		LOGINFO("Successfully decrypted '%s' but read length %i too small.\n", fn.c_str(), out_len);
-		free(buffer_out);
-		return 1; // Decrypted successfully
-	}
-	ptr = buffer_out;
-	firstbyte = *ptr & 0xff;
-	ptr++;
-	secondbyte = *ptr & 0xff;
-	if (firstbyte == 0x1f && secondbyte == 0x8b) {
-		LOGINFO("Successfully decrypted '%s' and file is compressed.\n", fn.c_str());
-		free(buffer_out);
-		return 3; // Compressed
-	}
-	if (out_len >= 262) {
-		ptr = buffer_out + 257;
-		if (strncmp((char*)ptr, "ustar", 5) == 0) {
-			LOGINFO("Successfully decrypted '%s' and file is tar format.\n", fn.c_str());
-			free(buffer_out);
-			return 2; // Tar
-		}
-	}
-	free(buffer_out);
-	LOGINFO("No errors decrypting '%s' but no known file format.\n", fn.c_str());
-	return 1; // Decrypted successfully
-#else
-	LOGERR("Encrypted backup support not included.\n");
-	return -1;
-#endif
-}
-
 bool TWFunc::Try_Decrypting_Backup(string Restore_Path, string Password) {
 	DIR* d;
 
@@ -945,31 +958,6 @@
 	return true;
 }
 
-int TWFunc::Wait_For_Child(pid_t pid, int *status, string Child_Name) {
-	pid_t rc_pid;
-
-	rc_pid = waitpid(pid, status, 0);
-	if (rc_pid > 0) {
-		if (WEXITSTATUS(*status) == 0)
-			LOGINFO("%s process ended with RC=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Success
-		else if (WIFSIGNALED(*status)) {
-			LOGINFO("%s process ended with signal: %d\n", Child_Name.c_str(), WTERMSIG(*status)); // Seg fault or some other non-graceful termination
-			return -1;
-		} else if (WEXITSTATUS(*status) != 0) {
-			LOGINFO("%s process ended with ERROR=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Graceful exit, but there was an error
-			return -1;
-		}
-	} else { // no PID returned
-		if (errno == ECHILD)
-			LOGINFO("%s no child process exist\n", Child_Name.c_str());
-		else {
-			LOGINFO("%s Unexpected error\n", Child_Name.c_str());
-			return -1;
-		}
-	}
-	return 0;
-}
-
 string TWFunc::Get_Current_Date() {
 	string Current_Date;
 	time_t seconds = time(0);
@@ -980,50 +968,56 @@
 	return Current_Date;
 }
 
-void TWFunc::Auto_Generate_Backup_Name() {
+string TWFunc::System_Property_Get(string Prop_Name) {
 	bool mount_state = PartitionManager.Is_Mounted_By_Path("/system");
 	std::vector<string> buildprop;
-	if (!PartitionManager.Mount_By_Path("/system", true)) {
-		DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date());
-		return;
-	}
+	string propvalue;
+	if (!PartitionManager.Mount_By_Path("/system", true))
+		return propvalue;
 	if (TWFunc::read_file("/system/build.prop", buildprop) != 0) {
-		LOGINFO("Unable to open /system/build.prop for getting backup name.\n");
+		LOGINFO("Unable to open /system/build.prop for getting '%s'.\n", Prop_Name.c_str());
 		DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date());
 		if (!mount_state)
 			PartitionManager.UnMount_By_Path("/system", false);
-		return;
+		return propvalue;
 	}
 	int line_count = buildprop.size();
 	int index;
 	size_t start_pos = 0, end_pos;
-	string propname, propvalue;
+	string propname;
 	for (index = 0; index < line_count; index++) {
 		end_pos = buildprop.at(index).find("=", start_pos);
 		propname = buildprop.at(index).substr(start_pos, end_pos);
-		if (propname == "ro.build.display.id") {
+		if (propname == Prop_Name) {
 			propvalue = buildprop.at(index).substr(end_pos + 1, buildprop.at(index).size());
-			string Backup_Name = Get_Current_Date();
-			Backup_Name += " " + propvalue;
-			if (Backup_Name.size() > MAX_BACKUP_NAME_LEN)
-				Backup_Name.resize(MAX_BACKUP_NAME_LEN);
-			// Trailing spaces cause problems on some file systems, so remove them
-			string space_check, space = " ";
-			space_check = Backup_Name.substr(Backup_Name.size() - 1, 1);
-			while (space_check == space) {
-				Backup_Name.resize(Backup_Name.size() - 1);
-				space_check = Backup_Name.substr(Backup_Name.size() - 1, 1);
-			}
-			DataManager::SetValue(TW_BACKUP_NAME, Backup_Name);
-			break;
+			if (!mount_state)
+				PartitionManager.UnMount_By_Path("/system", false);
+			return propvalue;
 		}
 	}
-	if (propvalue.empty()) {
-		LOGINFO("ro.build.display.id not found in build.prop\n");
-		DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date());
-	}
 	if (!mount_state)
 		PartitionManager.UnMount_By_Path("/system", false);
+	return propvalue;
+}
+
+void TWFunc::Auto_Generate_Backup_Name() {
+	string propvalue = System_Property_Get("ro.build.display.id");
+	if (propvalue.empty()) {
+		DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date());
+		return;
+	}
+	string Backup_Name = Get_Current_Date();
+	Backup_Name += " " + propvalue;
+	if (Backup_Name.size() > MAX_BACKUP_NAME_LEN)
+		Backup_Name.resize(MAX_BACKUP_NAME_LEN);
+	// Trailing spaces cause problems on some file systems, so remove them
+	string space_check, space = " ";
+	space_check = Backup_Name.substr(Backup_Name.size() - 1, 1);
+	while (space_check == space) {
+		Backup_Name.resize(Backup_Name.size() - 1);
+		space_check = Backup_Name.substr(Backup_Name.size() - 1, 1);
+	}
+	DataManager::SetValue(TW_BACKUP_NAME, Backup_Name);
 }
 
 void TWFunc::Fixup_Time_On_Boot()
@@ -1118,3 +1112,5 @@
 	settimeofday(&tv, NULL);
 #endif
 }
+
+#endif // ndef BUILD_TWRPTAR_MAIN
diff --git a/twrp-functions.hpp b/twrp-functions.hpp
index 587d772..661ca02 100644
--- a/twrp-functions.hpp
+++ b/twrp-functions.hpp
@@ -42,20 +42,25 @@
 	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 int Exec_Cmd(const string& cmd, string &result);                     //execute a command and return the result as a string by reference
+	static int Exec_Cmd(const string& cmd);                                     //execute a command
+	static int Wait_For_Child(pid_t pid, int *status, string Child_Name);       // Waits for pid to exit and checks exit status
+	static bool Path_Exists(string Path);                                       // Returns true if the path exists
+	static int Get_File_Type(string fn); // Determines file type, 0 for unknown, 1 for gzip, 2 for OAES encrypted
+	static int Try_Decrypting_File(string fn, string password); // -1 for some error, 0 for failed to decrypt, 1 for decrypted, 3 for decrypted and found gzip format
+	static unsigned long Get_File_Size(string Path);                            // Returns the size of a file
+
+#ifndef BUILD_TWRPTAR_MAIN
 	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
 	static int Recursive_Mkdir(string Path);                                    // Recursively makes the entire path
-	static bool Path_Exists(string Path);                                       // Returns true if the path exists
 	static void GUI_Operation_Text(string Read_Value, string Default_Text);     // Updates text for display in the GUI, e.g. Backing up %partition name%
 	static void GUI_Operation_Text(string Read_Value, string Partition_Name, string Default_Text); // Same as above but includes partition name
-	static unsigned long Get_File_Size(string Path);                            // Returns the size of a file
 	static void Update_Log_File(void);                                          // Writes the log to last_log
 	static void Update_Intent_File(string Intent);                              // Updates intent file
 	static int tw_reboot(RebootCommand command);                                // Prepares the device for rebooting
 	static void check_and_run_script(const char* script_file, const char* display_name); // checks for the existence of a script, chmods it to 755, then runs it
-	static int Exec_Cmd(const string& cmd, string &result); //execute a command and return the result as a string by reference
-	static int Exec_Cmd(const string& cmd); //execute a command
 	static int removeDir(const string path, bool removeParent); //recursively remove a directory
 	static int copy_file(string src, string dst, int mode); //copy file from src to dst with mode permissions
 	static unsigned int Get_D_Type_From_Stat(string Path);                      // Returns a dirent dt_type value using stat instead of dirent
@@ -69,11 +74,8 @@
 	static bool Fix_su_Perms(void); // sets proper permissions for su binaries and superuser apk
 	static int tw_chmod(const string& fn, const string& mode); // chmod function that converts a 3 or 4 char string into st_mode automatically
 	static bool Install_SuperSU(void); // Installs su binary and apk and sets proper permissions
-	static vector<string> split_string(const string &in, char del, bool skip_empty);
-	static int Get_File_Type(string fn); // Determines file type, 0 for unknown, 1 for gzip, 2 for OAES encrypted
-	static int Try_Decrypting_File(string fn, string password); // -1 for some error, 0 for failed to decrypt, 1 for decrypted, 3 for decrypted and found gzip format
 	static bool Try_Decrypting_Backup(string Restore_Path, string Password); // true for success, false for failed to decrypt
-	static int Wait_For_Child(pid_t pid, int *status, string Child_Name); // Waits for pid to exit and checks exit status
+	static string System_Property_Get(string Prop_Name);                // Returns value of Prop_Name from reading /system/build.prop
 	static string Get_Current_Date(void);                               // Returns the current date in ccyy-m-dd--hh-nn-ss format
 	static void Auto_Generate_Backup_Name();                            // Populates TW_BACKUP_NAME with a backup name based on current date and ro.build.display.id from /system/build.prop
 	static void Fixup_Time_On_Boot(); // Fixes time on devices which need it
@@ -84,5 +86,8 @@
 };
 
 extern int Log_Offset;
+#else
+};
+#endif // ndef BUILD_TWRPTAR_MAIN
 
 #endif // _TWRPFUNCTIONS_HPP
diff --git a/twrpTar.cpp b/twrpTar.cpp
index 824356a..cc09b78 100644
--- a/twrpTar.cpp
+++ b/twrpTar.cpp
@@ -21,7 +21,6 @@
 	#include "libtar/libtar.h"
 	#include "twrpTar.h"
 	#include "tarWrite.h"
-	#include "libcrecovery/common.h"
 }
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -39,7 +38,6 @@
 #include <sys/mman.h>
 #include "twrpTar.hpp"
 #include "twcommon.h"
-#include "data.hpp"
 #include "variables.h"
 #include "twrp-functions.hpp"
 
@@ -77,6 +75,10 @@
 	Total_Backup_Size = backup_size;
 }
 
+void twrpTar::setpassword(string pass) {
+	password = pass;
+}
+
 int twrpTar::createTarFork() {
 	int status = 0;
 	pid_t pid, rc_pid;
@@ -529,9 +531,7 @@
 		int ret = extractTar();
 		return ret;
 	} else if (Archive_Current_Type == 2) {
-		string Password;
-		DataManager::GetValue("tw_restore_password", Password);
-		int ret = TWFunc::Try_Decrypting_File(tarfn, Password);
+		int ret = TWFunc::Try_Decrypting_File(tarfn, password);
 		if (ret < 1) {
 			LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
 			return -1;
@@ -675,13 +675,11 @@
 	char* charTarFile = (char*) tarfn.c_str();
 	char* charRootDir = (char*) tardir.c_str();
 	static tartype_t type = { open, close, read, write_tar };
-	string Password;
 
 	if (use_encryption && use_compression) {
 		// Compressed and encrypted
 		Archive_Current_Type = 3;
 		LOGINFO("Using encryption and compression...\n");
-		DataManager::GetValue("tw_backup_password", Password);
 		int i, pipes[4];
 
 		if (pipe(pipes) < 0) {
@@ -738,7 +736,7 @@
 				dup2(pipes[2], 0);
 				close(1);
 				dup2(output_fd, 1);
-				if (execlp("openaes", "openaes", "enc", "--key", Password.c_str(), NULL) < 0) {
+				if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
 					LOGERR("execlp openaes ERROR!\n");
 					close(pipes[2]);
 					close(output_fd);
@@ -806,7 +804,6 @@
 		// Encrypted
 		Archive_Current_Type = 2;
 		LOGINFO("Using encryption...\n");
-		DataManager::GetValue("tw_backup_password", Password);
 		int oaesfd[2];
 		pipe(oaesfd);
 		oaes_pid = fork();
@@ -826,7 +823,7 @@
 			}
 			dup2(oaesfd[0], 0); // remap stdin
 			dup2(output_fd, 1); // remap stdout to output file
-			if (execlp("openaes", "openaes", "enc", "--key", Password.c_str(), NULL) < 0) {
+			if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
 				LOGERR("execlp openaes ERROR!\n");
 				close(output_fd);
 				close(oaesfd[0]);
@@ -861,7 +858,6 @@
 
 	if (Archive_Current_Type == 3) {
 		LOGINFO("Opening encrypted and compressed backup...\n");
-		DataManager::GetValue("tw_restore_password", Password);
 		int i, pipes[4];
 
 		if (pipe(pipes) < 0) {
@@ -894,7 +890,7 @@
 			dup2(input_fd, 0);
 			close(1);
 			dup2(pipes[1], 1);
-			if (execlp("openaes", "openaes", "dec", "--key", Password.c_str(), NULL) < 0) {
+			if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
 				LOGERR("execlp openaes ERROR!\n");
 				close(input_fd);
 				close(pipes[1]);
@@ -938,7 +934,6 @@
 		}
 	} else if (Archive_Current_Type == 2) {
 		LOGINFO("Opening encrypted backup...\n");
-		DataManager::GetValue("tw_restore_password", Password);
 		int oaesfd[2];
 
 		pipe(oaesfd);
@@ -960,7 +955,7 @@
 			close(0);   // close stdin
 			dup2(oaesfd[1], 1); // remap stdout
 			dup2(input_fd, 0); // remap input fd to stdin
-			if (execlp("openaes", "openaes", "dec", "--key", Password.c_str(), NULL) < 0) {
+			if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
 				LOGERR("execlp openaes ERROR!\n");
 				close(input_fd);
 				close(oaesfd[1]);
@@ -1119,38 +1114,6 @@
 	return ret;
 }
 
-unsigned long long twrpTar::uncompressedSize() {
-	int type = 0;
-	unsigned long long total_size = 0;
-	string Tar, Command, result;
-	vector<string> split;
-
-	Tar = TWFunc::Get_Filename(tarfn);
-	type = TWFunc::Get_File_Type(tarfn);
-	if (type == 0)
-		total_size = TWFunc::Get_File_Size(tarfn);
-	else {
-		Command = "pigz -l " + tarfn;
-		/* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
-		   we get the uncompressed size at once. */
-		TWFunc::Exec_Cmd(Command, result);
-		if (!result.empty()) {
-			/* Expected output:
-				compressed   original reduced  name
-				  95855838  179403776   -1.3%  data.yaffs2.win
-						^
-					     split[5]
-			*/
-			split = TWFunc::split_string(result, ' ', true);
-			if (split.size() > 4)
-				total_size = atoi(split[5].c_str());
-		}
-	}
-	LOGINFO("%s's uncompressed size: %llu bytes\n", Tar.c_str(), total_size);
-
-	return total_size;
-}
-
 extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
 	return (ssize_t) write_libtar_buffer(fd, buffer, size);
 }
diff --git a/twrpTar.hpp b/twrpTar.hpp
index 17f6959..a42dea0 100644
--- a/twrpTar.hpp
+++ b/twrpTar.hpp
@@ -51,7 +51,7 @@
 	void setfn(string fn);
 	void setdir(string dir);
 	void setsize(unsigned long long backup_size);
-	unsigned long long uncompressedSize();
+	void setpassword(string pass);
 
 public:
 	int use_encryption;
@@ -89,6 +89,7 @@
 	string tardir;
 	string tarfn;
 	string basefn;
+	string password;
 
 	vector <string> tarexclude;
 
diff --git a/twrpTarMain/Android.mk b/twrpTarMain/Android.mk
new file mode 100644
index 0000000..5cd6fe1
--- /dev/null
+++ b/twrpTarMain/Android.mk
@@ -0,0 +1,71 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Build static binary
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	twrpTarMain.cpp \
+	../twrp-functions.cpp \
+	../twrpTar.cpp \
+	../tarWrite.c \
+	../twrpDU.cpp
+LOCAL_CFLAGS:= -g -c -W -DBUILD_TWRPTAR_MAIN
+
+LOCAL_C_INCLUDES += bionic external/stlport/stlport
+LOCAL_STATIC_LIBRARIES := libc libtar_static libstlport_static libstdc++
+
+ifeq ($(TWHAVE_SELINUX), true)
+    LOCAL_C_INCLUDES += external/libselinux/include
+    LOCAL_STATIC_LIBRARIES += libselinux
+    LOCAL_CFLAGS += -DHAVE_SELINUX -g
+endif
+ifneq ($(RECOVERY_SDCARD_ON_DATA),)
+	LOCAL_CFLAGS += -DRECOVERY_SDCARD_ON_DATA
+endif
+ifeq ($(TW_EXCLUDE_ENCRYPTED_BACKUPS), true)
+    LOCAL_CFLAGS += -DTW_EXCLUDE_ENCRYPTED_BACKUPS
+else
+	LOCAL_STATIC_LIBRARIES += libopenaes_static
+endif
+
+LOCAL_MODULE:= twrpTar_static
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_MODULE_TAGS:= eng
+LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
+include $(BUILD_EXECUTABLE)
+
+
+# Build shared binary
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	twrpTarMain.cpp \
+	../twrp-functions.cpp \
+	../twrpTar.cpp \
+	../tarWrite.c \
+	../twrpDU.cpp
+LOCAL_CFLAGS:= -g -c -W -DBUILD_TWRPTAR_MAIN
+
+LOCAL_C_INCLUDES += bionic external/stlport/stlport
+LOCAL_SHARED_LIBRARIES := libc libtar libstlport libstdc++
+
+ifeq ($(TWHAVE_SELINUX), true)
+    LOCAL_C_INCLUDES += external/libselinux/include
+    LOCAL_SHARED_LIBRARIES += libselinux
+    LOCAL_CFLAGS += -DHAVE_SELINUX -g
+endif
+ifneq ($(RECOVERY_SDCARD_ON_DATA),)
+	LOCAL_CFLAGS += -DRECOVERY_SDCARD_ON_DATA
+endif
+ifeq ($(TW_EXCLUDE_ENCRYPTED_BACKUPS), true)
+    LOCAL_CFLAGS += -DTW_EXCLUDE_ENCRYPTED_BACKUPS
+else
+	LOCAL_SHARED_LIBRARIES += libopenaes
+endif
+
+LOCAL_MODULE:= twrpTar
+LOCAL_MODULE_TAGS:= eng
+LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
+include $(BUILD_EXECUTABLE)
diff --git a/twrpTarMain/twrpTarMain.cpp b/twrpTarMain/twrpTarMain.cpp
new file mode 100644
index 0000000..ef6a5ef
--- /dev/null
+++ b/twrpTarMain/twrpTarMain.cpp
@@ -0,0 +1,164 @@
+
+/*
+	Copyright 2014 TeamWin
+	This file is part of TWRP/TeamWin Recovery Project.
+
+	TWRP is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	TWRP is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../twrp-functions.hpp"
+#include "../twrpTar.hpp"
+#include "../twrpDU.hpp"
+#include <string.h>
+
+twrpDU du;
+
+void usage() {
+	printf("twrpTar <action> [options]\n\n");
+	printf("actions: -c create\n");
+	printf("         -x extract\n\n");
+	printf(" -d    target directory\n");
+	printf(" -t    output file\n");
+	printf(" -m    skip media subfolder (has data media)\n");
+	printf(" -z    compress backup (/sbin/pigz must be present)\n");
+#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
+	printf(" -e    encrypt/decrypt backup followed by password (/sbin/openaes must be present)\n");
+	printf(" -u    encrypt using userdata encryption (must be used with -e\n");
+#endif
+	printf("\n\n");
+	printf("Example: twrpTar -c -d /cache -t /sdcard/test.tar\n");
+	printf("         twrpTar -x -d /cache -t /sdcard/test.tar\n");
+}
+
+int main(int argc, char **argv) {
+	twrpTar tar;
+	int use_encryption = 0, userdata_encryption = 0, has_data_media = 0, use_compression = 0, include_root = 0;
+	int i, action = 0;
+	unsigned j;
+	string Directory, Tar_Filename;
+#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
+	string Password;
+#endif
+
+	if (argc < 2) {
+		usage();
+		return 0;
+	}
+
+	if (strcmp(argv[1], "-c") == 0)
+		action = 1; // create tar
+	else if (strcmp(argv[1], "-x") == 0)
+		action = 2; // extract tar
+	else {
+		printf("Invalid action '%s' specified.\n", argv[1]);
+		usage();
+		return -1;
+	}
+
+	for (i = 2; i < argc; i++) {
+		if (strcmp(argv[i], "-d") == 0) {
+			i++;
+			if (argc <= i) {
+				printf("No argument specified for %s\n", argv[i - 1]);
+				usage();
+				return -1;
+			} else {
+				Directory = argv[i];
+			}
+		} else if (strcmp(argv[i], "-t") == 0) {
+			i++;
+			if (argc <= i) {
+				printf("No argument specified for %s\n", argv[i - 1]);
+				usage();
+				return -1;
+			} else {
+				Tar_Filename = argv[i];
+			}
+		} else if (strcmp(argv[i], "-e") == 0) {
+#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
+			i++;
+			if (argc <= i) {
+				printf("No argument specified for %s\n", argv[i - 1]);
+				usage();
+				return -1;
+			} else {
+				use_encryption = 1;
+				Password = argv[i];
+			}
+#else
+			printf("Encrypted tar file support not present\n");
+			usage();
+			return -1;
+#endif
+		} else if (strcmp(argv[i], "-m") == 0) {
+			if (action == 2)
+				printf("NOTE: %s option not needed when extracting.\n", argv[i]);
+			has_data_media = 1;
+		} else if (strcmp(argv[i], "-z") == 0) {
+			if (action == 2)
+				printf("NOTE: %s option not needed when extracting.\n", argv[i]);
+			use_compression = 1;
+		} else if (strcmp(argv[i], "-u") == 0) {
+#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
+			if (action == 2)
+				printf("NOTE: %s option not needed when extracting.\n", argv[i]);
+			userdata_encryption = 1;
+#else
+			printf("Encrypted tar file support not present\n");
+			usage();
+			return -1;
+#endif
+		}
+	}
+
+	vector<string> excludedirs = du.get_absolute_dirs();
+	for (j = 0; j < excludedirs.size(); ++j) {
+		tar.setexcl(excludedirs.at(j));
+	}
+	tar.has_data_media = has_data_media;
+	tar.setdir(Directory);
+	tar.setfn(Tar_Filename);
+	tar.setsize(du.Get_Folder_Size(Directory));
+	tar.use_compression = use_compression;
+#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
+	if (userdata_encryption && !use_encryption) {
+		printf("userdata encryption set without encryption option\n");
+		usage();
+		return -1;
+	}
+	if (use_encryption) {
+		tar.use_encryption = use_encryption;
+		tar.userdata_encryption = userdata_encryption;
+		tar.setpassword(Password);
+	} else {
+		use_encryption = false;
+	}
+#endif
+	if (action == 1) {
+		if (tar.createTarFork() != 0) {
+			sync();
+			return -1;
+		}
+		sync();
+		printf("\n\ntar created successfully.\n");
+	} else if (action == 2) {
+		if (tar.extractTarFork() != 0) {
+			sync();
+			return -1;
+		}
+		sync();
+		printf("\n\ntar extracted successfully.\n");
+	}
+	return 0;
+}