Support v2 fstab format

Auto detect and support both the v1 and v2 fstab formats
Support putting TWRP style flags in a separate /etc/twrp.flags file

twrp.flags format is the same as twrp.fstab (v1 with TWRP flags)

Support using a wildcard in a block device and find all partitions:
/usb-otg vfat /dev/block/sda*

Support using sysfs entries (voldmanaged) and read uevents and scan for
wildcard partitions from uevent data. (twvold?)

May not be complete for some of the newer flags found in fstabs in newer
build trees and there is a slim chance of a crash if the user removes a
removable device while TWRP is performing actions. May need to add some
kind of mutex to prevent the 2 threads from causing this crash. We need
to start somewhere though and this change is pretty innocuous when not
using a v2 fstab.

Change-Id: I617d97c7db332cbe671a9d2b8ad98b3d9c4f03cc
diff --git a/partitions.hpp b/partitions.hpp
index 30a025a..d780fe5 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -19,8 +19,10 @@
 #ifndef __TWRP_Partition_Manager
 #define __TWRP_Partition_Manager
 
+#include <map>
 #include <vector>
 #include <string>
+#include <sys/poll.h>
 #include "exclude.hpp"
 #include "tw_atomic.hpp"
 #include "progresstracking.hpp"
@@ -35,14 +37,32 @@
 	unsigned int selected;
 };
 
