store partition length in recovery.fstab

Don't hardcode magical partition behavior in roots.c.

Change-Id: I587fc2c066575b51c11efd2e45a50f5b864df484
diff --git a/common.h b/common.h
index d99daaf..e6e8f85 100644
--- a/common.h
+++ b/common.h
@@ -99,6 +99,12 @@
     const char* device2;      // alternative device to try if fs_type
                               // == "ext4" or "vfat" and mounting
                               // 'device' fails
+
+    long long length;         // (ext4 partition only) when
+                              // formatting, size to use for the
+                              // partition.  0 or negative number
+                              // means to format all but the last
+                              // (that much).
 } Volume;
 
 #endif  // RECOVERY_COMMON_H
diff --git a/roots.c b/roots.c
index 5731d74..cb7e067 100644
--- a/roots.c
+++ b/roots.c
@@ -31,6 +31,21 @@
 static int num_volumes = 0;
 static Volume* device_volumes = NULL;
 
+static int parse_options(char* options, Volume* volume) {
+    char* option;
+    while (option = strtok(options, ",")) {
+        options = NULL;
+
+        if (strncmp(option, "length=", 7) == 0) {
+            volume->length = strtoll(option+7, NULL, 10);
+        } else {
+            LOGE("bad option \"%s\"\n", option);
+            return -1;
+        }
+    }
+    return 0;
+}
+
 void load_volume_table() {
     int alloc = 2;
     device_volumes = malloc(alloc * sizeof(Volume));
@@ -40,6 +55,7 @@
     device_volumes[0].fs_type = "ramdisk";
     device_volumes[0].device = NULL;
     device_volumes[0].device2 = NULL;
+    device_volumes[0].length = 0;
     num_volumes = 1;
 
     FILE* fstab = fopen("/etc/recovery.fstab", "r");
@@ -61,7 +77,16 @@
         char* device = strtok(NULL, " \t\n");
         // lines may optionally have a second device, to use if
         // mounting the first one fails.
+        char* options = NULL;
         char* device2 = strtok(NULL, " \t\n");
+        if (device2) {
+            if (device2[0] == '/') {
+                options = strtok(NULL, " \t\n");
+            } else {
+                options = device2;
+                device2 = NULL;
+            }
+        }
 
         if (mount_point && fs_type && device) {
             while (num_volumes >= alloc) {
@@ -73,7 +98,13 @@
             device_volumes[num_volumes].device = strdup(device);
             device_volumes[num_volumes].device2 =
                 device2 ? strdup(device2) : NULL;
-            ++num_volumes;
+
+            device_volumes[num_volumes].length = 0;
+            if (parse_options(options, device_volumes + num_volumes) != 0) {
+                LOGE("skipping malformed recovery.fstab line: %s\n", original);
+            } else {
+                ++num_volumes;
+            }
         } else {
             LOGE("skipping malformed recovery.fstab line: %s\n", original);
         }
@@ -86,8 +117,8 @@
     printf("=========================\n");
     for (i = 0; i < num_volumes; ++i) {
         Volume* v = &device_volumes[i];
-        printf("  %d %s %s %s %s\n", i, v->mount_point, v->fs_type,
-               v->device, v->device2);
+        printf("  %d %s %s %s %s %lld\n", i, v->mount_point, v->fs_type,
+               v->device, v->device2, v->length);
     }
     printf("\n");
 }
@@ -238,12 +269,7 @@
     }
 
     if (strcmp(v->fs_type, "ext4") == 0) {
-        s64 len = 0;
-
-        if (strcmp(volume, "/data") == 0) {
-            len = -16384;  /* Reserve 16 Kbytes for the crypto footer */
-        }
-        int result = make_ext4fs(v->device, len);
+        int result = make_ext4fs(v->device, v->length);
         if (result != 0) {
             LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
             return -1;