ADB Backup: add ability for TWRP GUI to restore

Restore adb backup files that TWRP made to your PC.
Put files in your backup directory to see them.

e.g. /sdcard/TWRP/BACKUPS/<sn>

Change-Id: I2c57970d77b64c39a302159041456e761c185259
diff --git a/Android.mk b/Android.mk
index 04b8653..11bf006 100644
--- a/Android.mk
+++ b/Android.mk
@@ -61,7 +61,8 @@
     twrp-functions.cpp \
     twrpDigestDriver.cpp \
     openrecoveryscript.cpp \
-    tarWrite.c
+    tarWrite.c \
+    twrpAdbBuFifo.cpp
 
 ifneq ($(TARGET_RECOVERY_REBOOT_SRC),)
   LOCAL_SRC_FILES += $(TARGET_RECOVERY_REBOOT_SRC)
diff --git a/adbbu/Android.mk b/adbbu/Android.mk
index 33d3ad7..efb5f9a 100644
--- a/adbbu/Android.mk
+++ b/adbbu/Android.mk
@@ -1,10 +1,35 @@
 LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libtwadbbu
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS = -fno-strict-aliasing -D_LARGFILE_SOURCE
+LOCAL_C_INCLUDES += bionic external/zlib
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0)
+    LOCAL_C_INCLUDES += external/stlport/stlport
+endif
+
+LOCAL_SRC_FILES = \
+        libtwadbbu.cpp \
+        twrpback.cpp
+
+LOCAL_SHARED_LIBRARIES += libz libc libstdc++ libtwrpdigest
+
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0)
+    LOCAL_SHARED_LIBRARIES += libstlport
+else
+    LOCAL_SHARED_LIBRARIES += libc++
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	twrpback.cpp
+        adbbumain.cpp
 
-LOCAL_SHARED_LIBRARIES += libstdc++ libz libtwrpdigest
+LOCAL_SHARED_LIBRARIES += libstdc++ libz libtwadbbu
+
 ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0)
     LOCAL_C_INCLUDES += external/stlport/stlport
     LOCAL_SHARED_LIBRARIES += libstlport
@@ -21,21 +46,3 @@
 LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
 include $(BUILD_EXECUTABLE)
 
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtwadbbu
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS = -D_FILE_OFFSET_BITS=64 -fno-strict-aliasing
-LOCAL_C_INCLUDES += bionic external/zlib
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0)
-    LOCAL_C_INCLUDES += external/stlport/stlport
-    LOCAL_SHARED_LIBRARIES += libstlport
-else
-    LOCAL_SHARED_LIBRARIES += libc++
-endif
-
-LOCAL_SRC_FILES = \
-    libtwadbbu.cpp
-
-LOCAL_SHARED_LIBRARIES += libz libc libstdc++
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/adbbu/adbbumain.cpp b/adbbu/adbbumain.cpp
new file mode 100644
index 0000000..050c9bc
--- /dev/null
+++ b/adbbu/adbbumain.cpp
@@ -0,0 +1,89 @@
+/*
+		Copyright 2013 to 2017 TeamWin
+		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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string>
+#include <sstream>
+
+#include "twrpback.hpp"
+#include "twadbstream.h"
+
+
+int main(int argc, char **argv) {
+	int index;
+	int ret = 0, pos = 0;
+	int maxpos = sizeof(TWRPARG + 2);
+	std::string command;
+	twrpback tw;
+
+	tw.adblogwrite("Starting adb backup and restore\n");
+	command = argv[1];
+	for (index = 2; index < argc; index++) {
+		command = command + " " + argv[index];
+	}
+
+	pos = command.find(TWRP_BACKUP_ARG);
+	if (pos < 0 || pos > (maxpos + sizeof(TWRP_BACKUP_ARG) + 1)) {
+		pos = command.find(TWRP_RESTORE_ARG);
+	}
+	if (pos < 0 || pos > maxpos + sizeof(TWRP_STREAM_ARG + 1)) {
+		pos = command.find(TWRP_STREAM_ARG);
+	}
+
+	tw.adblogwrite("command: " + command + "\n");
+	command.erase(0, pos);
+	command.erase(std::remove(command.begin(), command.end(), '\''), command.end());
+
+	if (command.substr(0, sizeof(TWRP_BACKUP_ARG) - 1) == TWRP_BACKUP_ARG) {
+		tw.adblogwrite("Starting adb backup\n");
+		if (isdigit(*argv[1]))
+			tw.adbd_fd = atoi(argv[1]);
+		else
+			tw.adbd_fd = 1;
+		ret = tw.backup(command);
+	}
+	else if (command.substr(0, sizeof(TWRP_RESTORE_ARG) - 1) == TWRP_RESTORE_ARG) {
+		tw.adblogwrite("Starting adb restore\n");
+		if (isdigit(*argv[1]))
+			tw.adbd_fd = atoi(argv[1]);
+		else
+			tw.adbd_fd = 0;
+		ret = tw.restore();
+	}
+	else if (command.substr(0, sizeof(TWRP_STREAM_ARG) - 1) == TWRP_STREAM_ARG) {
+		tw.setStreamFileName(argv[3]);
+		tw.threadStream();
+	}
+	if (ret == 0)
+		tw.adblogwrite("Adb backup/restore completed\n");
+	else
+		tw.adblogwrite("Adb backup/restore failed\n");
+
+	if (unlink(TW_ADB_BU_CONTROL) < 0) {
+		std::stringstream str;
+		str << strerror(errno);
+		tw.adblogwrite("Unable to remove TW_ADB_BU_CONTROL: " + str.str());
+	}
+	unlink(TW_ADB_TWRP_CONTROL);
+	return ret;
+}
diff --git a/adbbu/libtwadbbu.cpp b/adbbu/libtwadbbu.cpp
index cdc2170..a13ecb2 100644
--- a/adbbu/libtwadbbu.cpp
+++ b/adbbu/libtwadbbu.cpp
@@ -1,5 +1,5 @@
 /*
-		Copyright 2013 to 2016 TeamWin
+		Copyright 2013 to 2017 TeamWin
 		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
@@ -27,12 +27,107 @@
 #include <sys/select.h>
 #include <sys/time.h>
 #include <string>
+#include <vector>
 #include <fstream>
 #include <sstream>
 
 #include "twadbstream.h"
 #include "libtwadbbu.hpp"
 
+bool twadbbu::Check_ADB_Backup_File(std::string fname) {
+	struct AdbBackupStreamHeader adbbuhdr;
+	uint32_t crc, adbbuhdrcrc;
+	unsigned char buf[MAX_ADB_READ];
+	int bytes;
+
+	int fd = open(fname.c_str(), O_RDONLY);
+	if (fd < 0) {
+		printf("Unable to open %s for reading: %s.\n", fname.c_str(), strerror(errno));
+		close(fd);
+		return false;
+	}
+	bytes = read(fd, &buf, sizeof(buf));
+	close(fd);
+
+	if (memcpy(&adbbuhdr, buf, sizeof(adbbuhdr)) < 0) {
+		printf("Unable to memcpy: %s.\n", fname.c_str(), strerror(errno));
+		return false;
+	}
+	adbbuhdrcrc = adbbuhdr.crc;
+	memset(&adbbuhdr.crc, 0, sizeof(adbbuhdr.crc));
+	crc = crc32(0L, Z_NULL, 0);
+	crc = crc32(crc, (const unsigned char*) &adbbuhdr, sizeof(adbbuhdr));
+
+	return (crc == adbbuhdrcrc);
+}
+
+std::vector<std::string> twadbbu::Get_ADB_Backup_Files(std::string fname) {
+	unsigned char buf[MAX_ADB_READ];
+	struct AdbBackupControlType structcmd;
+	std::vector<std::string> adb_partitions;
+
+	int fd = open(fname.c_str(), O_RDONLY);
+	if (fd < 0) {
+		printf("Unable to open %s for reading: %s\n", fname.c_str(), strerror(errno));
+		close(fd);
+		return std::vector<std::string>();
+	}
+
+	while (1) {
+		std::string cmdstr;
+		int readbytes;
+		if (readbytes = read(fd, &buf, sizeof(buf)) > 0) {
+			memcpy(&structcmd, buf, sizeof(structcmd));
+			assert(structcmd.type == TWENDADB || structcmd.type == TWIMG || structcmd.type == TWFN);
+			cmdstr = structcmd.type;
+			std::string cmdtype = cmdstr.substr(0, sizeof(structcmd.type) - 1);
+			if (cmdtype == TWENDADB) {
+				struct AdbBackupControlType endadb;
+				uint32_t crc, endadbcrc;
+
+				memcpy(&endadb, buf, sizeof(endadb));
+				endadbcrc = endadb.crc;
+				memset(&endadb.crc, 0, sizeof(endadb.crc));
+				crc = crc32(0L, Z_NULL, 0);
+				crc = crc32(crc, (const unsigned char*) &endadb, sizeof(endadb));
+
+				if (crc == endadbcrc) {
+					break;
+				}
+				else {
+					printf("ADB TWENDADB crc header doesn't match\n");
+					close(fd);
+					return std::vector<std::string>();
+				}
+			}
+			else if (cmdtype == TWIMG || cmdtype == TWFN) {
+				struct twfilehdr twfilehdr;
+				uint32_t crc, twfilehdrcrc;
+
+				memcpy(&twfilehdr, buf, sizeof(twfilehdr));
+				twfilehdrcrc = twfilehdr.crc;
+				memset(&twfilehdr.crc, 0, sizeof(twfilehdr.crc));
+
+				crc = crc32(0L, Z_NULL, 0);
+				crc = crc32(crc, (const unsigned char*) &twfilehdr, sizeof(twfilehdr));
+				if (crc == twfilehdrcrc) {
+					std::string adbfile = twfilehdr.name;
+					int pos = adbfile.find_last_of("/") + 1;
+					adbfile = adbfile.substr(pos, adbfile.size());
+					adb_partitions.push_back(adbfile);
+				}
+				else {
+					printf("ADB crc header doesn't match\n");
+					close(fd);
+					return std::vector<std::string>();
+				}
+			}
+		}
+	}
+	close(fd);
+	return adb_partitions;
+}
+
 bool twadbbu::Write_ADB_Stream_Header(uint64_t partition_count) {
 	struct AdbBackupStreamHeader twhdr;
 	int adb_control_bu_fd;
@@ -40,7 +135,7 @@
 	memset(&twhdr, 0, sizeof(twhdr));
 	adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK);
 	if (adb_control_bu_fd < 0) {
-		printf("Cannot write to TW_ADB_BU_CONTROL.\n");
+		printf("Cannot write to TW_ADB_BU_CONTROL: %s\n", strerror(errno));
 		return false;
 	}
 
@@ -52,7 +147,7 @@
 	twhdr.crc = crc32(0L, Z_NULL, 0);
 	twhdr.crc = crc32(twhdr.crc, (const unsigned char*) &twhdr, sizeof(twhdr));
 	if (write(adb_control_bu_fd, &twhdr, sizeof(twhdr)) < 0) {
-		printf("Cannot write to adb control channel\n");
+		printf("Cannot write to adb control channel: %s\n", strerror(errno));
 		close(adb_control_bu_fd);
 		return false;
 	}
@@ -67,7 +162,7 @@
 
 	adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY);
 	if (adb_control_bu_fd < 0) {
-		printf("Error opening adb_control_bu_fd\n");
+		printf("Error opening adb_control_bu_fd: %s\n", strerror(errno));
 		return false;
 	}
 	strncpy(endadb.start_of_header, TWRP, sizeof(endadb.start_of_header));
@@ -75,7 +170,7 @@
 	endadb.crc = crc32(0L, Z_NULL, 0);
 	endadb.crc = crc32(endadb.crc, (const unsigned char*) &endadb, sizeof(endadb));
 	if (write(adb_control_bu_fd, &endadb, sizeof(endadb)) < 0) {
-		printf("Cannot write to ADB control.\n");
+		printf("Cannot write to ADB control: %s\n", strerror(errno));
 		close(adb_control_bu_fd);
 		return false;
 	}
@@ -97,10 +192,11 @@
 
 	printf("Sending TWFN to adb\n");
 	if (write(adb_control_bu_fd, &twfilehdr, sizeof(twfilehdr)) < 1) {
-		printf("Cannot that write to adb_control_bu_fd\n");
+		printf("Cannot that write to adb_control_bu_fd: %s\n", strerror(errno));
 		close(adb_control_bu_fd);
 		return false;
 	}
+	fsync(adb_control_bu_fd);
 	close(adb_control_bu_fd);
 	return true;
 }
@@ -118,7 +214,7 @@
 	twimghdr.crc = crc32(twimghdr.crc, (const unsigned char*) &twimghdr, sizeof(twimghdr));
 	printf("Sending TWIMG to adb\n");
 	if (write(adb_control_bu_fd, &twimghdr, sizeof(twimghdr)) < 1) {
-		printf("Cannot write to adb control channel\n");
+		printf("Cannot write to adb control channel: %s\n", strerror(errno));
 		return false;
 	}
 
@@ -168,7 +264,7 @@
 	twerror.crc = crc32(0L, Z_NULL, 0);
 	twerror.crc = crc32(twerror.crc, (const unsigned char*) &twerror, sizeof(twerror));
 	if (write(adb_control_bu_fd, &twerror, sizeof(twerror)) < 0) {
-		printf("Cannot write to adb control channel");
+		printf("Cannot write to adb control channel: %s\n", strerror(errno));
 		return false;
 	}
 	close(adb_control_bu_fd);
diff --git a/adbbu/libtwadbbu.hpp b/adbbu/libtwadbbu.hpp
index bcd8b6a..ff9a3eb 100644
--- a/adbbu/libtwadbbu.hpp
+++ b/adbbu/libtwadbbu.hpp
@@ -1,5 +1,5 @@
 /*
-		Copyright 2013 to 2016 TeamWin
+		Copyright 2013 to 2017 TeamWin
 		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
@@ -13,6 +13,8 @@
 		You should have received a copy of the GNU General Public License
 		along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
 */
