Parse postinstall parameters from the payload metadata.

Payload v2 includes a description of the post-install command it should
run, while in payload v1 we use the default values. This patch mounts
the partition on the new top-level directory called /postinstall that
should already be created.

Bug: 27177071
TEST=FEATURES=test emerge-link update_engine

Change-Id: Iaedf3b01e5e1ad57c68bd316b4b6e79cbab35bb6
diff --git a/common/constants.cc b/common/constants.cc
index 6b1d416..fc6df37 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -29,6 +29,8 @@
 
 const char kStatefulPartition[] = "/mnt/stateful_partition";
 
+const char kPostinstallDefaultScript[] = "postinst";
+
 // Constants defining keys for the persisted state of update engine.
 const char kPrefsAttemptInProgress[] = "attempt-in-progress";
 const char kPrefsBackoffExpiryTime[] = "backoff-expiry-time";
diff --git a/common/constants.h b/common/constants.h
index f9a43c6..25d587b 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -32,6 +32,9 @@
 // The location where we store the AU preferences (state etc).
 extern const char kPrefsSubDirectory[];
 
+// Path to the post install command, relative to the partition.
+extern const char kPostinstallDefaultScript[];
+
 // Path to the stateful partition on the root filesystem.
 extern const char kStatefulPartition[];
 
diff --git a/common/test_utils.cc b/common/test_utils.cc
index c09096b..a574863 100644
--- a/common/test_utils.cc
+++ b/common/test_utils.cc
@@ -260,7 +260,7 @@
   string loop_dev;
   loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
 
-  EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
+  EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, ""));
   unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
 }
 
diff --git a/common/utils.cc b/common/utils.cc
index 91dcfc8..b4956e7 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -613,9 +613,14 @@
 
 bool MountFilesystem(const string& device,
                      const string& mountpoint,
-                     unsigned long mountflags) {  // NOLINT(runtime/int)
-  // TODO(sosa): Remove "ext3" once crbug.com/208022 is resolved.
-  const vector<const char*> fstypes{"ext2", "ext3", "ext4", "squashfs"};
+                     unsigned long mountflags,  // NOLINT(runtime/int)
+                     const string& type) {
+  vector<const char*> fstypes;
+  if (type.empty()) {
+    fstypes = {"ext2", "ext3", "ext4", "squashfs"};
+  } else {
+    fstypes = {type.c_str()};
+  }
   for (const char* fstype : fstypes) {
     int rc = mount(device.c_str(), mountpoint.c_str(), fstype, mountflags,
                    nullptr);
@@ -625,7 +630,9 @@
     PLOG(WARNING) << "Unable to mount destination device " << device
                   << " on " << mountpoint << " as " << fstype;
   }
-  LOG(ERROR) << "Unable to mount " << device << " with any supported type";
+  if (!type.empty()) {
+    LOG(ERROR) << "Unable to mount " << device << " with any supported type";
+  }
   return false;
 }
 
diff --git a/common/utils.h b/common/utils.h
index 5bf1422..8da0726 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -171,10 +171,13 @@
 std::string MakePartitionNameForMount(const std::string& part_name);
 
 // Synchronously mount or unmount a filesystem. Return true on success.
-// When mounting, it will attempt to mount the the device as "ext3", "ext2" and
-// "squashfs", with the passed |flags| options.
-bool MountFilesystem(const std::string& device, const std::string& mountpoint,
-                     unsigned long flags);  // NOLINT(runtime/int)
+// When mounting, it will attempt to mount the device as the passed filesystem
+// type |type|, with the passed |flags| options. If |type| is empty, "ext2",
+// "ext3", "ext4" and "squashfs" will be tried.
+bool MountFilesystem(const std::string& device,
+                     const std::string& mountpoint,
+                     unsigned long flags,  // NOLINT(runtime/int)
+                     const std::string& type);
 bool UnmountFilesystem(const std::string& mountpoint);
 
 // Returns the block count and the block byte size of the file system on