vold: allow to store key in a file on another partition

Add support for keeping the keys in a separate file on another partition,
for devices with no space reserved for a footer after the userdata filesystem.

Add support for encrypting the volumes managed by vold, if they meet certain
criteria, namely being marked as nonremovable and encryptable in vold.fstab.
A bit of trickiness is required to keep vold happy.

Change-Id: Idf0611f74b56c1026c45742ca82e0c26e58828fe
diff --git a/main.cpp b/main.cpp
index 9c45774..5924fe4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -32,6 +32,7 @@
 #include "CommandListener.h"
 #include "NetlinkManager.h"
 #include "DirectVolume.h"
+#include "cryptfs.h"
 
 static int process_config(VolumeManager *vm);
 static void coldboot(const char *path);
@@ -141,6 +142,22 @@
     }
 }
 
+static int parse_mount_flags(char *mount_flags)
+{
+    char *save_ptr;
+    int flags = 0;
+
+    if (strcasestr(mount_flags, "encryptable")) {
+        flags |= VOL_ENCRYPTABLE;
+    }
+
+    if (strcasestr(mount_flags, "nonremovable")) {
+        flags |= VOL_NONREMOVABLE;
+    }
+
+    return flags;
+}
+
 static int process_config(VolumeManager *vm) {
     FILE *fp;
     int n = 0;
@@ -153,7 +170,8 @@
     while(fgets(line, sizeof(line), fp)) {
         const char *delim = " \t";
         char *save_ptr;
-        char *type, *label, *mount_point;
+        char *type, *label, *mount_point, *mount_flags, *sysfs_path;
+        int flags;
 
         n++;
         line[strlen(line)-1] = '\0';
@@ -193,13 +211,27 @@
                 dv = new DirectVolume(vm, label, mount_point, atoi(part));
             }
 
-            while (char *sysfs_path = strtok_r(NULL, delim, &save_ptr)) {
+            while ((sysfs_path = strtok_r(NULL, delim, &save_ptr))) {
+                if (*sysfs_path != '/') {
+                    /* If the first character is not a '/', it must be flags */
+                    break;
+                }
                 if (dv->addPath(sysfs_path)) {
                     SLOGE("Failed to add devpath %s to volume %s", sysfs_path,
                          label);
                     goto out_fail;
                 }
             }
+
+            /* If sysfs_path is non-null at this point, then it contains
+             * the optional flags for this volume
+             */
+            if (sysfs_path)
+                flags = parse_mount_flags(sysfs_path);
+            else
+                flags = 0;
+            dv->setFlags(flags);
+
             vm->addVolume(dv);
         } else if (!strcmp(type, "map_mount")) {
         } else {