change tar create to pthread

Change-Id: I5a33d207ec6683de20da37e6f4f174c67785fc52
diff --git a/gui/action.cpp b/gui/action.cpp
index 14ef716..997cf55 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -249,10 +249,11 @@
 		LOGE("Error setting pthread_attr_setscope\n");
 		return -1;
 	}
-	if (pthread_attr_setstacksize(&tattr, 524288)) {
+	/*if (pthread_attr_setstacksize(&tattr, 524288)) {
 		LOGE("Error setting pthread_attr_setstacksize\n");
 		return -1;
 	}
+	*/
 	LOGI("Creating thread\n");
 	int ret = pthread_create(&t, &tattr, thread_start, this);
     if (ret) {
diff --git a/partition.cpp b/partition.cpp
index d16ed7c..c532fa8 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -1255,7 +1255,7 @@
 	unsigned long long total_bsize = 0, file_size;
 	twrpTar tar;
 	vector <string> files;
-
+	
 	if (!Mount(true))
 		return false;
 
@@ -1276,7 +1276,9 @@
 		// This backup needs to be split into multiple archives
 		ui_print("Breaking backup file into multiple archives...\n");
 		sprintf(back_name, "%s", Backup_Path.c_str());
-		backup_count = tar.Split_Archive(back_name, Full_FileName);
+		tar.setdir(back_name);
+		tar.setfn(Full_FileName);
+		backup_count = tar.splitArchiveThread();
 		if (backup_count == -1) {
 			LOGE("Error tarring split files!\n");
 			return false;
@@ -1285,14 +1287,18 @@
 	} else {
 		Full_FileName = backup_folder + "/" + Backup_FileName;
 		if (use_compression) {
-			if (tar.createTGZ(Backup_Path, Full_FileName) != 0)
-				return false;
+			tar.setdir(Backup_Path);
+			tar.setfn(Full_FileName);
+			if (tar.createTarGZThread() != 0)
+				return -1;
 			string gzname = Full_FileName + ".gz";
 			rename(gzname.c_str(), Full_FileName.c_str());
 		}
 		else {
-			if (tar.create(Backup_Path, Full_FileName) != 0)
-				return false;
+			tar.setdir(Backup_Path);
+			tar.setfn(Full_FileName);
+			if (tar.createTarThread() != 0)
+				return -1;
 		}
 		if (TWFunc::Get_File_Size(Full_FileName) == 0) {
 			LOGE("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str());
@@ -1381,7 +1387,9 @@
 				ui_print("Restoring archive %i...\n", index);
 				LOGI("Restoring '%s'...\n", Full_FileName.c_str());
 				twrpTar tar;
-				if (tar.extract("/", Full_FileName) != 0)
+				tar.setdir("/");
+				tar.setfn(Full_FileName);
+				if (tar.extractTarThread() != 0)
 					return false;
 				sprintf(split_index, "%03i", index);
 				Full_FileName = restore_folder + "/" + Backup_FileName + split_index;
@@ -1393,7 +1401,9 @@
 		}
 	} else {
 		twrpTar tar;
-		if (tar.extract(Backup_Path, Full_FileName) != 0)
+		tar.setdir(Backup_Path);
+		tar.setfn(Full_FileName);
+		if (tar.extractTarThread() != 0)
 			return false;
 	}
 	return true;
diff --git a/twrpTar.cpp b/twrpTar.cpp
index 0008de4..78409c7 100644
--- a/twrpTar.cpp
+++ b/twrpTar.cpp
@@ -28,29 +28,79 @@
 #include <fstream>
 #include <iostream>
 #include <string>
+#include <sstream>
 #include <dirent.h>
 #include <sys/mman.h>
 #include "twrpTar.hpp"
 #include "common.h"
 #include "data.hpp"
 #include "variables.h"
-#include <sstream>
 #include "twrp-functions.hpp"
 
 using namespace std;
 
-int twrpTar::Generate_Multiple_Archives(string Path, string fn) {
+void twrpTar::setfn(string fn) {
+	tarfn = fn;
+}
+
+void twrpTar::setdir(string dir) {
+	tardir = dir;
+}
+
+int twrpTar::createTarGZThread() {
+	pthread_t thread;
+	ThreadPtr tarptr = &twrpTar::createTGZ;
+	PThreadPtr p = *(PThreadPtr*)&tarptr;
+	pthread_create(&thread, NULL, p, this);
+	if(pthread_join(thread, NULL)) {
+		return -1;
+	}
+	return 0;
+}
+
+int twrpTar::createTarThread() {
+	pthread_t thread;
+	ThreadPtr tarptr = &twrpTar::create;
+	PThreadPtr p = *(PThreadPtr*)&tarptr;
+	pthread_create(&thread, NULL, p, this);
+	if(pthread_join(thread, NULL)) {
+		return -1;
+	}
+	return 0;
+}
+
+int twrpTar::extractTarThread() {
+	pthread_t thread;
+	ThreadPtr tarptr = &twrpTar::extract;
+	PThreadPtr p = *(PThreadPtr*)&tarptr;
+	pthread_create(&thread, NULL, p, this);
+	if(pthread_join(thread, NULL)) {
+		return -1;
+	}
+	return 0;
+}
+
+int twrpTar::splitArchiveThread() {
+	pthread_t thread;
+	ThreadPtr tarptr = &twrpTar::Split_Archive;
+	PThreadPtr p = *(PThreadPtr*)&tarptr;
+	pthread_create(&thread, NULL, p, this);
+	if(pthread_join(thread, NULL)) {
+		return -1;
+	}
+	return 0;
+}
+
+int twrpTar::Generate_Multiple_Archives(string Path) {
 	DIR* d;
 	struct dirent* de;
 	struct stat st;
 	string FileName;
 	char actual_filename[255];
 
-	sprintf(actual_filename, fn.c_str(), Archive_File_Count);
-
 	if (has_data_media == 1 && Path.size() >= 11 && strncmp(Path.c_str(), "/data/media", 11) == 0)
 		return 0; // Skip /data/media
-	LOGI("Path: '%s', archive filename: '%s'\n", Path.c_str(), actual_filename);
+	LOGI("Path: '%s', archive filename: '%s'\n", Path.c_str(), tarfn.c_str());
 
 	d = opendir(Path.c_str());
 	if (d == NULL)
@@ -68,13 +118,16 @@
 		if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
 		{
 			unsigned long long folder_size = TWFunc::Get_Folder_Size(FileName, false);
+			tardir = FileName;
 			if (Archive_Current_Size + folder_size > MAX_ARCHIVE_SIZE) {
-				if (Generate_Multiple_Archives(FileName, fn) < 0)
+				LOGI("Calling Generate_Multiple_Archives\n");
+				if (Generate_Multiple_Archives(FileName) < 0)
 					return -1;
 			} else {
 				//FileName += "/";
 				LOGI("Adding folder '%s'\n", FileName.c_str());
-				if (tarDirs(FileName, actual_filename, true) < 0)
+				tardir = FileName;
+				if (tarDirs(true) < 0)
 					return -1;
 				Archive_Current_Size += folder_size;
 			}
@@ -84,22 +137,25 @@
 			stat(FileName.c_str(), &st);
 
 			if (Archive_Current_Size != 0 && Archive_Current_Size + st.st_size > MAX_ARCHIVE_SIZE) {
-				LOGI("Closing tar '%s', ", actual_filename);
-				closeTar(actual_filename, false);
-				Archive_File_Count++;
-				if (TWFunc::Get_File_Size(actual_filename) == 0) {
-					LOGE("Backup file size for '%s' is 0 bytes.\n", actual_filename);
-					return false;
+				LOGI("Closing tar '%s', ", tarfn.c_str());
+				closeTar(false);
+				if (TWFunc::Get_File_Size(tarfn) == 0) {
+					LOGE("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
+					return -1;
 				}
+				Archive_File_Count++;
 				if (Archive_File_Count > 999) {
 					LOGE("Archive count is too large!\n");
 					return -1;
 				}
+				string temp = basefn + "%03i";
+				sprintf(actual_filename, temp.c_str(), Archive_File_Count);
+				tarfn = actual_filename;
 				Archive_Current_Size = 0;
-				sprintf(actual_filename, fn.c_str(), Archive_File_Count);
-				LOGI("Creating tar '%s'\n", actual_filename);
+				LOGI("Creating tar '%s'\n", tarfn.c_str());
 				ui_print("Creating archive %i...\n", Archive_File_Count + 1);
-				createTar(Path, actual_filename);
+				if (createTar() != 0)
+					return -1;
 			}
 			LOGI("Adding file: '%s'... ", FileName.c_str());
 			if (addFile(FileName, true) < 0)
@@ -114,34 +170,35 @@
 	return 0;
 }
 
-int twrpTar::Split_Archive(string Path, string fn)
+int twrpTar::Split_Archive()
 {
-	string temp = fn + "%03i";
+	string temp = tarfn + "%03i";
 	char actual_filename[255];
 
+	basefn = tarfn;
 	Archive_File_Count = 0;
 	Archive_Current_Size = 0;
 	sprintf(actual_filename, temp.c_str(), Archive_File_Count);
-	createTar(Path, actual_filename);
+	tarfn = actual_filename;
+	createTar();
 	DataManager::GetValue(TW_HAS_DATA_MEDIA, has_data_media);
 	ui_print("Creating archive 1...\n");
-	if (Generate_Multiple_Archives(Path, temp) < 0) {
+	if (Generate_Multiple_Archives(tardir) < 0) {
 		LOGE("Error generating file list\n");
 		return -1;
 	}
-	sprintf(actual_filename, temp.c_str(), Archive_File_Count);
-	closeTar(actual_filename, false);
+	closeTar(false);
 	LOGI("Done, created %i archives.\n", (Archive_File_Count++));
 	return (Archive_File_Count);
 }
 
-int twrpTar::extractTar(string rootdir, string fn) {
-        char* charRootDir = (char*) rootdir.c_str();
+int twrpTar::extractTar() {
+        char* charRootDir = (char*) tardir.c_str();
 	bool gzip = false;
-	if (openTar(rootdir, fn, gzip) == -1)
+	if (openTar(gzip) == -1)
 		return -1;
 	if (tar_extract_all(t, charRootDir) != 0) {
-		LOGE("Unable to extract tar archive '%s'\n", fn.c_str());
+		LOGE("Unable to extract tar archive '%s'\n", tarfn.c_str());
 		return -1;
 	}
 	if (tar_close(t) != 0) {
@@ -151,7 +208,7 @@
 	return 0;
 }
 
-int twrpTar::extract(string rootdir, string fn) {
+int twrpTar::extract() {
         int len = 3;
         char header[len];
         string::size_type i = 0;
@@ -159,7 +216,7 @@
         int secondbyte = 0;
         int ret;
         ifstream f;
-        f.open(fn.c_str(), ios::in | ios::binary);
+        f.open(tarfn.c_str(), ios::in | ios::binary);
         f.get(header, len);
         firstbyte = header[i] & 0xff;
         secondbyte = header[++i] & 0xff;
@@ -167,27 +224,27 @@
         if (firstbyte == 0x1f && secondbyte == 0x8b) {
 		//if you return the extractTGZ function directly, stack crashes happen
 		LOGI("Extracting gzipped tar\n");
-		ret = extractTGZ(rootdir, fn);
+		ret = extractTGZ();
 		return ret;
 	}
 	else {
 		LOGI("Extracting uncompressed tar\n");
-		return extractTar(rootdir, fn);
+		return extractTar();
 	}
 }
 
-int twrpTar::tarDirs(string dir, string fn, bool include_root) {
+int twrpTar::tarDirs(bool include_root) {
         DIR* d;
-        string mainfolder = dir + "/", subfolder;
+        string mainfolder = tardir + "/", subfolder;
         char buf[1024];
-        char* charTarFile = (char*) fn.c_str();
-        d = opendir(dir.c_str());
+        char* charTarFile = (char*) tarfn.c_str();
+        d = opendir(tardir.c_str());
         if (d != NULL) {
                 struct dirent* de;
                 while ((de = readdir(d)) != NULL) {
                         LOGI("adding %s\n", de->d_name);
 #ifdef RECOVERY_SDCARD_ON_DATA
-                        if ((dir == "/data" || dir == "/data/") && strcmp(de->d_name, "media") == 0) continue;
+                        if ((tardir == "/data" || tardir == "/data/") && strcmp(de->d_name, "media") == 0) continue;
 #endif
                         if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)   continue;
 
@@ -195,7 +252,7 @@
                         subfolder += de->d_name;
                         strcpy(buf, subfolder.c_str());
                         if (de->d_type == DT_DIR) {
-							if (include_root) {
+					if (include_root) {
                                 if (tar_append_tree(t, buf, NULL) != 0) {
                                         LOGE("Error appending '%s' to tar archive '%s'\n", buf, charTarFile);
                                         return -1;
@@ -208,7 +265,7 @@
                                         return -1;
                                 }
 							}
-                        } else if (dir != "/" && (de->d_type == DT_REG || de->d_type == DT_LNK)) {
+                        } else if (tardir != "/" && (de->d_type == DT_REG || de->d_type == DT_LNK)) {
 							if (addFile(buf, include_root) != 0)
 								return -1;
 						}
@@ -219,24 +276,24 @@
 	return 0;
 }
 
-int twrpTar::createTGZ(string dir, string fn) {
+int twrpTar::createTGZ() {
         bool gzip = true;
-	if (createTar(dir, fn) == -1)
+	if (createTar() == -1)
 		return -1;
-	if (tarDirs(dir, fn, false) == -1)
+	if (tarDirs(false) == -1)
 		return -1;
-	if (closeTar(fn, gzip) == -1)
+	if (closeTar(gzip) == -1)
 		return -1;
         return 0;
 }
 
-int twrpTar::create(string dir, string fn) {
+int twrpTar::create() {
         bool gzip = false;
-	if (createTar(dir, fn) == -1)
+	if (createTar() == -1)
 		return -1;
-	if (tarDirs(dir, fn, false) == -1)
+	if (tarDirs(false) == -1)
 		return -1;
-	if (closeTar(fn, gzip) == -1)
+	if (closeTar(gzip) == -1)
 		return -1;
 	return 0;
 }
@@ -250,7 +307,7 @@
 	if (tar_open(&t, charTarFile, NULL, O_WRONLY | O_APPEND | O_LARGEFILE, 0644, TAR_GNU) == -1)
 		return -1;
 	for (unsigned int i = 0; i < files.size(); ++i) {
-		char* file = (char*) files.at(i).c_str(); 
+		char* file = (char*) files.at(i).c_str();
 		if (tar_append_file(t, file, file) == -1)
 			return -1;
 	}
@@ -261,15 +318,14 @@
 	return 0;
 }
 
-int twrpTar::createTar(string rootdir, string fn) {
-	char* charTarFile = (char*) fn.c_str();
-        char* charRootDir = (char*) rootdir.c_str();
+int twrpTar::createTar() {
+	char* charTarFile = (char*) tarfn.c_str();
+        char* charRootDir = (char*) tardir.c_str();
 	int use_compression = 0;
 
 	DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
-	LOGI("2nd compression\n");
 	if (use_compression) {
-		string cmd = "pigz - > '" + fn + "'";
+		string cmd = "pigz - > '" + tarfn + "'";
 		p = popen(cmd.c_str(), "w");
 		fd = fileno(p);
 		if (!p) return -1;
@@ -277,7 +333,7 @@
 			pclose(p);
 			return -1;
 		}
-	}	
+	}
 	else {
 		if (tar_open(&t, charTarFile, NULL, O_WRONLY | O_CREAT | O_LARGEFILE, 0644, TAR_GNU) == -1)
 			return -1;
@@ -285,13 +341,13 @@
 	return 0;
 }
 
-int twrpTar::openTar(string rootdir, string fn, bool gzip) {
-        char* charRootDir = (char*) rootdir.c_str();
-        char* charTarFile = (char*) fn.c_str();
+int twrpTar::openTar(bool gzip) {
+        char* charRootDir = (char*) tardir.c_str();
+        char* charTarFile = (char*) tarfn.c_str();
 
 	if (gzip) {
 		LOGI("Opening as a gzip\n");
-		string cmd = "pigz -d -c '" + fn + "'";
+		string cmd = "pigz -d -c '" + tarfn + "'";
 		FILE* pipe = popen(cmd.c_str(), "r");
 		int fd = fileno(pipe);
 		if (!pipe) return -1;
@@ -344,7 +400,7 @@
 	return 0;
 }
 
-int twrpTar::closeTar(string fn, bool gzip) {
+int twrpTar::closeTar(bool gzip) {
 	int use_compression;
 	DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
 
@@ -354,7 +410,7 @@
 		return -1;
 	}
 	if (tar_close(t) != 0) {
-		LOGE("Unable to close tar archive: '%s'\n", fn.c_str());
+		LOGE("Unable to close tar archive: '%s'\n", tarfn.c_str());
 		return -1;
 	}
 	if (use_compression || gzip) {
@@ -369,19 +425,19 @@
 	char* charTarFile = (char*) tarFile.c_str();
 	off_t tarFileEnd;
 	while (th_read(t) == 0) {
-		if (TH_ISREG(t)) 
+		if (TH_ISREG(t))
 			tar_skip_regfile(t);
 		tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
-	}	
+	}
 	if (tar_close(t) == -1)
 		return -1;
-	if (truncate(charTarFile, tarFileEnd) == -1) 
+	if (truncate(charTarFile, tarFileEnd) == -1)
 		return -1;
 	return 0;
 }
 
 int twrpTar::compress(string fn) {
-	string cmd = "pigz " + fn; 
+	string cmd = "pigz " + fn;
 	p = popen(cmd.c_str(), "r");
 	if (!p) return -1;
 	char buffer[128];
@@ -394,11 +450,11 @@
 	return 0;
 }
 
-int twrpTar::extractTGZ(string rootdir, string fn) {
-	string splatrootdir(rootdir);
+int twrpTar::extractTGZ() {
+	string splatrootdir(tardir);
 	bool gzip = true;
         char* splatCharRootDir = (char*) splatrootdir.c_str();
-	if (openTar(rootdir, fn, gzip) == -1)
+	if (openTar(gzip) == -1)
 		return -1;
 	int ret = tar_extract_all(t, splatCharRootDir);
 	if (tar_close(t) != 0) {
diff --git a/twrpTar.hpp b/twrpTar.hpp
index 554a01d..db9cf9b 100644
--- a/twrpTar.hpp
+++ b/twrpTar.hpp
@@ -32,30 +32,39 @@
 
 class twrpTar {
 	public:
-		int create(string dir, string fn);
-		int createTGZ(string dir, string fn);
-		int extract(string rootDir, string fn);
+		int extract();
 		int compress(string fn);
-		int extractTGZ(string rootdir, string fn);
 		int uncompress(string fn);
                 int addFilesToExistingTar(vector <string> files, string tarFile);
-		int createTar(string dir, string fn);
-		int openTar(string rootdir, string fn, bool gzip);
+		int createTar();
 		int addFile(string fn, bool include_root);
-		int closeTar(string fn, bool gzip);
-		int Split_Archive(string Path, string fn);
+		int closeTar(bool gzip);
+		int createTarGZThread();
+		int createTarThread();
+		int extractTarThread();
+		int splitArchiveThread();
+                void setfn(string fn);
+                void setdir(string dir);
 	private:
+		int createTGZ();
+		int create();
+		int Split_Archive();
 		int removeEOT(string tarFile);
-		int extractTar(string rootdir, string fn);
-		int tarDirs(string dir, string fn, bool include_root);
-		int Generate_Multiple_Archives(string Path, string fn);
-
-	private:
+		int extractTar();
+		int tarDirs(bool include_root);
+		int Generate_Multiple_Archives(string Path);
+		string Strip_Root_Dir(string Path);
+		int extractTGZ();
+		int openTar(bool gzip);
 		int has_data_media;
 		int Archive_File_Count;
 		unsigned long long Archive_Current_Size;
-		string Strip_Root_Dir(string Path);
 		TAR *t;
 		FILE* p;
 		int fd;
+		string tardir;
+		string tarfn;
+		string basefn;
+		typedef int (twrpTar::*ThreadPtr)(void);
+		typedef void* (*PThreadPtr)(void*);
 }; 
diff --git a/variables.h b/variables.h
index f56a469..91c1f2c 100644
--- a/variables.h
+++ b/variables.h
@@ -164,7 +164,7 @@
 //   tw_sp2_is_mountable
 //   tw_sp3_is_mountable
 
-// Max archive size for tar backups before we split (4GB)
-#define MAX_ARCHIVE_SIZE 4294967296LLU
+// Max archive size for tar backups before we split (1.5GB)
+#define MAX_ARCHIVE_SIZE 1610612736LLU
 
 #endif  // _VARIABLES_HEADER_