Wait to mount until after fstab processed

The necessity to process fstab twice stems from mounting partitions
while still processing. Instead, wait to finish setup of /data, /cache
and storage parameters until after fstab has been processed (once).

Change-Id: Id77e1edbab5eb68a7cd4a1f34953d819a043d47a
diff --git a/partition.cpp b/partition.cpp
index 5bbde2c..1261a2a 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -286,7 +286,7 @@
 					LOGERR("Invalid block device '%s' in fstab line '%s'", ptr, fstab_line);
 				else
 					LOGINFO("Invalid block device '%s' in fstab line '%s'", ptr, fstab_line);
-				return 0;
+				return false;
 			} else {
 				Primary_Block_Device = ptr;
 				Find_Real_Block_Device(Primary_Block_Device, Display_Error);
@@ -305,7 +305,6 @@
 				// Custom flags, save for later so that new values aren't overwritten by defaults
 				ptr += 6;
 				strlcpy(twflags, ptr, sizeof(twflags));
-				Process_TW_Flags(twflags, Display_Error);
 			} else if (strlen(ptr) == 4 && (strncmp(ptr, "NULL", 4) == 0 || strncmp(ptr, "null", 4) == 0 || strncmp(ptr, "null", 4) == 0)) {
 				// Do nothing
 			} else {
@@ -322,7 +321,7 @@
 			LOGERR("Unknown File System: '%s'\n", Fstab_File_System.c_str());
 		else
 			LOGINFO("Unknown File System: '%s'\n", Fstab_File_System.c_str());
-		return 0;
+		return false;
 	} else if (Is_File_System(Fstab_File_System)) {
 		Find_Actual_Block_Device();
 		Setup_File_System(Display_Error);
@@ -334,7 +333,6 @@
 			Can_Be_Backed_Up = true;
 			Mount_Read_Only = true;
 		} else if (Mount_Point == "/data") {
-			UnMount(false); // added in case /data is mounted as tmpfs for qcom hardware decrypt
 			Display_Name = "Data";
 			Backup_Display_Name = Display_Name;
 			Storage_Name = Display_Name;
@@ -343,49 +341,6 @@
 			Can_Be_Backed_Up = true;
 			Can_Encrypt_Backup = true;
 			Use_Userdata_Encryption = true;
-			if (datamedia)
-				Setup_Data_Media();
-#ifdef TW_INCLUDE_CRYPTO
-			Can_Be_Encrypted = true;
-			char crypto_blkdev[255];
-			property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
-			if (strcmp(crypto_blkdev, "error") != 0) {
-				DataManager::SetValue(TW_IS_DECRYPTED, 1);
-				Is_Encrypted = true;
-				Is_Decrypted = true;
-				Decrypted_Block_Device = crypto_blkdev;
-				LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
-			} else if (!Mount(false)) {
-				if (Is_Present) {
-					set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str());
-					if (cryptfs_check_footer() == 0) {
-						Is_Encrypted = true;
-						Is_Decrypted = false;
-						Can_Be_Mounted = false;
-						Current_File_System = "emmc";
-						Setup_Image(Display_Error);
-						DataManager::SetValue(TW_IS_ENCRYPTED, 1);
-						DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
-						DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
-						DataManager::SetValue("tw_crypto_display", "");
-					} else {
-						gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
-					}
-				} else {
-					LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
-				}
-			} else {
-				// Filesystem is not encrypted and the mount
-				// succeeded, so get it back to the original
-				// unmounted state
-				UnMount(false);
-			}
-			if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted)))
-				Recreate_Media_Folder();
-#else
-			if (datamedia)
-				Recreate_Media_Folder();
-#endif
 		} else if (Mount_Point == "/cache") {
 			Display_Name = "Cache";
 			Backup_Display_Name = Display_Name;
@@ -393,11 +348,6 @@
 			Wipe_Available_in_GUI = true;
 			Wipe_During_Factory_Reset = true;
 			Can_Be_Backed_Up = true;
-			if (Mount(false) && !TWFunc::Path_Exists("/cache/recovery/.")) {
-				LOGINFO("Recreating /cache/recovery folder.\n");
-				if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
-					return -1;
-			}
 		} else if (Mount_Point == "/datadata") {
 			Wipe_During_Factory_Reset = true;
 			Display_Name = "DataData";
@@ -512,6 +462,82 @@
 	return true;
 }
 
