allow flashing sparse images

if the image has the right magic bytes to be a sparse image,
use simg2img to flash the image

create a rule to make a fully dynamic simg2img which results in a
much smaller increase in gzip ramdisk size (2KB vs 40KB)

Change-Id: I1b0f6bc127da46103888b1154a9bddd8ac02c01d
diff --git a/partition.cpp b/partition.cpp
index d038c38..c511298 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -68,6 +68,7 @@
 #include <sys/xattr.h>
 #include <linux/xattr.h>
 #endif
+#include <sparse_format.h>
 
 using namespace std;
 
@@ -407,12 +408,12 @@
 		} else if (Mount_Point == "/system_image") {
 			Display_Name = "System Image";
 			Backup_Display_Name = Display_Name;
-			Can_Flash_Img = false;
+			Can_Flash_Img = true;
 			Can_Be_Backed_Up = true;
 		} else if (Mount_Point == "/vendor_image") {
 			Display_Name = "Vendor Image";
 			Backup_Display_Name = Display_Name;
-			Can_Flash_Img = false;
+			Can_Flash_Img = true;
 			Can_Be_Backed_Up = true;
 		}
 	}
@@ -2375,7 +2376,24 @@
 	string Command;
 
 	gui_msg(Msg("flashing=Flashing {1}...")(Display_Name));
-	Command = "dd bs=8388608 if='" + Filename + "' of=" + Actual_Block_Device;
+
+	uint32_t magic = 0;
+	int fd = open(Filename.c_str(), O_RDONLY);
+	if (fd < 0) {
+		gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno)));
+		return false;
+	}
+	if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) {
+		gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno)));
+		close(fd);
+		return false;
+	}
+	close(fd);
+	if (magic == SPARSE_HEADER_MAGIC) {
+		Command = "simg2img '" + Filename + "' " + Actual_Block_Device;
+	} else {
+		Command = "dd bs=8388608 if='" + Filename + "' of=" + Actual_Block_Device;
+	}
 	LOGINFO("Flash command: '%s'\n", Command.c_str());
 	TWFunc::Exec_Cmd(Command);
 	return true;