AB/Non AB Devices: updates for moving cache

This patchset updates all the places we touch cache on AB devices
and non AB devices so that we can write to the appropriate
location. AB devices removed the cache partition and moved it to
/data/cache.

Change-Id: I485ec205a604f1f07ceb7700ae9c4e720fd55c3e
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
old mode 100644
new mode 100755
index 00a57a7..37dd0df
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -37,6 +37,7 @@
 #include <sstream>
 #include <cctype>
 #include <algorithm>
+#include <selinux/label.h>
 #include "twrp-functions.hpp"
 #include "twcommon.h"
 #include "gui/gui.hpp"
@@ -58,6 +59,8 @@
 	#include "libcrecovery/common.h"
 }
 
+struct selabel_handle *selinux_handle;
+
 /* Execute a command */
 int TWFunc::Exec_Cmd(const string& cmd, string &result) {
 	FILE* exec;
@@ -520,28 +523,29 @@
 }
 
 void TWFunc::Update_Log_File(void) {
-	// Copy logs to cache so the system can find out what happened.
-	if (PartitionManager.Mount_By_Path("/cache", false)) {
-		if (!TWFunc::Path_Exists("/cache/recovery/.")) {
-			LOGINFO("Recreating /cache/recovery folder.\n");
-			if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
-				LOGINFO("Unable to create /cache/recovery folder.\n");
+	std::string recoveryDir = get_cache_dir() + "recovery/";
+
+	if (get_cache_dir() == NON_AB_CACHE_DIR) {
+		if (!PartitionManager.Mount_By_Path(NON_AB_CACHE_DIR, false)) {
+			LOGINFO("Failed to mount %s for TWFunc::Update_Log_File\n", NON_AB_CACHE_DIR);
 		}
-		Copy_Log(TMP_LOG_FILE, "/cache/recovery/log");
-		copy_file("/cache/recovery/log", "/cache/recovery/last_log", 600);
-		chown("/cache/recovery/log", 1000, 1000);
-		chmod("/cache/recovery/log", 0600);
-		chmod("/cache/recovery/last_log", 0640);
-	} else if (PartitionManager.Mount_By_Path("/data", false) && TWFunc::Path_Exists("/data/cache/recovery/.")) {
-		Copy_Log(TMP_LOG_FILE, "/data/cache/recovery/log");
-		copy_file("/data/cache/recovery/log", "/data/cache/recovery/last_log", 600);
-		chown("/data/cache/recovery/log", 1000, 1000);
-		chmod("/data/cache/recovery/log", 0600);
-		chmod("/data/cache/recovery/last_log", 0640);
-	} else {
-		LOGINFO("Failed to mount /cache or find /data/cache for TWFunc::Update_Log_File\n");
 	}
 
+	if (!TWFunc::Path_Exists(recoveryDir)) {
+		LOGINFO("Recreating %s folder.\n", recoveryDir.c_str());
+		if (mkdir(recoveryDir.c_str(),  S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0) {
+			LOGINFO("Unable to create %s folder.\n", recoveryDir.c_str());
+		}
+	}
+
+	std::string logCopy = recoveryDir + "log";
+	std::string lastLogCopy = recoveryDir + "last_log";
+	copy_file(logCopy, lastLogCopy, 600);
+	Copy_Log(TMP_LOG_FILE, logCopy);
+	chown(logCopy.c_str(), 1000, 1000);
+	chmod(logCopy.c_str(), 0600);
+	chmod(lastLogCopy.c_str(), 0640);
+
 	// Reset bootloader message
 	TWPartition* Part = PartitionManager.Find_Partition_By_Path("/misc");
 	if (Part != NULL) {
@@ -555,12 +559,13 @@
 		}
 	}
 
-	if (PartitionManager.Mount_By_Path("/cache", false)) {
-		if (unlink("/cache/recovery/command") && errno != ENOENT) {
-			LOGINFO("Can't unlink %s\n", "/cache/recovery/command");
+	if (get_cache_dir() == NON_AB_CACHE_DIR) {
+		if (PartitionManager.Mount_By_Path("/cache", false)) {
+			if (unlink("/cache/recovery/command") && errno != ENOENT) {
+				LOGINFO("Can't unlink %s\n", "/cache/recovery/command");
+			}
 		}
 	}
-
 	sync();
 }
 
@@ -1154,4 +1159,58 @@
 		return -1;
 	return ret;
 }
+
+std::string TWFunc::get_cache_dir() {
+	if (PartitionManager.Find_Partition_By_Path(NON_AB_CACHE_DIR) == NULL) {
+		return AB_CACHE_DIR;
+	}
+	else {
+		return NON_AB_CACHE_DIR;
+	}
+}
+
+void TWFunc::check_selinux_support() {
+	if (TWFunc::Path_Exists("/prebuilt_file_contexts")) {
+		if (TWFunc::Path_Exists("/file_contexts")) {
+			printf("Renaming regular /file_contexts -> /file_contexts.bak\n");
+			rename("/file_contexts", "/file_contexts.bak");
+		}
+		printf("Moving /prebuilt_file_contexts -> /file_contexts\n");
+		rename("/prebuilt_file_contexts", "/file_contexts");
+	}
+	struct selinux_opt selinux_options[] = {
+		{ SELABEL_OPT_PATH, "/file_contexts" }
+	};
+	selinux_handle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
+	if (!selinux_handle)
+		printf("No file contexts for SELinux\n");
+	else
+		printf("SELinux contexts loaded from /file_contexts\n");
+	{ // Check to ensure SELinux can be supported by the kernel
+		char *contexts = NULL;
+		std::string cacheDir = TWFunc::get_cache_dir();
+		std::string se_context_check = cacheDir + "recovery/";
+		int ret = 0;
+
+		if (cacheDir == NON_AB_CACHE_DIR) {
+			PartitionManager.Mount_By_Path(NON_AB_CACHE_DIR, false);
+		}
+		if (TWFunc::Path_Exists(se_context_check)) {
+			ret = lgetfilecon(se_context_check.c_str(), &contexts);
+			if (ret > 0) {
+				lsetfilecon(se_context_check.c_str(), "test");
+				lgetfilecon(se_context_check.c_str(), &contexts);
+			} else {
+				LOGINFO("Could not check %s SELinux contexts, using /sbin/teamwin instead which may be inaccurate.\n", se_context_check.c_str());
+				lgetfilecon("/sbin/teamwin", &contexts);
+			}
+		}
+		if (ret < 0) {
+			gui_warn("no_kernel_selinux=Kernel does not have support for reading SELinux contexts.");
+		} else {
+			free(contexts);
+			gui_msg("full_selinux=Full SELinux support is present.");
+		}
+	}
+}
 #endif // ndef BUILD_TWRPTAR_MAIN