add support for fsflags= option in twrp.fstab file

example userdata line (as needed by MotoX):
/data         f2fs      /dev/block/platform/msm_sdcc.1/by-name/userdata       flags=fsflags="inline_xattr"

Code for parsing flags/options originally based on AOSP fs_mgr sources.

Change-Id: I5fb2b5d5cdd08137e6bf71f0085a3f8aebd889a8
diff --git a/partition.cpp b/partition.cpp
index c1e214e..061a3e1 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -57,6 +57,31 @@
 
 extern struct selabel_handle *selinux_handle;
 
+struct flag_list {
+	const char *name;
+	unsigned flag;
+};
+
+static struct flag_list mount_flags[] = {
+	{ "noatime",    MS_NOATIME },
+	{ "noexec",     MS_NOEXEC },
+	{ "nosuid",     MS_NOSUID },
+	{ "nodev",      MS_NODEV },
+	{ "nodiratime", MS_NODIRATIME },
+	{ "ro",         MS_RDONLY },
+	{ "rw",         0 },
+	{ "remount",    MS_REMOUNT },
+	{ "bind",       MS_BIND },
+	{ "rec",        MS_REC },
+	{ "unbindable", MS_UNBINDABLE },
+	{ "private",    MS_PRIVATE },
+	{ "slave",      MS_SLAVE },
+	{ "shared",     MS_SHARED },
+	{ "sync",       MS_SYNCHRONOUS },
+	{ "defaults",   0 },
+	{ 0,            0 },
+};
+
 TWPartition::TWPartition(void) {
 	Can_Be_Mounted = false;
 	Can_Be_Wiped = false;
@@ -101,6 +126,8 @@
 	Storage_Path = "";
 	Current_File_System = "";
 	Fstab_File_System = "";
+	Mount_Flags = 0;
+	Mount_Options = "";
 	Format_Block_Size = 0;
 	Ignore_Blkid = false;
 	Retain_Layout_Version = false;
@@ -373,6 +400,38 @@
 	return true;
 }
 
+bool TWPartition::Process_FS_Flags(string& Options, int Flags) {
+	int i;
+	char *p;
+	char *savep;
+	char fs_options[250];
+
+	strlcpy(fs_options, Options.c_str(), sizeof(fs_options));
+	Options = "";
+
+	p = strtok_r(fs_options, ",", &savep);
+	while (p) {
+		/* Look for the flag "p" in the flag list "fl"
+		* If not found, the loop exits with fl[i].name being null.
+		*/
+		for (i = 0; mount_flags[i].name; i++) {
+			if (strncmp(p, mount_flags[i].name, strlen(mount_flags[i].name)) == 0) {
+				Flags |= mount_flags[i].flag;
+				break;
+			}
+		}
+
+		if (!mount_flags[i].name) {
+			if (Options.size() > 0)
+				Options += ",";
+			Options += p;
+		}
+		p = strtok_r(NULL, ",", &savep);
+	}
+
+	return true;
+}
+
 bool TWPartition::Process_Flags(string Flags, bool Display_Error) {
 	char flags[MAX_FSTAB_LINE_LENGTH];
 	int flags_len, index = 0, ptr_len;
@@ -474,6 +533,15 @@
 			} else {
 				Use_Userdata_Encryption = false;
 			}
+		} else if (ptr_len > 8 && strncmp(ptr, "fsflags=", 8) == 0) {
+			ptr += 8;
+			if (*ptr == '\"') ptr++;
+
+			Mount_Options = ptr;
+			if (Mount_Options.substr(Mount_Options.size() - 1, 1) == "\"") {
+				Mount_Options.resize(Mount_Options.size() - 1);
+			}
+			Process_FS_Flags(Mount_Options, Mount_Flags);
 		} else {
 			if (Display_Error)
 				LOGERR("Unhandled flag: '%s'\n", ptr);
@@ -872,7 +940,7 @@
 			}
 			return true;
 		}
-	} else if (!exfat_mounted && mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
+	} else if (!exfat_mounted && mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), Mount_Flags, Mount_Options.c_str()) != 0) {
 #ifdef TW_NO_EXFAT_FUSE
 		if (Current_File_System == "exfat") {
 			LOGINFO("Mounting exfat failed, trying vfat...\n");
@@ -881,7 +949,7 @@
 					LOGERR("Unable to mount '%s'\n", Mount_Point.c_str());
 				else
 					LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
-				LOGINFO("Actual block device: '%s', current file system: '%s'\n", Actual_Block_Device.c_str(), Current_File_System.c_str());
+				LOGINFO("Actual block device: '%s', current file system: '%s', flags: 0x%8x, options: '%s'\n", Actual_Block_Device.c_str(), Current_File_System.c_str(), Mount_Flags, Mount_Options.c_str());
 				return false;
 			}
 		} else {