+void TWPartition::Partition_Post_Processing(bool Display_Error) {
+	if (Mount_Point == "/data")
+		Setup_Data_Partition(Display_Error);
+	else if (Mount_Point == "/cache")
+		Setup_Cache_Partition(Display_Error);
+}
+
+void TWPartition::Setup_Data_Partition(bool Display_Error) {
+	if (Mount_Point != "/data")
+		return;
+
+	// Ensure /data is not mounted as tmpfs for qcom hardware decrypt
+	UnMount(false);
+
+#ifdef TW_INCLUDE_CRYPTO
+	if (datamedia)
+		Setup_Data_Media();
+	Can_Be_Encrypted = true;
+	char crypto_blkdev[255];
+	property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
+	if (strcmp(crypto_blkdev, "error") != 0) {
+		DataManager::SetValue(TW_IS_DECRYPTED, 1);
+		Is_Encrypted = true;
+		Is_Decrypted = true;
+		Decrypted_Block_Device = crypto_blkdev;
+		LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
+	} else if (!Mount(false)) {
+		if (Is_Present) {
+			set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str());
+			if (cryptfs_check_footer() == 0) {
+				Is_Encrypted = true;
+				Is_Decrypted = false;
+				Can_Be_Mounted = false;
+				Current_File_System = "emmc";
+				Setup_Image(Display_Error);
+				DataManager::SetValue(TW_IS_ENCRYPTED, 1);
+				DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
+				DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
+				DataManager::SetValue("tw_crypto_display", "");
+			} else {
+				gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
+			}
+		} else {
+			LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
+		}
+	} else {
+		// Filesystem is not encrypted and the mount succeeded, so return to
+		// the original unmounted state
+		UnMount(false);
+	}
+	if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))) {
+		Setup_Data_Media();
+		Recreate_Media_Folder();
+	}
+#else
+	if (datamedia) {
+		Setup_Data_Media();
+		Recreate_Media_Folder();
+	}
+#endif
+}
+
+void TWPartition::Setup_Cache_Partition(bool Display_Error __unused) {
+	if (Mount_Point != "/cache")
+		return;
+
+	if (!Mount(true))
+		return;
+
+	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)
+			LOGERR("Could not create /cache/recovery\n");
+	}
+}
+
 void TWPartition::Process_FS_Flags(const char *str) {
 	char *options = strdup(str);
 	char *ptr, *savep;
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index cc36b2e..320944c 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -92,29 +92,35 @@
 			fstab_line[strlen(fstab_line)] = '\n';
 
 		TWPartition* partition = new TWPartition();
-		if (partition->Process_Fstab_Line(fstab_line, Display_Error)) {
-			if (partition->Is_Storage) {
-				++storageid;
-				partition->MTP_Storage_ID = storageid;
-			}
-			if (!settings_partition && partition->Is_Settings_Storage && partition->Is_Present) {
-				settings_partition = partition;
-			} else {
-				partition->Is_Settings_Storage = false;
-			}
-			if (!andsec_partition && partition->Has_Android_Secure && partition->Is_Present) {
-				andsec_partition = partition;
-			} else {
-				partition->Has_Android_Secure = false;
-			}
+		if (partition->Process_Fstab_Line(fstab_line, Display_Error))
 			Partitions.push_back(partition);
-		} else {
+		else
 			delete partition;
-		}
 
 		memset(fstab_line, 0, sizeof(fstab_line));
 	}
 	fclose(fstabFile);
+
+	std::vector<TWPartition*>::iterator iter;
+	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
+		(*iter)->Partition_Post_Processing(Display_Error);
+
+		if ((*iter)->Is_Storage) {
+			++storageid;
+			(*iter)->MTP_Storage_ID = storageid;
+		}
+
+		if (!settings_partition && (*iter)->Is_Settings_Storage && (*iter)->Is_Present)
+			settings_partition = (*iter);
+		else
+			(*iter)->Is_Settings_Storage = false;
+
+		if (!andsec_partition && (*iter)->Has_Android_Secure && (*iter)->Is_Present)
+			andsec_partition = (*iter);
+		else
+			(*iter)->Has_Android_Secure = false;
+	}
+
 	if (!datamedia && !settings_partition && Find_Partition_By_Path("/sdcard") == NULL && Find_Partition_By_Path("/internal_sd") == NULL && Find_Partition_By_Path("/internal_sdcard") == NULL && Find_Partition_By_Path("/emmc") == NULL) {
 		// Attempt to automatically identify /data/media emulated storage devices
 		TWPartition* Dat = Find_Partition_By_Path("/data");
@@ -129,7 +135,6 @@
 		}
 	}
 	if (!settings_partition) {
-		std::vector<TWPartition*>::iterator iter;
 		for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
 			if ((*iter)->Is_Storage) {
 				settings_partition = (*iter);
diff --git a/partitions.hpp b/partitions.hpp
index ab34ec2..1ba0691 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -80,6 +80,7 @@
 	int Check_Lifetime_Writes();
 	int Decrypt_Adopted();
 	void Revert_Adopted();
+	void Partition_Post_Processing(bool Display_Error);                       // Apply partition specific settings after fstab processed
 
 public:
 	string Current_File_System;                                               // Current file system
@@ -96,6 +97,8 @@
 
 private:
 	bool Process_Fstab_Line(const char *fstab_line, bool Display_Error);      // Processes a fstab line
+	void Setup_Data_Partition(bool Display_Error);                            // Setup data partition after fstab processed
+	void Setup_Cache_Partition(bool Display_Error);                           // Setup cache partition after fstab processed
 	void Find_Actual_Block_Device();                                          // Determines the correct block device and stores it in Actual_Block_Device
 
 	void Apply_TW_Flag(const unsigned flag, const char* str, const bool val); // Apply custom twrp fstab flags