recovery: Update recovery from CM.

Change-Id: Ibda5ba8bbfc93ef6ff565128b63adc2991218a70
diff --git a/roots.c b/roots.c
index 4ef5c37..a3c4677 100644
--- a/roots.c
+++ b/roots.c
@@ -28,8 +28,30 @@
 #include "common.h"
 #include "make_ext4fs.h"
 
-static int num_volumes = 0;
-static Volume* device_volumes = NULL;
+int num_volumes;
+Volume* device_volumes;
+
+int get_num_volumes() {
+    return num_volumes;
+}
+
+Volume* get_device_volumes() {
+    return device_volumes;
+}
+
+static int is_null(const char* sz) {
+    if (sz == NULL)
+        return 1;
+    if (strcmp("NULL", sz) == 0)
+        return 1;
+    return 0;
+}
+
+static char* dupe_string(const char* sz) {
+    if (is_null(sz))
+        return NULL;
+    return strdup(sz);
+}
 
 void load_volume_table() {
     int alloc = 2;
@@ -40,6 +62,8 @@
     device_volumes[0].fs_type = "ramdisk";
     device_volumes[0].device = NULL;
     device_volumes[0].device2 = NULL;
+    device_volumes[0].fs_options = NULL;
+    device_volumes[0].fs_options2 = NULL;
     num_volumes = 1;
 
     FILE* fstab = fopen("/etc/recovery.fstab", "r");
@@ -63,6 +87,8 @@
         // mounting the first one fails.
         char* device2 = strtok(NULL, " \t\n");
         char* fs_type2 = strtok(NULL, " \t\n");
+        char* fs_options = strtok(NULL, " \t\n");
+        char* fs_options2 = strtok(NULL, " \t\n");
 
         if (mount_point && fs_type && device) {
             while (num_volumes >= alloc) {
@@ -70,11 +96,20 @@
                 device_volumes = realloc(device_volumes, alloc*sizeof(Volume));
             }
             device_volumes[num_volumes].mount_point = strdup(mount_point);
-            device_volumes[num_volumes].fs_type = fs_type2 != NULL ? strdup(fs_type2) : strdup(fs_type);
+            device_volumes[num_volumes].fs_type = !is_null(fs_type2) ? strdup(fs_type2) : strdup(fs_type);
             device_volumes[num_volumes].device = strdup(device);
             device_volumes[num_volumes].device2 =
-                (device2 != NULL && strcmp(device2, "NULL") != 0) ? strdup(device2) : NULL;
-            device_volumes[num_volumes].fs_type2 = fs_type2 != NULL ? strdup(fs_type) : NULL;
+                !is_null(device2) ? strdup(device2) : NULL;
+            device_volumes[num_volumes].fs_type2 = !is_null(fs_type2) ? strdup(fs_type) : NULL;
+
+            if (!is_null(fs_type2)) {
+                device_volumes[num_volumes].fs_options2 = dupe_string(fs_options);
+                device_volumes[num_volumes].fs_options = dupe_string(fs_options2);
+            }
+            else {
+                device_volumes[num_volumes].fs_options2 = NULL;
+                device_volumes[num_volumes].fs_options = dupe_string(fs_options);
+            }
             ++num_volumes;
         } else {
             LOGE("skipping malformed recovery.fstab line: %s\n", original);
@@ -107,11 +142,20 @@
     return NULL;
 }
 
-int try_mount(const char* device, const char* mount_point, const char* fs_type) {
+int try_mount(const char* device, const char* mount_point, const char* fs_type, const char* fs_options) {
     if (device == NULL || mount_point == NULL || fs_type == NULL)
         return -1;
-    int ret = mount(device, mount_point, fs_type,
+    int ret = 0;
+    if (fs_options == NULL) {
+        ret = mount(device, mount_point, fs_type,
                        MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
+    }
+    else {
+        char mount_cmd[PATH_MAX];
+        sprintf(mount_cmd, "mount -t %s -o%s %s %s", fs_type, fs_options, device, mount_point);
+        LOGE("%s\n", mount_cmd);
+        ret = __system(mount_cmd);
+    }
     if (ret == 0)
         return 0;
     LOGW("failed to mount %s (%s)\n", device, strerror(errno));
@@ -158,15 +202,15 @@
         return mtd_mount_partition(partition, v->mount_point, v->fs_type, 0);
     } else if (strcmp(v->fs_type, "ext4") == 0 ||
                strcmp(v->fs_type, "ext3") == 0 ||
+               strcmp(v->fs_type, "rfs") == 0 ||
                strcmp(v->fs_type, "vfat") == 0) {
-        // try fs type 2 first
-        if ((result = try_mount(v->device, v->mount_point, v->fs_type)) == 0)
+        if ((result = try_mount(v->device, v->mount_point, v->fs_type, v->fs_options)) == 0)
             return 0;
-        if ((result = try_mount(v->device2, v->mount_point, v->fs_type)) == 0)
+        if ((result = try_mount(v->device2, v->mount_point, v->fs_type, v->fs_options)) == 0)
             return 0;
-        if ((result = try_mount(v->device, v->mount_point, v->fs_type2)) == 0)
+        if ((result = try_mount(v->device, v->mount_point, v->fs_type2, v->fs_options2)) == 0)
             return 0;
-        if ((result = try_mount(v->device2, v->mount_point, v->fs_type2)) == 0)
+        if ((result = try_mount(v->device2, v->mount_point, v->fs_type2, v->fs_options2)) == 0)
             return 0;
         return result;
     } else {