Allow restoring to read-only file system

This allows the restoration of firmware or modems on read-only
mounted file systems. If the user is able to make a backup of
these partitions, it would only make sense they be allowed to
restore that backup. The current handling is dangerous in that
it happily wipes, but refuses to restore. :)

Note that it would be preferable to use the backup=emmc flag
instead in most cases, added by change:
https://gerrit.omnirom.org/#/c/17183

Change-Id: I32d47c8928dee61595c15a9db16d3c5b9a6d7183
diff --git a/partition.cpp b/partition.cpp
index 979272a..fe2843c 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -984,6 +984,14 @@
 	return ret;
 }
 
+bool TWPartition::Is_File_System_Writable(void) {
+	if (!Is_File_System(Current_File_System) || !Is_Mounted())
+		return false;
+
+	string test_path = Mount_Point + "/.";
+	return (access(test_path.c_str(), W_OK) == 0);
+}
+
 bool TWPartition::Mount(bool Display_Error) {
 	int exfat_mounted = 0;
 	unsigned long flags = Mount_Flags;
@@ -1152,6 +1160,31 @@
 	}
 }
 
+bool TWPartition::ReMount(bool Display_Error) {
+	if (UnMount(Display_Error))
+		return Mount(Display_Error);
+	return false;
+}
+
+bool TWPartition::ReMount_RW(bool Display_Error) {
+	// No need to remount if already mounted rw
+	if (Is_File_System_Writable())
+		return true;
+
+	bool ro = Mount_Read_Only;
+	int flags = Mount_Flags;
+
+	Mount_Read_Only = false;
+	Mount_Flags &= ~MS_RDONLY;
+
+	bool ret = ReMount(Display_Error);
+
+	Mount_Read_Only = ro;
+	Mount_Flags = flags;
+
+	return ret;
+}
+
 bool TWPartition::Wipe(string New_File_System) {
 	bool wiped = false, update_crypt = false, recreate_media = true;
 	int check;
@@ -2141,7 +2174,8 @@
 	TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}"));
 	gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name));
 
-	if (!Mount(true))
+	// Remount as read/write as needed so we can restore the backup
+	if (!ReMount_RW(true))
 		return false;
 
 	Full_FileName = restore_folder + "/" + Backup_FileName;
@@ -2178,6 +2212,10 @@
 		}
 	}
 #endif
+	if (Mount_Read_Only || Mount_Flags & MS_RDONLY)
+		// Remount as read only when restoration is complete
+		ReMount(true);
+
 	return ret;
 }
 
diff --git a/partitions.hpp b/partitions.hpp
index 90f772c..1d43e04 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -51,8 +51,11 @@
 
 public:
 	bool Is_Mounted();                                                        // Checks mount to see if the partition is currently mounted
+	bool Is_File_System_Writable();                                           // Checks if the root directory of the file system can be written to
 	bool Mount(bool Display_Error);                                           // Mounts the partition if it is not mounted
 	bool UnMount(bool Display_Error);                                         // Unmounts the partition if it is mounted
+	bool ReMount(bool Display_Error);                                         // Remounts the partition
+	bool ReMount_RW(bool Display_Error);                                      // Remounts the partition with read/write access
 	bool Wipe(string New_File_System);                                        // Wipes the partition
 	bool Wipe();                                                              // Wipes the partition
 	bool Wipe_AndSec();                                                       // Wipes android secure