-enum PartitionManager_Op {                                                        // PartitionManager Restore Mode for Raw_Read_Write()
+struct Uevent_Block_Data {
+	std::string action;
+	std::string subsystem;
+	std::string block_device;
+	std::string type;
+	std::string sysfs_path;
+	int major;
+	int minor;
+};
+
+struct Flags_Map {
+	std::string Primary_Block_Device;
+	std::string Alternate_Block_Device;
+	std::string File_System;
+	std::string Flags;
+	char* fstab_line;
+};
+
+enum PartitionManager_Op {                                                    // PartitionManager Restore Mode for Raw_Read_Write()
 	PM_BACKUP = 0,
 	PM_RESTORE = 1,
 };
 
 class TWPartition;
 
-struct PartitionSettings {                                                        // Settings for backup session
+struct PartitionSettings {                                                    // Settings for backup session
 	TWPartition* Part;                                                        // Partition to pass to the partition backup loop
 	std::string Backup_Folder;                                                // Path to restore folder
 	bool adbbackup;                                                           // tell the system we are backing up over adb
@@ -124,14 +144,16 @@
 	void Setup_Data_Media();                                                  // Sets up a partition as a /data/media emulated storage partition
 
 private:
-	bool Process_Fstab_Line(const char *fstab_line, bool Display_Error);      // Processes a fstab line
+	bool Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map<string, Flags_Map> *twrp_flags); // 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
+	bool Find_Wildcard_Block_Devices(const string& Device);                   // Searches for and finds wildcard block devices
 	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
-	void Process_TW_Flags(char *flags, bool Display_Error);                   // Process custom twrp fstab flags
+	void Process_TW_Flags(char *flags, bool Display_Error, int fstab_ver);    // Process custom twrp fstab flags
 	void Process_FS_Flags(const char *str);                                   // Process standard fstab fs flags
+	void Save_FS_Flags(const string& local_File_System, int local_Mount_Flags, const string& local_Mount_Options); // Saves fs flags to a vector in case there are multiple lines in a v2 fstab with different mount flags for different file systems
 	bool Is_File_System(string File_System);                                  // Checks to see if the file system given is considered a file system
 	bool Is_Image(string File_System);                                        // Checks to see if the file system given is considered an image
 	void Setup_File_System(bool Display_Error);                               // Sets defaults for a file system partition
@@ -184,6 +206,8 @@
 	string Symlink_Mount_Point;                                               // /sdcard could be the symlink mount point for /data/media
 	string Mount_Point;                                                       // Mount point for this partition (e.g. /system or /data)
 	string Backup_Path;                                                       // Path for backup
+	bool Wildcard_Block_Device;                                               // If the block device contains an asterisk, we set this flag
+	string Sysfs_Entry;                                                       // For v2 fstab, if the "block device" starts with /devices then it is a sysfs entry that is handled by uevents
 	string Primary_Block_Device;                                              // Block device (e.g. /dev/block/mmcblk1p1)
 	string Alternate_Block_Device;                                            // Alternate block device (e.g. /dev/block/mmcblk1)
 	string Decrypted_Block_Device;                                            // Decrypted block device available after decryption
@@ -223,6 +247,14 @@
 	TWExclude backup_exclusions;                                              // Exclusions for file based backups
 	TWExclude wipe_exclusions;                                                // Exclusions for file based wipes (data/media devices only)
 
+	struct partition_fs_flags_struct {                                        // This struct is used to store mount flags and options for different file systems for the same partition
+		string File_System;
+		int Mount_Flags;
+		string Mount_Options;
+	};
+
+	std::vector<partition_fs_flags_struct> fs_flags;                          // This vector stores mount flags and options for different file systems for the same partition
+
 friend class TWPartitionManager;
 friend class DataManager;
 friend class GUIPartitionList;
@@ -240,12 +272,14 @@
 	int Process_Fstab(string Fstab_Filename, bool Display_Error);             // Parses the fstab and populates the partitions
 	int Write_Fstab();                                                        // Creates /etc/fstab file that's used by the command line for mount commands
 	void Output_Partition_Logging();                                          // Outputs partition information to the log
+	void Output_Partition(TWPartition* Part);                                 // Outputs partition details to the log
 	int Mount_By_Path(string Path, bool Display_Error);                       // Mounts partition based on path (e.g. /system)
 	int UnMount_By_Path(string Path, bool Display_Error);                     // Unmounts partition based on path
 	int Is_Mounted_By_Path(string Path);                                      // Checks if partition is mounted based on path
 	int Mount_Current_Storage(bool Display_Error);                            // Mounts the current storage location
 	int Mount_Settings_Storage(bool Display_Error);                           // Mounts the settings file storage location (usually internal)
-	TWPartition* Find_Partition_By_Path(string Path);                         // Returns a pointer to a partition based on path
+	TWPartition* Find_Partition_By_Path(const string& Path);                  // Returns a pointer to a partition based on path
+	TWPartition* Find_Partition_By_Block_Device(const string& Block_Device);  // Returns a pointer to a partition based on block device
 	int Check_Backup_Name(bool Display_Error);                                // Checks the current backup name to ensure that it is valid
 	int Run_Backup(bool adbbackup);                                           // Initiates a backup in the current storage
 	int Run_Restore(const string& Restore_Name);                              // Restores a backup
@@ -289,7 +323,7 @@
 	void Translate_Partition(const char* path, const char* resource_name, const char* default_value, const char* storage_resource_name, const char* storage_default_value);
 	void Translate_Partition(const char* path, const char* resource_name, const char* default_value, const char* storage_resource_name, const char* storage_default_value, const char* backup_name, const char* backup_default);
 	void Translate_Partition_Display_Names();                                 // Updates display names based on translations
-	void Decrypt_Adopted();                                                   // Attempt to identy and decrypt any adopted storage partitions
+	bool Decrypt_Adopted();                                                   // Attempt to identy and decrypt any adopted storage partitions
 	void Remove_Partition_By_Path(string Path);                               // Removes / erases a partition entry from the partition list
 
 	bool Flash_Image(string& path, string& filename);                         // Flashes an image to a selected partition from the partition list
@@ -298,17 +332,26 @@
 	void Set_Active_Slot(const string& Slot);                                 // Sets the active slot to A or B
 	string Get_Active_Slot_Suffix();                                          // Returns active slot _a or _b
 	string Get_Active_Slot_Display();                                         // Returns active slot A or B for display purposes
+	struct pollfd uevent_pfd;                                                 // Used for uevent code
+	void Remove_Uevent_Devices(const string& sysfs_path);                     // Removes subpartitions from the Partitions vector for a matched uevent device
+	void Handle_Uevent(const Uevent_Block_Data& uevent_data);                 // Handle uevent data
+	void setup_uevent();                                                      // Opens the uevent netlink socket
+	Uevent_Block_Data get_event_block_values(char *buf, int len);             // Scans the buffer from uevent data and loads the appropriate data into a Uevent_Block_Data struct for processing
+	void read_uevent();                                                       // Reads uevent data into a buffer
+	void close_uevent();                                                      // Closes the uevent netlink socket
+	void Add_Partition(TWPartition* Part);                                    // Adds a new partition to the Partitions vector
 
 private:
 	void Setup_Settings_Storage_Partition(TWPartition* Part);                 // Sets up settings storage
 	void Setup_Android_Secure_Location(TWPartition* Part);                    // Sets up .android_secure if needed
 	bool Backup_Partition(struct PartitionSettings *part_settings);           // Backup the partitions based on type
-	void Output_Partition(TWPartition* Part);                                 // Outputs partition details to the log
 	TWPartition* Find_Partition_By_MTP_Storage_ID(unsigned int Storage_ID);   // Returns a pointer to a partition based on MTP Storage ID
 	bool Add_Remove_MTP_Storage(TWPartition* Part, int message_type);         // Adds or removes an MTP Storage partition
 	TWPartition* Find_Next_Storage(string Path, bool Exclude_Data_Media);
 	int Open_Lun_File(string Partition_Path, string Lun_File);
 	void Post_Decrypt(const string& Block_Device);                            // Completes various post-decrypt tasks
+	void Coldboot_Scan(std::vector<string> *sysfs_entries, const string& Path, int depth); // Scans subfolders to find matches to the paths stored in sysfs_entries so we can trigger the uevent system to "re-add" devices
+	void Coldboot();                                                          // Starts the scan of the /sys/block folder
 	pid_t mtppid;
 	bool mtp_was_enabled;
 	int mtp_write_fd;