+#ifndef _LIBTWADBBU_HPP
+#define _LIBTWADBBU_HPP
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -26,6 +28,7 @@
 #include <sys/select.h>
 #include <sys/time.h>
 #include <string>
+#include <vector>
 #include <fstream>
 #include <sstream>
 
@@ -34,6 +37,8 @@
 
 class twadbbu {
 public:
+	static bool Check_ADB_Backup_File(std::string fname);                                          //Check if file is ADB Backup file
+	static std::vector<std::string> Get_ADB_Backup_Files(std::string fname);                       //List ADB Files in String Vector
 	static bool Write_ADB_Stream_Header(uint64_t partition_count);                                 //Write ADB Stream Header to stream
 	static bool Write_ADB_Stream_Trailer();                                                        //Write ADB Stream Trailer to stream
 	static bool Write_TWFN(std::string Backup_FileName, uint64_t file_size, bool use_compression); //Write a tar image to stream
@@ -42,3 +47,5 @@
 	static bool Write_TWERROR();                                                                   //Write error message occurred to stream
 	static bool Write_TWENDADB();                                                                  //Write ADB End-Of-Stream command to stream
 };
+
+#endif //__LIBTWADBBU_HPP
diff --git a/adbbu/twadbstream.h b/adbbu/twadbstream.h
index 5fa6bde..3c73084 100644
--- a/adbbu/twadbstream.h
+++ b/adbbu/twadbstream.h
@@ -1,27 +1,33 @@
 /*
-		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 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.
+	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/>.
+	You should have received a copy of the GNU General Public License
+	along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #ifndef __TWADBSTREAM_H
 #define __TWADBSTREAM_H
 
+#define TWRPARG "--twrp"
+#define TWRP_BACKUP_ARG "backup"
+#define TWRP_RESTORE_ARG "restore"
+#define TWRP_STREAM_ARG "stream"
 #define TW_ADB_BACKUP "/tmp/twadbbackup"		//FIFO for adb backup
 #define TW_ADB_RESTORE "/tmp/twadbrestore"		//FIFO for adb restore
 #define TW_ADB_BU_CONTROL "/tmp/twadbbucontrol"		//FIFO for sending control from TWRP to ADB Backup
 #define TW_ADB_TWRP_CONTROL "/tmp/twadbtwrpcontrol"	//FIFO for sending control from ADB Backup to TWRP
 #define TWRP "TWRP"					//Magic Value
 #define ADB_BU_MAX_ERROR 20				//Max amount of errors for while loops
+#define ADB_BACKUP_OP "adbbackup"
+#define ADB_RESTORE_OP "adbrestore"
 
 //ADB Backup Control Commands
 #define TWSTREAMHDR "twstreamheader"			//TWRP Parititon Count Control
diff --git a/adbbu/twrpback.cpp b/adbbu/twrpback.cpp
index 8652de2..2c7ea69 100644
--- a/adbbu/twrpback.cpp
+++ b/adbbu/twrpback.cpp
@@ -1,5 +1,5 @@
 /*
-		Copyright 2013 to 2016 TeamWin
+		Copyright 2013 to 2017 TeamWin
 		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
@@ -28,14 +28,17 @@
 #include <ctype.h>
 #include <semaphore.h>
 #include <string>
-#include <fstream>
 #include <sstream>
+#include <fstream>
 #include <algorithm>
+#include <utils/threads.h>
+#include <pthread.h>
 
 #include "twadbstream.h"
 #include "twrpback.hpp"
 #include "../twrpDigest/twrpDigest.hpp"
 #include "../twrpDigest/twrpMD5.hpp"
+#include "../twrpAdbBuFifo.hpp"
 
 twrpback::twrpback(void) {
 	read_fd = 0;
@@ -47,11 +50,40 @@
 	adb_write_fd = 0;
 	ors_fd = 0;
 	firstPart = true;
+	createFifos();
 	adbloginit();
 }
 
 twrpback::~twrpback(void) {
 	adblogfile.close();
+	closeFifos();
+}
+
+void twrpback::createFifos(void) {
+        if (mkfifo(TW_ADB_BU_CONTROL, 0666) < 0) {
+                std::stringstream str;
+                str << strerror(errno);
+                adblogwrite("Unable to create TW_ADB_BU_CONTROL fifo: " + str.str() + "\n");
+        }
+        if (mkfifo(TW_ADB_TWRP_CONTROL, 0666) < 0) {
+                std::stringstream str;
+                str << strerror(errno);
+                adblogwrite("Unable to create TW_ADB_TWRP_CONTROL fifo: " + str.str() + "\n");
+                unlink(TW_ADB_BU_CONTROL);
+        }
+}
+
+void twrpback::closeFifos(void) {
+        if (unlink(TW_ADB_BU_CONTROL) < 0) {
+                std::stringstream str;
+                str << strerror(errno);
+                adblogwrite("Unable to remove TW_ADB_BU_CONTROL: " + str.str());
+        }
+        if (unlink(TW_ADB_TWRP_CONTROL) < 0) {
+                std::stringstream str;
+                str << strerror(errno);
+                adblogwrite("Unable to remove TW_ADB_TWRP_CONTROL: " + str.str());
+	}
 }
 
 void twrpback::adbloginit(void) {
@@ -119,14 +151,14 @@
 		return -1;
 	}
 
-	adblogwrite("opening ORS_INPUT_FILE\n");
-	write_fd = open(ORS_INPUT_FILE, O_WRONLY);
+	adblogwrite("opening TW_ADB_FIFO\n");
+	write_fd = open(TW_ADB_FIFO, O_WRONLY);
 	while (write_fd < 0) {
-		write_fd = open(ORS_INPUT_FILE, O_WRONLY);
+		write_fd = open(TW_ADB_FIFO, O_WRONLY);
 		usleep(10000);
 		errctr++;
 		if (errctr > ADB_BU_MAX_ERROR) {
-			adblogwrite("Unable to open ORS_INPUT_FILE\n");
+			adblogwrite("Unable to open TW_ADB_FIFO\n");
 			close_backup_fds();
 			return -1;
 		}
@@ -144,14 +176,6 @@
 		return -1;
 	}
 
-	adblogwrite("opening ORS_OUTPUT_FILE\n");
-	ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY);
-	if (ors_fd < 0) {
-		adblogwrite("Unable to open ORS_OUTPUT_FILE\n");
-		close_backup_fds();
-		return -1;
-	}
-
 	memset(&result, 0, sizeof(result));
 	memset(&cmd, 0, sizeof(cmd));
 
@@ -263,7 +287,7 @@
 				count = totalbytes / MAX_ADB_READ + 1;
 				count = count * MAX_ADB_READ;
 
-				while ((bytes = read(adb_read_fd, &result, sizeof(result))) == MAX_ADB_READ) {
+				while ((bytes = read(adb_read_fd, &result, sizeof(result))) > 0) {
 					totalbytes += bytes;
 					char *writeresult = new char [bytes];
 					memcpy(writeresult, result, bytes);
@@ -421,14 +445,14 @@
 		return -1;
 	}
 
-	adblogwrite("opening ORS_INPUT_FILE\n");
-	write_fd = open(ORS_INPUT_FILE, O_WRONLY);
+	adblogwrite("opening TW_ADB_FIFO\n");
+	write_fd = open(TW_ADB_FIFO, O_WRONLY);
 
 	while (write_fd < 0) {
-		write_fd = open(ORS_INPUT_FILE, O_WRONLY);
+		write_fd = open(TW_ADB_FIFO, O_WRONLY);
 		errctr++;
 		if (errctr > ADB_BU_MAX_ERROR) {
-			adblogwrite("Unable to open ORS_INPUT_FILE\n");
+			adblogwrite("Unable to open TW_ADB_FIFO\n");
 			close_restore_fds();
 			return -1;
 		}
@@ -437,16 +461,7 @@
 	memset(operation, 0, sizeof(operation));
 	sprintf(operation, "adbrestore");
 	if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
-		adblogwrite("Unable to write to ORS_INPUT_FILE\n");
-		close_restore_fds();
-		return -1;
-	}
-
-	ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY);
-	if (ors_fd < 0) {
-		std::stringstream str;
-		str << strerror(errno);
-		adblogwrite("Unable to write to ORS_OUTPUT_FILE: " + str.str() + "\n");
+		adblogwrite("Unable to write to TW_ADB_FIFO\n");
 		close_restore_fds();
 		return -1;
 	}
@@ -748,74 +763,25 @@
 	return 0;
 }
 
-int main(int argc, char **argv) {
-	int index;
-	int ret = 0, pos = 0;
-	std::string command;
-	twrpback tw;
+void twrpback::streamFileForTWRP(void) {
+	adblogwrite("streamFileForTwrp" + streamFn + "\n");
+}
 
-	tw.adblogwrite("Starting adb backup and restore\n");
-	if (mkfifo(TW_ADB_BU_CONTROL, 0666) < 0) {
-		std::stringstream str;
-		str << strerror(errno);
-		tw.adblogwrite("Unable to create TW_ADB_BU_CONTROL fifo: " + str.str() + "\n");
-		unlink(TW_ADB_BU_CONTROL);
-		return -1;
+void twrpback::setStreamFileName(std::string fn) {
+	streamFn = fn;
+	adbd_fd = open(fn.c_str(), O_RDONLY);
+	if (adbd_fd < 0) {
+		adblogwrite("Unable to open adb_fd\n");
+		close(adbd_fd);
+		return;
 	}
-	if (mkfifo(TW_ADB_TWRP_CONTROL, 0666) < 0) {
-		std::stringstream str;
-		str << strerror(errno);
-		tw.adblogwrite("Unable to create TW_ADB_TWRP_CONTROL fifo: " + str.str() + "\n");
-		unlink(TW_ADB_TWRP_CONTROL);
-		unlink(TW_ADB_BU_CONTROL);
-		return -1;
-	}
+	restore();
+}
 
-	if (argc <= 1) {
-		tw.adblogwrite("No parameters given, exiting...\n");
-		tw.close_restore_fds();
-		return -1;
-	}
-
-	command = argv[1];
-	for (index = 2; index < argc; index++) {
-		command = command + " " + argv[index];
-	}
-
-	pos = command.find("backup");
-	if (pos < 0) {
-		pos = command.find("restore");
-	}
-	command.erase(0, pos);
-	command.erase(std::remove(command.begin(), command.end(), '\''), command.end());
-	tw.adblogwrite("command: " + command + "\n");
-
-	if (command.substr(0, sizeof("backup") - 1) == "backup") {
-		tw.adblogwrite("Starting adb backup\n");
-		if (isdigit(*argv[1]))
-			tw.adbd_fd = atoi(argv[1]);
-		else
-			tw.adbd_fd = 1;
-		ret = tw.backup(command);
-	}
-	else if (command.substr(0, sizeof("restore") - 1) == "restore") {
-		tw.adblogwrite("Starting adb restore\n");
-		if (isdigit(*argv[1]))
-			tw.adbd_fd = atoi(argv[1]);
-		else
-			tw.adbd_fd = 0;
-		ret = tw.restore();
-	}
-	if (ret == 0)
-		tw.adblogwrite("Adb backup/restore completed\n");
-	else
-		tw.adblogwrite("Adb backup/restore failed\n");
-
-	if (unlink(TW_ADB_BU_CONTROL) < 0) {
-		std::stringstream str;
-		str << strerror(errno);
-		tw.adblogwrite("Unable to remove TW_ADB_BU_CONTROL: " + str.str());
-	}
-	unlink(TW_ADB_TWRP_CONTROL);
-	return ret;
+void twrpback::threadStream(void) {
+	pthread_t thread;
+	ThreadPtr streamPtr = &twrpback::streamFileForTWRP;
+	PThreadPtr p = *(PThreadPtr*)&streamPtr;
+	pthread_create(&thread, NULL, p, this);
+	pthread_join(thread, NULL);
 }
diff --git a/adbbu/twrpback.hpp b/adbbu/twrpback.hpp
index 752d35e..1c6b09f 100644
--- a/adbbu/twrpback.hpp
+++ b/adbbu/twrpback.hpp
@@ -1,5 +1,5 @@
 /*
-		Copyright 2013 to 2016 TeamWin
+		Copyright 2013 to 2017 TeamWin
 		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
@@ -14,23 +14,24 @@
 		along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include <fstream>
+#ifndef _TWRPBACK_HPP
+#define _TWRPBACK_HPP
 
-#include "../orscmd/orscmd.h"
-#include "../variables.h"
-#include "../twcommon.h"
+#include <fstream>
 
 class twrpback {
 public:
 	int adbd_fd;                                                             // adbd data stream
-
 	twrpback(void);
 	virtual ~twrpback(void);
 	int backup(std::string command);                                         // adb backup stream
 	int restore(void);                                                       // adb restore stream
 	void adblogwrite(std::string writemsg);                                  // adb debugging log function
-	void close_backup_fds();                                                 // close backup resources
-	void close_restore_fds();                                                // close restore resources
+	void createFifos(void);                                                  // create fifos needed for adb backup
+	void closeFifos(void);                                                   // close created fifos
+	void streamFileForTWRP(void);                                            // stream file to twrp via bu
+	void setStreamFileName(std::string fn);                                  // tell adb backup what file to load on storage
+	void threadStream(void);                                                 // thread bu for streaming
 
 private:
 	int read_fd;                                                             // ors input fd
@@ -45,5 +46,12 @@
 	char cmd[512];                                                           // store result of commands
 	char operation[512];                                                     // operation to send to ors
 	std::ofstream adblogfile;                                                // adb stream log file
+	std::string streamFn;
+	typedef void (twrpback::*ThreadPtr)(void);
+	typedef void* (*PThreadPtr)(void *);
 	void adbloginit(void);                                                   // setup adb log stream file
+	void close_backup_fds();                                                 // close backup resources
+	void close_restore_fds();                                                // close restore resources
 };
+
+#endif // _TWRPBACK_HPP
diff --git a/gui/action.cpp b/gui/action.cpp
index 05ae465..039c4ef 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -566,6 +566,7 @@
 int GUIAction::readBackup(std::string arg __unused)
 {
 	string Restore_Name;
+
 	DataManager::GetValue("tw_restore", Restore_Name);
 	PartitionManager.Set_Restore_Files(Restore_Name);
 	return 0;
@@ -1192,6 +1193,18 @@
 			string auto_gen = gui_lookup("auto_generate", "(Auto Generate)");
 			if (Backup_Name == auto_gen || Backup_Name == gui_lookup("curr_date", "(Current Date)") || Backup_Name == "0" || Backup_Name == "(" || PartitionManager.Check_Backup_Name(true) == 0) {
 				ret = PartitionManager.Run_Backup(false);
+				DataManager::SetValue("tw_encrypt_backup", 0); // reset value so we don't encrypt every subsequent backup
+				if (!PartitionManager.stop_backup.get_value()) {
+					if (ret == false)
+						ret = 1; // 1 for failure
+					else
+						ret = 0; // 0 for success
+					DataManager::SetValue("tw_cancel_backup", 0);
+				} else {
+					DataManager::SetValue("tw_cancel_backup", 1);
+					gui_msg("backup_cancel=Backup Cancelled");
+					ret = 0;
+				}
 			} else {
 				operation_end(1);
 				return -1;
@@ -1199,25 +1212,28 @@
 			DataManager::SetValue(TW_BACKUP_NAME, auto_gen);
 		} else if (arg == "restore") {
 			string Restore_Name;
+			int gui_adb_backup;
+
 			DataManager::GetValue("tw_restore", Restore_Name);
-			ret = PartitionManager.Run_Restore(Restore_Name);
+			DataManager::GetValue("tw_enable_adb_backup", gui_adb_backup);
+			if (gui_adb_backup) {
+				DataManager::SetValue("tw_operation_state", 1);
+				if (TWFunc::stream_adb_backup(Restore_Name) == 0)
+					ret = 0; // success
+				else
+					ret = 1; // failure
+				DataManager::SetValue("tw_enable_adb_backup", 0);
+				ret = 0; // assume success???
+			} else {
+				if (PartitionManager.Run_Restore(Restore_Name))
+					ret = 0; // success
+				else
+					ret = 1; // failure
+			}
 		} else {
-			operation_end(1);
+			operation_end(1); // invalid arg specified, fail
 			return -1;
 		}
-		DataManager::SetValue("tw_encrypt_backup", 0);
-		if (!PartitionManager.stop_backup.get_value()) {
-			if (ret == false)
-				ret = 1; // 1 for failure
-			else
-				ret = 0; // 0 for success
-			DataManager::SetValue("tw_cancel_backup", 0);
-		}
-		else {
-			DataManager::SetValue("tw_cancel_backup", 1);
-			gui_msg("backup_cancel=Backup Cancelled");
-			ret = 0;
-		}
 		operation_end(ret);
 		return ret;
 	}
diff --git a/gui/fileselector.cpp b/gui/fileselector.cpp
index a992b80..c4aaab1 100644
--- a/gui/fileselector.cpp
+++ b/gui/fileselector.cpp
@@ -30,6 +30,7 @@
 #include "objects.hpp"
 #include "../data.hpp"
 #include "../twrp-functions.hpp"
+#include "../adbbu/libtwadbbu.hpp"
 
 int GUIFileSelector::mSortOrder = 0;
 
@@ -270,7 +271,10 @@
 				mFolderList.push_back(data);
 		} else if (data.fileType == DT_REG || data.fileType == DT_LNK || data.fileType == DT_BLK) {
 			if (mExtn.empty() || (data.fileName.length() > mExtn.length() && data.fileName.substr(data.fileName.length() - mExtn.length()) == mExtn)) {
-				mFileList.push_back(data);
+				if (mExtn == ".ab" && twadbbu::Check_ADB_Backup_File(path))
+					mFolderList.push_back(data);
+				else
+					mFileList.push_back(data);
 			}
 		}
 	}
@@ -354,8 +358,8 @@
 				cwd += str;
 			}
 
-			if (mShowNavFolders == 0 && mShowFiles == 0) {
-				// nav folders and files are disabled, this is probably the restore list and we need to save chosen location to mVariable instead of mPathVar
+			if (mShowNavFolders == 0 && (mShowFiles == 0 || mExtn == ".ab")) {
+				// this is probably the restore list and we need to save chosen location to mVariable instead of mPathVar
 				DataManager::SetValue(mVariable, cwd);
 			} else {
 				// We are changing paths, so we need to set mPathVar
diff --git a/gui/gui.cpp b/gui/gui.cpp
index 369b6b8..a70dadf 100644
--- a/gui/gui.cpp
+++ b/gui/gui.cpp
@@ -462,14 +462,6 @@
 				gui_set_FILE(orsout);
 				PageManager::GetResources()->DumpStrings();
 				ors_command_done();
-			//check to see if we should show backup page for parsing adbbackup partitions
-			} else if (strlen(command) == 23 && strncmp(command, "adbbackup", 9) == 0) {
-				gui_set_FILE(orsout);
-				DataManager::SetValue("tw_action", "twcmd");
-				DataManager::SetValue("tw_action_param", command);
-				DataManager::SetValue("tw_enable_adb_backup", 1);
-				gui_changePage("backup");
-				ors_command_done();
 			} else {
 				// mirror output messages
 				gui_set_FILE(orsout);
diff --git a/gui/theme/common/landscape.xml b/gui/theme/common/landscape.xml
index c3d89fe..f460e6f 100644
--- a/gui/theme/common/landscape.xml
+++ b/gui/theme/common/landscape.xml
@@ -2047,7 +2047,7 @@
 			<fileselector>
 				<placement x="%col1_x_left%" y="%row1a_y%" w="%content_quarter_width%" h="%fileselector_install_height%"/>
 				<text>{@restore_sel_pack_fs=Select Package to Restore:}</text>
-				<filter folders="1" files="0" nav="0"/>
+				<filter folders="1" files="1" nav="0" extn=".ab"/>
 				<path name="tw_backups_folder"/>
 				<data name="tw_restore" default=""/>
 				<selection name="tw_restore_name"/>
@@ -2273,6 +2273,7 @@
 
 			<checkbox>
 				<placement x="%col1_x_right%" y="%row6_y%"/>
+				<condition var1="tw_enable_adb_backup" op="=" var2="0"/>
 				<text>{@restore_enable_digest_chk=Enable Digest Verification of Backup Files}</text>
 				<data variable="tw_skip_digest_check"/>
 			</checkbox>
diff --git a/gui/theme/common/portrait.xml b/gui/theme/common/portrait.xml
index f163bea..0d1d6d8 100644
--- a/gui/theme/common/portrait.xml
+++ b/gui/theme/common/portrait.xml
@@ -2209,7 +2209,7 @@
 			<fileselector>
 				<placement x="%indent%" y="%row3_y%" w="%content_width%" h="%fileselector_install_height%"/>
 				<text>{@restore_sel_pack_fs=Select Package to Restore:}</text>
-				<filter folders="1" files="0" nav="0"/>
+				<filter folders="1" files="1" nav="0" extn=".ab"/>
 				<path name="tw_backups_folder"/>
 				<data name="tw_restore" default=""/>
 				<selection name="tw_restore_name"/>
@@ -2429,6 +2429,7 @@
 			</partitionlist>
 
 			<checkbox>
+				<condition var1="tw_enable_adb_backup" op="=" var2="0"/>
 				<placement x="%indent%" y="%row17_y%"/>
 				<text>{@restore_enable_digest_chk=Enable Digest Verification of Backup Files}</text>
 				<data variable="tw_skip_digest_check"/>
diff --git a/gui/theme/common/watch.xml b/gui/theme/common/watch.xml
index d5ef869..152818e 100644
--- a/gui/theme/common/watch.xml
+++ b/gui/theme/common/watch.xml
@@ -2551,7 +2551,7 @@
 			<fileselector>
 				<placement x="%indent%" y="%row2_header_y%" w="%content_width%" h="%fileselector_install_height%"/>
 				<text>%tw_storage_display_name%</text>
-				<filter folders="1" files="0" nav="0"/>
+				<filter folders="1" files="1" nav="0" extn=".ab"/>
 				<path name="tw_backups_folder"/>
 				<data name="tw_restore" default=""/>
 				<selection name="tw_restore_name"/>
@@ -2807,6 +2807,7 @@
 			</text>
 
 			<listbox style="scrolllist">
+				<condition var1="tw_enable_adb_backup" op="=" var2="0"/>
 				<placement x="%col1_x_left%" y="%row2_header_y%" w="%content_width%" h="%partitionlist_wipe_height%"/>
 				<listitem name="{@restore_enable_digest_chk=Enable Digest Verification of Backup Files}">
 					<data variable="tw_skip_digest_check"/>
diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp
index 0235438..92cac07 100644
--- a/openrecoveryscript.cpp
+++ b/openrecoveryscript.cpp
@@ -1,5 +1,5 @@
 /*
-	Copyright 2016 TeamWin
+	Copyright 2003 to 2017 TeamWin
 	This file is part of TWRP/TeamWin Recovery Project.
 
 	TWRP is free software: you can redistribute it and/or modify
@@ -51,7 +51,6 @@
 #include "gui/gui.hpp"
 #include "gui/pages.hpp"
 #include "orscmd/orscmd.h"
-#include "adbbu/libtwadbbu.hpp"
 #include "twinstall.h"
 extern "C" {
 	#include "gui/gui.h"
@@ -292,15 +291,6 @@
 					ret_val = 1;
 				else
 					gui_msg("done=Done.");
-			} else if (strncmp(command, "adbbackup", 9) == 0) {
-				ret_val = Backup_ADB_Command(value);
-				if (ret_val == 1) {
-					twadbbu::Write_TWERROR();
-					gui_err("adbbackup_error=Error with ADB Backup. Quitting...");
-				}
-			} else if (strcmp(command, "adbrestore") == 0) {
-				LOGINFO("running adb restore\n");
-				ret_val = Restore_ADB_Backup();
 			} else if (strcmp(command, "remountrw") == 0) {
 				ret_val = remountrw();
 			} else if (strcmp(command, "mount") == 0) {
@@ -509,72 +499,6 @@
 	return ret_val;
 }
 
-int OpenRecoveryScript::Backup_ADB_Command(std::string Options) {
-	std::vector<std::string> args;
-	std::string Backup_List;
-	bool adbbackup = true, ret = false;
-	std::string rmopt = "--";
-
-	std::replace(Options.begin(), Options.end(), ':', ' ');
-	args = TWFunc::Split_String(Options, " ");
-
-	DataManager::SetValue(TW_USE_COMPRESSION_VAR, 0);
-	DataManager::SetValue(TW_SKIP_DIGEST_GENERATE_VAR, 0);
-
-	if (args[1].compare("--twrp") != 0) {
-		gui_err("twrp_adbbu_option=--twrp option is required to enable twrp adb backup");
-		sleep(2);
-		return 1;
-	}
-
-	for (unsigned i = 2; i < args.size(); i++) {
-		int compress;
-
-		std::string::size_type size = args[i].find(rmopt);
-		if (size != std::string::npos)
-			args[i].erase(size, rmopt.length());
-
-		if (args[i].compare("compress") == 0) {
-			gui_msg("compression_on=Compression is on");
-			DataManager::SetValue(TW_USE_COMPRESSION_VAR, 1);
-			continue;
-		}
-		DataManager::GetValue(TW_USE_COMPRESSION_VAR, compress);
-		gui_print("%s\n", args[i].c_str());
-		std::string path;
-		path = "/" + args[i];
-		TWPartition* part = PartitionManager.Find_Partition_By_Path(path);
-		if (part) {
-			Backup_List += path;
-			Backup_List += ";";
-		}
-		else {
-			gui_msg(Msg(msg::kError, "partition_not_found=path: {1} not found in partition list")(path));
-			return 1;
-		}
-	}
-
-	if (Backup_List.empty()) {
-		DataManager::GetValue("tw_backup_list", Backup_List);
-		if (Backup_List.empty()) {
-			gui_err("no_partition_selected=No partitions selected for backup.");
-			return 1;
-		}
-	}
-	else
-		DataManager::SetValue("tw_backup_list", Backup_List);
-
-	ret = PartitionManager.Run_Backup(adbbackup);
-	DataManager::SetValue(TW_BACKUP_NAME, gui_lookup("auto_generate", "(Auto Generate)"));
-	if (!ret) {
-		gui_err("backup_fail=Backup failed");
-		return 1;
-	}
-	gui_msg("backup_complete=Backup Complete");
-	sleep(2); //give time for user to see messages on console
-	return 0;
-}
-
 string OpenRecoveryScript::Locate_Zip_File(string Zip, string Storage_Root) {
 	string Path = TWFunc::Get_Path(Zip);
 	string File = TWFunc::Get_Filename(Zip);
@@ -742,191 +666,6 @@
 	LOGINFO("Done reading ORS command from command line\n");
 }
 
-int OpenRecoveryScript::Restore_ADB_Backup(void) {
-	bool breakloop = false;
-	int partition_count = 0;
-	std::string Restore_Name;
-	struct AdbBackupFileTrailer adbmd5;
-	struct PartitionSettings part_settings;
-	int adb_control_twrp_fd;
-	int adb_control_bu_fd, ret = 0;
-	char cmd[512];
-
-	part_settings.total_restore_size = 0;
-
-	PartitionManager.Mount_All_Storage();
-	DataManager::SetValue(TW_SKIP_DIGEST_CHECK_VAR, 0);
-
-	LOGINFO("opening TW_ADB_BU_CONTROL\n");
-	adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK);
-	if (adb_control_bu_fd < 0) {
-		LOGERR("Error opening TW_ADB_BU_CONTROL\n");
-		return -1;
-	}
-	LOGINFO("opening TW_ADB_TWRP_CONTROL\n");
-	adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_RDONLY | O_NONBLOCK);
-	if (adb_control_twrp_fd < 0) {
-		LOGERR("Error opening TW_ADB_TWRP_CONTROL\n");
-		close(adb_control_bu_fd);
-		return -1;
-	}
-
-	memset(&adbmd5, 0, sizeof(adbmd5));
-
-	while (!breakloop) {
-		memset(&cmd, 0, sizeof(cmd));
-		if (read(adb_control_twrp_fd, cmd, sizeof(cmd)) > 0) {
-			struct AdbBackupControlType cmdstruct;
-
-			memset(&cmdstruct, 0, sizeof(cmdstruct));
-			memcpy(&cmdstruct, cmd, sizeof(cmdstruct));
-			std::string cmdstr(cmdstruct.type);
-			std::string cmdtype = cmdstr.substr(0, sizeof(cmdstruct.type) - 1);
-			if (cmdstr.substr(0, sizeof(cmdstruct.type) - 1) == TWSTREAMHDR) {
-				struct AdbBackupStreamHeader twhdr;
-				memcpy(&twhdr, cmd, sizeof(cmd));
-				LOGINFO("ADB Partition count: %" PRIu64 "\n", twhdr.partition_count);
-				LOGINFO("ADB version: %" PRIu64 "\n", twhdr.version);
-				if (twhdr.version != ADB_BACKUP_VERSION) {
-					LOGERR("Incompatible adb backup version!\n");
-					breakloop = false;
-					break;
-				}
-				partition_count = twhdr.partition_count;
-			}
-			else if (cmdtype == MD5TRAILER) {
-				LOGINFO("Restoring MD5TRAILER\n");
-				memcpy(&adbmd5, cmd, sizeof(cmd));
-			}
-			else if (cmdtype == TWMD5) {
-				struct AdbBackupFileTrailer md5check;
-				LOGINFO("Restoring TWMD5\n");
-
-				memset(&md5check, 0, sizeof(md5check));
-				memcpy(&md5check, cmd, sizeof(cmd));
-				if (strcmp(md5check.md5, adbmd5.md5) != 0) {
-					LOGERR("md5 doesn't match!\n");
-					LOGERR("file md5: %s\n", adbmd5.md5);
-					LOGERR("check md5: %s\n", md5check.md5);
-					breakloop = true;
-					ret = 1;
-					break;
-				}
-				else {
-					LOGINFO("adbrestore md5 matches\n");
-					LOGINFO("adbmd5.md5: %s\n", adbmd5.md5);
-					LOGINFO("md5check.md5: %s\n", md5check.md5);
-				}
-			}
-			else if (cmdtype == TWENDADB) {
-				LOGINFO("received TWENDADB\n");
-				breakloop = true;
-				break;
-			}
-			else {
-				struct twfilehdr twimghdr;
-				memcpy(&twimghdr, cmd, sizeof(cmd));
-				std::string cmdstr(twimghdr.type);
-				Restore_Name = twimghdr.name;
-				part_settings.total_restore_size = twimghdr.size;
-				if (cmdtype == TWIMG) {
-					LOGINFO("ADB Type: %s\n", twimghdr.type);
-					LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str());
-					LOGINFO("ADB Restore_size: %" PRIu64 "\n", part_settings.total_restore_size);
-					string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed";
-					LOGINFO("ADB compression: %s\n", compression.c_str());
-					std::string Backup_FileName;
-					std::size_t pos = Restore_Name.find_last_of("/");
-					std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size());
-					pos = path.find_first_of(".");
-					path = path.substr(0, pos);
-					if (path.substr(0,1).compare("//")) {
-						path = path.substr(1, path.size());
-					}
-
-					pos = Restore_Name.find_last_of("/");
-					Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size());
-					part_settings.Part = PartitionManager.Find_Partition_By_Path(path);
-					part_settings.Backup_Folder = path;
-					part_settings.partition_count = partition_count;
-					part_settings.adbbackup = true;
-					part_settings.adb_compression = twimghdr.compressed;
-					part_settings.PM_Method = PM_RESTORE;
-					ProgressTracking progress(part_settings.total_restore_size);
-					part_settings.progress = &progress;
-					if (!PartitionManager.Restore_Partition(&part_settings)) {
-						LOGERR("ADB Restore failed.\n");
-						close(adb_control_twrp_fd);
-						close(adb_control_bu_fd);
-						return 1;
-					}
-				}
-				else if (cmdtype == TWFN) {
-					LOGINFO("ADB Type: %s\n", twimghdr.type);
-					LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str());
-					LOGINFO("ADB Restore_size: %" PRIi64 "\n", part_settings.total_restore_size);
-					string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed";
-					LOGINFO("ADB compression: %s\n", compression.c_str());
-					std::string Backup_FileName;
-					std::size_t pos = Restore_Name.find_last_of("/");
-					std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size());
-					pos = path.find_first_of(".");
-					path = path.substr(0, pos);
-					if (path.substr(0,1).compare("//")) {
-						path = path.substr(1, path.size());
-					}
-
-					pos = Restore_Name.find_last_of("/");
-					Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size());
-					pos = Restore_Name.find_last_of("/");
-					part_settings.Part = PartitionManager.Find_Partition_By_Path(path);
-
-					if (path.compare("/system") == 0) {
-						if (part_settings.Part->Is_Read_Only()) {
-							struct AdbBackupControlType twerror;
-							strncpy(twerror.start_of_header, TWRP, sizeof(twerror.start_of_header));
-							strncpy(twerror.type, TWERROR, sizeof(twerror.type));
-							memset(twerror.space, 0, sizeof(twerror.space));
-							twerror.crc = crc32(0L, Z_NULL, 0);
-							twerror.crc = crc32(twerror.crc, (const unsigned char*) &twerror, sizeof(twerror));
-							if (write(adb_control_bu_fd, &twerror, sizeof(twerror)) < 0) {
-								LOGERR("Cannot write to ADB_CONTROL_BU_FD: %s\n", strerror(errno));
-							}
-							gui_msg(Msg(msg::kError, "restore_read_only=Cannot restore {1} -- mounted read only.")(part_settings.Part->Backup_Display_Name));
-							close(adb_control_twrp_fd);
-							close(adb_control_bu_fd);
-							return 1;
-
-						}
-					}
-					part_settings.partition_count = partition_count;
-					part_settings.adbbackup = true;
-					part_settings.adb_compression = twimghdr.compressed;
-					part_settings.Part->Set_Backup_FileName(part_settings.Part->Get_Backup_Name() + "." + part_settings.Part->Current_File_System + ".win");
-					part_settings.total_restore_size += part_settings.Part->Get_Restore_Size(&part_settings);
-					part_settings.PM_Method = PM_RESTORE;
-					ProgressTracking progress(part_settings.total_restore_size);
-					part_settings.progress = &progress;
-					if (!PartitionManager.Restore_Partition(&part_settings)) {
-						LOGERR("ADB Restore failed.\n");
-						close(adb_control_twrp_fd);
-						close(adb_control_bu_fd);
-						return 1;
-					}
-				}
-			}
-		}
-	}
-	close(adb_control_twrp_fd);
-	close(adb_control_bu_fd);
-	gui_msg("restore_complete=Restore Complete");
-
-	if (!twadbbu::Write_TWENDADB())
-		ret = 1;
-	sleep(2); //give time for user to see messages on console
-	return ret;
-}
-
 int OpenRecoveryScript::remountrw(void)
 {
 	bool remount_system = PartitionManager.Is_Mounted_By_Path("/system");
diff --git a/openrecoveryscript.hpp b/openrecoveryscript.hpp
index f442746..0806223 100644
--- a/openrecoveryscript.hpp
+++ b/openrecoveryscript.hpp
@@ -1,5 +1,5 @@
 /*
-	Copyright 2012 bigbiff/Dees_Troy TeamWin
+	Copyright 2012 - 2017 TeamWin
 	This file is part of TWRP/TeamWin Recovery Project.
 
 	TWRP is free software: you can redistribute it and/or modify
@@ -40,8 +40,6 @@
 	static int Run_OpenRecoveryScript_Action();                                    // Actually runs the ORS scripts for the GUI action
 	static void Call_After_CLI_Command(VoidFunction fn) { call_after_cli_command = fn; }
 	static void Run_CLI_Command(const char* command);                              // Runs a command for orscmd (twrp binary)
-	static int Backup_ADB_Command(string Options);                                 // Runs adbbackup
-	static int Restore_ADB_Backup();                                               // Restore adb backup through ors
 	static int remountrw();                                                        // Remount system and vendor rw
 };
 
diff --git a/partition.cpp b/partition.cpp
index 44403d8..4157e97 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -2249,7 +2249,7 @@
 		gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(destfn.c_str())(strerror(errno)));
 		goto exit;
 	}
-	
+
 	LOGINFO("Reading '%s', writing '%s'\n", srcfn.c_str(), destfn.c_str());
 
 	if (part_settings->adbbackup) {
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 9b1c1c9..e896cee 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -1,5 +1,5 @@
 /*
-	Copyright 2014 to 2016 TeamWin
+	Copyright 2014 to 2017 TeamWin
 	This file is part of TWRP/TeamWin Recovery Project.
 
 	TWRP is free software: you can redistribute it and/or modify
@@ -667,10 +667,6 @@
 	part_settings.file_bytes = 0;
 	part_settings.PM_Method = PM_BACKUP;
 
-	DataManager::GetValue("tw_enable_adb_backup", gui_adb_backup);
-	if (gui_adb_backup == true)
-		adbbackup = true;
-
 	part_settings.adbbackup = adbbackup;
 	time(&total_start);
 
@@ -865,6 +861,8 @@
 	time_t Start, Stop;
 
 	if (part_settings->adbbackup) {
+		std::string partName = part_settings->Part->Backup_Name + "." + part_settings->Part->Current_File_System + ".win";
+		LOGINFO("setting backup name: %s\n", partName.c_str());
 		part_settings->Part->Set_Backup_FileName(part_settings->Part->Backup_Name + "." + part_settings->Part->Current_File_System + ".win");
 	}
 
@@ -876,7 +874,7 @@
 		TWFunc::SetPerformanceMode(false);
 		return false;
 	}
-	if (part_settings->Part->Has_SubPartition) {
+	if (part_settings->Part->Has_SubPartition && !part_settings->adbbackup) {
 		std::vector<TWPartition*>::iterator subpart;
 		TWPartition *parentPart = part_settings->Part;
 
@@ -884,6 +882,7 @@
 			part_settings->Part = *subpart;
 			if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == parentPart->Mount_Point) {
 				part_settings->Part = (*subpart);
+				part_settings->Part->Set_Backup_FileName(part_settings->Part->Backup_Name + "." + part_settings->Part->Current_File_System + ".win");
 				if (!(*subpart)->Restore(part_settings)) {
 					TWFunc::SetPerformanceMode(false);
 					return false;
@@ -1013,93 +1012,114 @@
 	// Start with the default values
 	string Restore_List;
 	bool get_date = true, check_encryption = true;
+	bool adbbackup = false;
 
 	DataManager::SetValue("tw_restore_encrypted", 0);
-
-	DIR* d;
-	d = opendir(Restore_Name.c_str());
-	if (d == NULL)
-	{
-		gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Restore_Name)(strerror(errno)));
-		return;
+	if (twadbbu::Check_ADB_Backup_File(Restore_Name)) {
+		vector<string> adb_files;
+		adb_files = twadbbu::Get_ADB_Backup_Files(Restore_Name);
+		for (unsigned int i = 0; i < adb_files.size(); ++i) {
+			string adb_restore_file = adb_files.at(i);
+			std::size_t pos = adb_restore_file.find_first_of(".");
+			std::string path = "/" + adb_restore_file.substr(0, pos);
+			Restore_List = path + ";";
+			TWPartition* Part = Find_Partition_By_Path(path);
+			Part->Backup_FileName = TWFunc::Get_Filename(adb_restore_file);
+			adbbackup = true;
+		}
+		DataManager::SetValue("tw_enable_adb_backup", 1);
 	}
-
-	struct dirent* de;
-	while ((de = readdir(d)) != NULL)
-	{
-		// Strip off three components
-		char str[256];
-		char* label;
-		char* fstype = NULL;
-		char* extn = NULL;
-		char* ptr;
-
-		strcpy(str, de->d_name);
-		if (strlen(str) <= 2)
-			continue;
-
-		if (get_date) {
-			char file_path[255];
-			struct stat st;
-
-			strcpy(file_path, Restore_Name.c_str());
-			strcat(file_path, "/");
-			strcat(file_path, str);
-			stat(file_path, &st);
-			string backup_date = ctime((const time_t*)(&st.st_mtime));
-			DataManager::SetValue(TW_RESTORE_FILE_DATE, backup_date);
-			get_date = false;
-		}
-
-		label = str;
-		ptr = label;
-		while (*ptr && *ptr != '.')	 ptr++;
-		if (*ptr == '.')
+	else {
+		DIR* d;
+		d = opendir(Restore_Name.c_str());
+		if (d == NULL)
 		{
-			*ptr = 0x00;
-			ptr++;
-			fstype = ptr;
+			gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Restore_Name)(strerror(errno)));
+			return;
 		}
-		while (*ptr && *ptr != '.')	 ptr++;
-		if (*ptr == '.')
+
+		struct dirent* de;
+		while ((de = readdir(d)) != NULL)
 		{
-			*ptr = 0x00;
-			ptr++;
-			extn = ptr;
-		}
+			// Strip off three components
+			char str[256];
+			char* label;
+			char* fstype = NULL;
+			char* extn = NULL;
+			char* ptr;
 
-		if (fstype == NULL || extn == NULL || strcmp(fstype, "log") == 0) continue;
-		int extnlength = strlen(extn);
-		if (extnlength != 3 && extnlength != 6) continue;
-		if (extnlength >= 3 && strncmp(extn, "win", 3) != 0) continue;
-		//if (extnlength == 6 && strncmp(extn, "win000", 6) != 0) continue;
+			strcpy(str, de->d_name);
+			if (strlen(str) <= 2)
+				continue;
 
-		if (check_encryption) {
-			string filename = Restore_Name + "/";
-			filename += de->d_name;
-			if (TWFunc::Get_File_Type(filename) == 2) {
-				LOGINFO("'%s' is encrypted\n", filename.c_str());
-				DataManager::SetValue("tw_restore_encrypted", 1);
+			if (get_date) {
+				char file_path[255];
+				struct stat st;
+
+				strcpy(file_path, Restore_Name.c_str());
+				strcat(file_path, "/");
+				strcat(file_path, str);
+				stat(file_path, &st);
+				string backup_date = ctime((const time_t*)(&st.st_mtime));
+				DataManager::SetValue(TW_RESTORE_FILE_DATE, backup_date);
+				get_date = false;
 			}
-		}
-		if (extnlength == 6 && strncmp(extn, "win000", 6) != 0) continue;
 
-		TWPartition* Part = Find_Partition_By_Path(label);
-		if (Part == NULL)
-		{
-			gui_msg(Msg(msg::kError, "unable_locate_part_backup_name=Unable to locate partition by backup name: '{1}'")(label));
-			continue;
-		}
+			label = str;
+			ptr = label;
+			while (*ptr && *ptr != '.')	 ptr++;
+			if (*ptr == '.')
+			{
+				*ptr = 0x00;
+				ptr++;
+				fstype = ptr;
+			}
+			while (*ptr && *ptr != '.')	 ptr++;
+			if (*ptr == '.')
+			{
+				*ptr = 0x00;
+				ptr++;
+				extn = ptr;
+			}
 
-		Part->Backup_FileName = de->d_name;
-		if (strlen(extn) > 3) {
-			Part->Backup_FileName.resize(Part->Backup_FileName.size() - strlen(extn) + 3);
-		}
+			if (fstype == NULL || extn == NULL || strcmp(fstype, "log") == 0) continue;
+			int extnlength = strlen(extn);
+			if (extnlength != 3 && extnlength != 6) continue;
+			if (extnlength >= 3 && strncmp(extn, "win", 3) != 0) continue;
+			//if (extnlength == 6 && strncmp(extn, "win000", 6) != 0) continue;
 
-		if (!Part->Is_SubPartition)
-			Restore_List += Part->Backup_Path + ";";
+			if (check_encryption) {
+				string filename = Restore_Name + "/";
+				filename += de->d_name;
+				if (TWFunc::Get_File_Type(filename) == 2) {
+					LOGINFO("'%s' is encrypted\n", filename.c_str());
+					DataManager::SetValue("tw_restore_encrypted", 1);
+				}
+			}
+			if (extnlength == 6 && strncmp(extn, "win000", 6) != 0) continue;
+
+			TWPartition* Part = Find_Partition_By_Path(label);
+			if (Part == NULL)
+			{
+				gui_msg(Msg(msg::kError, "unable_locate_part_backup_name=Unable to locate partition by backup name: '{1}'")(label));
+				continue;
+			}
+
+			Part->Backup_FileName = de->d_name;
+			if (strlen(extn) > 3) {
+				Part->Backup_FileName.resize(Part->Backup_FileName.size() - strlen(extn) + 3);
+			}
+
+			if (!Part->Is_SubPartition)
+				Restore_List += Part->Backup_Path + ";";
+		}
+		closedir(d);
 	}
-	closedir(d);
+
+	if (adbbackup) {
+		Restore_List = "ADB_Backup;";
+		adbbackup = false;
+	}
 
 	// Set the final value
 	DataManager::SetValue("tw_restore_list", Restore_List);
@@ -1953,12 +1973,19 @@
 			size_t start_pos = 0, end_pos = Restore_List.find(";", start_pos);
 			while (end_pos != string::npos && start_pos < Restore_List.size()) {
 				restore_path = Restore_List.substr(start_pos, end_pos - start_pos);
+				struct PartitionList part;
+				if (restore_path.compare("ADB_Backup") == 0) {
+					part.Display_Name = "ADB Backup";
+					part.Mount_Point = "ADB Backup";
+					part.selected = 1;
+					Partition_List->push_back(part);
+					break;
+				}
 				if ((restore_part = Find_Partition_By_Path(restore_path)) != NULL) {
 					if ((restore_part->Backup_Name == "recovery" && !restore_part->Can_Be_Backed_Up) || restore_part->Is_SubPartition) {
 						// Don't allow restore of recovery (causes problems on some devices)
 						// Don't add subpartitions to the list of items
 					} else {
-						struct PartitionList part;
 						part.Display_Name = restore_part->Backup_Display_Name;
 						part.Mount_Point = restore_part->Backup_Path;
 						part.selected = 1;
diff --git a/partitions.hpp b/partitions.hpp
index 61bf7e2..30a025a 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -1,5 +1,5 @@
 /*
-	Copyright 2014 to 2016 TeamWin
+	Copyright 2014 to 2017 TeamWin
 	This file is part of TWRP/TeamWin Recovery Project.
 
 	TWRP is free software: you can redistribute it and/or modify
diff --git a/twinstall.cpp b/twinstall.cpp
index 0aaab45..ab71529 100644
--- a/twinstall.cpp
+++ b/twinstall.cpp
@@ -1,5 +1,5 @@
 /*
-	Copyright 2012 to 2016 bigbiff/Dees_Troy TeamWin
+	Copyright 2012 to 2017 bigbiff/Dees_Troy TeamWin
 	This file is part of TWRP/TeamWin Recovery Project.
 
 	TWRP is free software: you can redistribute it and/or modify
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index eabcc53..d7c9c2c 100644
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -35,6 +35,7 @@
 #include <iostream>
 #include <fstream>
 #include <sstream>
+#include <cctype>
 #include <algorithm>
 #include "twrp-functions.hpp"
 #include "twcommon.h"
@@ -857,6 +858,10 @@
 		DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date());
 		return;
 	}
+	else {
+		//remove periods from build display so it doesn't confuse the extension code
+		propvalue.erase(remove(propvalue.begin(), propvalue.end(), '.'), propvalue.end());
+	}
 	string Backup_Name = Get_Current_Date();
 	Backup_Name += "_" + propvalue;
 	if (Backup_Name.size() > MAX_BACKUP_NAME_LEN)
@@ -1122,4 +1127,23 @@
 	gui_msg(Msg("copy_kernel_log=Copied kernel log to {1}")(dmesgDst));
 	tw_set_default_metadata(dmesgDst.c_str());
 }
+
+bool TWFunc::isNumber(string strtocheck) {
+	int num = 0;
+	std::istringstream iss(strtocheck);
+
+	if (!(iss >> num).fail())
+		return true;
+	else
+		return false;
+}
+
+int TWFunc::stream_adb_backup(string &Restore_Name) {
+	string cmd = "/sbin/bu --twrp stream " + Restore_Name;
+	LOGINFO("stream_adb_backup: %s\n", cmd.c_str());
+	int ret = TWFunc::Exec_Cmd(cmd);
+	if (ret != 0)
+		return -1;
+	return ret;
+}
 #endif // ndef BUILD_TWRPTAR_MAIN
diff --git a/twrp-functions.hpp b/twrp-functions.hpp
index 1f6b9b1..66781bb 100644
--- a/twrp-functions.hpp
+++ b/twrp-functions.hpp
@@ -98,6 +98,8 @@
 	static void Disable_Stock_Recovery_Replace(); // Disable stock ROMs from replacing TWRP with stock recovery
 	static unsigned long long IOCTL_Get_Block_Size(const char* block_device);
 	static void copy_kernel_log(string curr_storage); // Copy Kernel Log to Current Storage (PSTORE/KMSG)
+	static bool isNumber(string strtocheck); // return true if number, false if not a number
+	static int stream_adb_backup(string &Restore_Name); // Tell ADB Backup to Stream to TWRP from GUI selection
 
 private:
 	static void Copy_Log(string Source, string Destination);
diff --git a/twrp.cpp b/twrp.cpp
index b68e321..8c2a24f 100644
--- a/twrp.cpp
+++ b/twrp.cpp
@@ -45,6 +45,7 @@
 #include "partitions.hpp"
 #include "openrecoveryscript.hpp"
 #include "variables.h"
+#include "twrpAdbBuFifo.hpp"
 #ifdef TW_USE_NEW_MINADBD
 #include "minadbd/minadbd.h"
 #else
@@ -330,6 +331,7 @@
 	// Check if system has never been changed
 	TWPartition* sys = PartitionManager.Find_Partition_By_Path("/system");
 	TWPartition* ven = PartitionManager.Find_Partition_By_Path("/vendor");
+
 	if (sys) {
 		if ((DataManager::GetIntValue("tw_mount_system_ro") == 0 && sys->Check_Lifetime_Writes() == 0) || DataManager::GetIntValue("tw_mount_system_ro") == 2) {
 			if (DataManager::GetIntValue("tw_never_show_system_ro_page") == 0) {
@@ -351,6 +353,9 @@
 		}
 	}
 #endif
+	twrpAdbBuFifo *adb_bu_fifo = new twrpAdbBuFifo();
+	adb_bu_fifo->threadAdbBuFifo();
+
 	// Launch the main GUI
 	gui_start();
 
@@ -379,6 +384,7 @@
 
 	// Reboot
 	TWFunc::Update_Intent_File(Send_Intent);
+	delete adb_bu_fifo;
 	TWFunc::Update_Log_File();
 	gui_msg(Msg("rebooting=Rebooting..."));
 	string Reboot_Arg;
diff --git a/twrpAdbBuFifo.cpp b/twrpAdbBuFifo.cpp
new file mode 100644
index 0000000..db34c5a
--- /dev/null
+++ b/twrpAdbBuFifo.cpp
@@ -0,0 +1,336 @@
+/*
+        Copyright 2013 to 2017 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/>.
+*/
+
+#define __STDC_FORMAT_MACROS 1
+#include <string>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <zlib.h>
+#include <inttypes.h>
+#include "twrpAdbBuFifo.hpp"
+#include "twcommon.h"
+#include "data.hpp"
+#include "variables.h"
+#include "partitions.hpp"
+#include "twrp-functions.hpp"
+#include "gui/gui.hpp"
+#include "gui/objects.hpp"
+#include "gui/pages.hpp"
+#include "adbbu/twadbstream.h"
+#include "adbbu/libtwadbbu.hpp"
+
+twrpAdbBuFifo::twrpAdbBuFifo(void) {
+	unlink(TW_ADB_FIFO);
+}
+
+bool twrpAdbBuFifo::Check_Adb_Fifo_For_Events(void) {
+	char cmd[512];
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	if (read(adb_fifo_fd, &cmd, sizeof(cmd)) > 0) {
+		LOGINFO("adb backup cmd: %s\n", cmd);
+		std::string cmdcheck(cmd);
+		cmdcheck = cmdcheck.substr(0, strlen(ADB_BACKUP_OP));
+		std::string Options(cmd);
+		Options = Options.substr(strlen(ADB_BACKUP_OP) + 1, strlen(cmd));
+		if (cmdcheck == ADB_BACKUP_OP)
+			return Backup_ADB_Command(Options);
+		else {
+			return Restore_ADB_Backup();
+		}
+	}
+
+	return true;
+}
+
+bool twrpAdbBuFifo::start(void) {
+	LOGINFO("Starting Adb Backup FIFO\n");
+	unlink(TW_ADB_FIFO);
+	if (mkfifo(TW_ADB_FIFO, 06660) != 0) {
+		LOGINFO("Unable to mkfifo %s\n", TW_ADB_FIFO);
+		return false;
+	}
+	adb_fifo_fd = open(TW_ADB_FIFO, O_RDONLY | O_NONBLOCK);
+	if (adb_fifo_fd < 0) {
+		LOGERR("Unable to open TW_ADB_FIFO for reading.\n");
+		close(adb_fifo_fd);
+		return false;
+	}
+	while (true) {
+		Check_Adb_Fifo_For_Events();
+		usleep(8000);
+	}
+	//Shouldn't get here but cleanup anwyay
+	close(adb_fifo_fd);
+	return true;
+}
+
+pthread_t twrpAdbBuFifo::threadAdbBuFifo(void) {
+	pthread_t thread;
+	ThreadPtr adbfifo = &twrpAdbBuFifo::start;
+	PThreadPtr p = *(PThreadPtr*)&adbfifo;
+	pthread_create(&thread, NULL, p, this);
+	return thread;
+}
+
+bool twrpAdbBuFifo::Backup_ADB_Command(std::string Options) {
+	std::vector<std::string> args;
+	std::string Backup_List;
+	bool adbbackup = true, ret = false;
+	std::string rmopt = "--";
+
+	std::replace(Options.begin(), Options.end(), ':', ' ');
+	args = TWFunc::Split_String(Options, " ");
+
+	DataManager::SetValue(TW_USE_COMPRESSION_VAR, 0);
+	DataManager::SetValue(TW_SKIP_DIGEST_GENERATE_VAR, 0);
+
+	if (args[1].compare("--twrp") != 0) {
+		gui_err("twrp_adbbu_option=--twrp option is required to enable twrp adb backup");
+		sleep(2);
+		return false;
+	}
+
+	for (unsigned i = 2; i < args.size(); i++) {
+		int compress;
+
+		std::string::size_type size = args[i].find(rmopt);
+		if (size != std::string::npos)
+			args[i].erase(size, rmopt.length());
+
+		if (args[i].compare("compress") == 0) {
+			gui_msg("compression_on=Compression is on");
+			DataManager::SetValue(TW_USE_COMPRESSION_VAR, 1);
+			continue;
+		}
+		DataManager::GetValue(TW_USE_COMPRESSION_VAR, compress);
+		gui_print("%s\n", args[i].c_str());
+		std::string path;
+		path = "/" + args[i];
+		TWPartition* part = PartitionManager.Find_Partition_By_Path(path);
+		if (part) {
+			Backup_List += path;
+			Backup_List += ";";
+		}
+		else {
+			gui_msg(Msg(msg::kError, "partition_not_found=path: {1} not found in partition list")(path));
+			return false;
+		}
+	}
+
+	if (Backup_List.empty()) {
+		DataManager::GetValue("tw_backup_list", Backup_List);
+		if (Backup_List.empty()) {
+			gui_err("no_partition_selected=No partitions selected for backup.");
+			return false;
+		}
+	}
+	else
+		DataManager::SetValue("tw_backup_list", Backup_List);
+
+	DataManager::SetValue("tw_action", "clear");
+	DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands"));
+	DataManager::SetValue("tw_action_text2", "");
+	gui_changePage("action_page");
+
+	ret = PartitionManager.Run_Backup(adbbackup);
+	DataManager::SetValue(TW_BACKUP_NAME, gui_lookup("auto_generate", "(Auto Generate)"));
+	if (!ret) {
+		gui_err("backup_fail=Backup failed");
+		return false;
+	}
+	gui_msg("backup_complete=Backup Complete");
+	DataManager::SetValue("ui_progress", 100);
+	sleep(2); //give time for user to see messages on console
+	gui_changePage("main");
+	return true;
+}
+
+bool twrpAdbBuFifo::Restore_ADB_Backup(void) {
+	int partition_count = 0;
+	std::string Restore_Name;
+	std::size_t pos = 0;
+	struct AdbBackupFileTrailer adbmd5;
+	struct PartitionSettings part_settings;
+	int adb_control_twrp_fd, adb_write_fd, systemro;
+	int adb_control_bu_fd, ret = 0;
+	char cmd[512];
+
+	part_settings.total_restore_size = 0;
+
+	PartitionManager.Mount_All_Storage();
+	DataManager::SetValue(TW_SKIP_DIGEST_CHECK_VAR, 0);
+	LOGINFO("opening TW_ADB_BU_CONTROL\n");
+	adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK);
+	LOGINFO("opening TW_ADB_TWRP_CONTROL\n");
+	adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_RDONLY | O_NONBLOCK);
+	memset(&adbmd5, 0, sizeof(adbmd5));
+
+	DataManager::SetValue("tw_action", "clear");
+	DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands"));
+	DataManager::SetValue("tw_action_text2", "");
+	gui_changePage("action_page");
+
+	while (1) {
+		memset(&cmd, 0, sizeof(cmd));
+		if (read(adb_control_twrp_fd, cmd, sizeof(cmd)) > 0) {
+			struct AdbBackupControlType cmdstruct;
+
+			memset(&cmdstruct, 0, sizeof(cmdstruct));
+			memcpy(&cmdstruct, cmd, sizeof(cmdstruct));
+			std::string cmdstr(cmdstruct.type);
+			std::string cmdtype = cmdstr.substr(0, sizeof(cmdstruct.type) - 1);
+			if (cmdtype == TWSTREAMHDR) {
+				struct AdbBackupStreamHeader twhdr;
+				memcpy(&twhdr, cmd, sizeof(cmd));
+				LOGINFO("ADB Partition count: %" PRIu64 "\n", twhdr.partition_count);
+				LOGINFO("ADB version: %" PRIu64 "\n", twhdr.version);
+				if (twhdr.version != ADB_BACKUP_VERSION) {
+					LOGERR("Incompatible adb backup version!\n");
+					break;
+				}
+				partition_count = twhdr.partition_count;
+			}
+			else if (cmdtype == MD5TRAILER) {
+				LOGINFO("Restoring MD5TRAILER\n");
+				memcpy(&adbmd5, cmd, sizeof(cmd));
+			}
+			else if (cmdtype == TWMD5) {
+				struct AdbBackupFileTrailer md5check;
+				LOGINFO("Restoring TWMD5\n");
+
+				memset(&md5check, 0, sizeof(md5check));
+				memcpy(&md5check, cmd, sizeof(cmd));
+				if (strcmp(md5check.md5, adbmd5.md5) != 0) {
+					LOGERR("md5 doesn't match!\n");
+					LOGERR("file md5: %s\n", adbmd5.md5);
+					LOGERR("check md5: %s\n", md5check.md5);
+					ret = false;
+					break;
+				}
+				else {
+					LOGINFO("adbrestore md5 matches\n");
+					LOGINFO("adbmd5.md5: %s\n", adbmd5.md5);
+					LOGINFO("md5check.md5: %s\n", md5check.md5);
+				}
+			}
+			else if (cmdtype == TWENDADB) {
+				LOGINFO("received TWENDADB\n");
+				break;
+			}
+			else {
+				struct twfilehdr twimghdr;
+				memcpy(&twimghdr, cmd, sizeof(cmd));
+				std::string cmdstr(twimghdr.type);
+				Restore_Name = twimghdr.name;
+				part_settings.total_restore_size = twimghdr.size;
+				if (cmdtype == TWIMG) {
+					LOGINFO("ADB Type: %s\n", twimghdr.type);
+					LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str());
+					LOGINFO("ADB Restore_size: %" PRIu64 "\n", part_settings.total_restore_size);
+					string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed";
+					LOGINFO("ADB compression: %s\n", compression.c_str());
+					std::string Backup_FileName;
+					std::size_t pos = Restore_Name.find_last_of("/");
+					std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size());
+					pos = path.find_first_of(".");
+					path = path.substr(0, pos);
+					if (path.substr(0,1).compare("//")) {
+						path = path.substr(1, path.size());
+					}
+
+					pos = Restore_Name.find_last_of("/");
+					Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size());
+					part_settings.Part = PartitionManager.Find_Partition_By_Path(path);
+					part_settings.Backup_Folder = path;
+					PartitionManager.Set_Restore_Files(path);
+					part_settings.partition_count = partition_count;
+					part_settings.adbbackup = true;
+					part_settings.adb_compression = twimghdr.compressed;
+					part_settings.PM_Method = PM_RESTORE;
+					ProgressTracking progress(part_settings.total_restore_size);
+					part_settings.progress = &progress;
+					if (!PartitionManager.Restore_Partition(&part_settings)) {
+						LOGERR("ADB Restore failed.\n");
+						return false;
+					}
+				}
+				else if (cmdtype == TWFN) {
+					LOGINFO("ADB Type: %s\n", twimghdr.type);
+					LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str());
+					LOGINFO("ADB Restore_size: %" PRIi64 "\n", part_settings.total_restore_size);
+					string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed";
+					LOGINFO("ADB compression: %s\n", compression.c_str());
+					std::string Backup_FileName;
+					std::size_t pos = Restore_Name.find_last_of("/");
+					std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size());
+					pos = path.find_first_of(".");
+					path = path.substr(0, pos);
+					if (path.substr(0,1).compare("//")) {
+						path = path.substr(1, path.size());
+					}
+
+					pos = Restore_Name.find_last_of("/");
+					Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size());
+					pos = Restore_Name.find_last_of("/");
+					part_settings.Part = PartitionManager.Find_Partition_By_Path(path);
+					part_settings.Part->Set_Backup_FileName(Backup_FileName);
+					PartitionManager.Set_Restore_Files(path);
+
+					if (path.compare("/system") == 0) {
+						if (part_settings.Part->Is_Read_Only()) {
+							struct AdbBackupControlType twerror;
+							strncpy(twerror.start_of_header, TWRP, sizeof(twerror.start_of_header));
+							strncpy(twerror.type, TWERROR, sizeof(twerror.type));
+							memset(twerror.space, 0, sizeof(twerror.space));
+							twerror.crc = crc32(0L, Z_NULL, 0);
+							twerror.crc = crc32(twerror.crc, (const unsigned char*) &twerror, sizeof(twerror));
+							if (write(adb_control_bu_fd, &twerror, sizeof(twerror)) < 0) {
+								LOGERR("Cannot write to ADB_CONTROL_BU_FD: %s\n", strerror(errno));
+							}
+							gui_msg(Msg(msg::kError, "restore_read_only=Cannot restore {1} -- mounted read only.")(part_settings.Part->Backup_Display_Name));
+							return false;
+
+						}
+					}
+					part_settings.partition_count = partition_count;
+					part_settings.adbbackup = true;
+					part_settings.adb_compression = twimghdr.compressed;
+					part_settings.total_restore_size += part_settings.Part->Get_Restore_Size(&part_settings);
+					part_settings.PM_Method = PM_RESTORE;
+					ProgressTracking progress(part_settings.total_restore_size);
+					part_settings.progress = &progress;
+					if (!PartitionManager.Restore_Partition(&part_settings)) {
+						LOGERR("ADB Restore failed.\n");
+						return false;
+					}
+				}
+			}
+		}
+	}
+	gui_msg("restore_complete=Restore Complete");
+
+	if (!twadbbu::Write_TWENDADB())
+		ret = false;
+	sleep(2); //give time for user to see messages on console
+	DataManager::SetValue("ui_progress", 100);
+	gui_changePage("main");
+	return ret;
+}
diff --git a/twrpAdbBuFifo.hpp b/twrpAdbBuFifo.hpp
new file mode 100644
index 0000000..e709b96
--- /dev/null
+++ b/twrpAdbBuFifo.hpp
@@ -0,0 +1,40 @@
+/*
+        Copyright 2013 to 2017 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/>.
+*/
+
+#ifndef TWRPADBFIFO_HPP
+#define TWRPADBFIFO_HPP
+
+#include <string>
+#include <pthread.h>
+
+#define TW_ADB_FIFO "/tmp/twadbfifo"
+
+class twrpAdbBuFifo {
+	public:
+		twrpAdbBuFifo(void);
+		pthread_t threadAdbBuFifo(void);
+	private:
+		bool start(void);
+		bool Backup_ADB_Command(std::string Options);
+		bool Check_Adb_Fifo_For_Events(void);
+		bool Restore_ADB_Backup(void);
+		typedef bool (twrpAdbBuFifo::*ThreadPtr)(void);
+		typedef void* (*PThreadPtr)(void *);
+		int adb_fifo_fd;
+};
+#endif