Revert "Revert "Adding e4crypt support""

Fix build break caused by original change

This reverts commit 84b0bab58fcc7f225e9a17a15c531b0c2fc509c5.

Change-Id: I99fbd7c3d1ed92db1f546033c8493bb71a327924
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 6daea37..9d5b8a8 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -29,6 +29,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #include <linux/loop.h>
+#include <ext4_crypt.h>
 
 #include <selinux/selinux.h>
 #include <selinux/label.h>
@@ -302,7 +303,7 @@
         }
     }
 
-    return 0;
+    return e4crypt_set_directory_policy(args[1]);
 }
 
 static struct {
@@ -446,6 +447,17 @@
     while (1) { pause(); }  // never reached
 }
 
+/*
+ * Callback to make a directory from the ext4 code
+ */
+static int do_mount_alls_make_dir(const char* dir)
+{
+    if (make_dir(dir, 0700) && errno != EEXIST) {
+        return -1;
+    }
+
+    return 0;
+}
 
 /*
  * This function might request a reboot, in which case it will
@@ -514,6 +526,37 @@
         ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n");
         ret = wipe_data_via_recovery();
         /* If reboot worked, there is no return. */
+    } else if (ret == FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED) {
+        // We have to create the key files here. Only init can call make_dir,
+        // and we can't do it from fs_mgr as then fs_mgr would depend on
+        // make_dir creating a circular dependency.
+        fstab = fs_mgr_read_fstab(args[1]);
+        for (int i = 0; i < fstab->num_entries; ++i) {
+            if (fs_mgr_is_file_encrypted(&fstab->recs[i])) {
+              if (e4crypt_create_device_key(fstab->recs[i].mount_point,
+                                            do_mount_alls_make_dir)) {
+                    ERROR("Could not create device key on %s"
+                          " - continue unencrypted\n",
+                          fstab->recs[i].mount_point);
+                }
+            }
+        }
+        fs_mgr_free_fstab(fstab);
+
+        if (e4crypt_install_keyring()) {
+            return -1;
+        }
+        property_set("ro.crypto.state", "encrypted");
+
+        // Although encrypted, we have device key, so we do not need to
+        // do anything different from the nonencrypted case.
+        action_for_each_trigger("nonencrypted", action_add_queue_tail);
+    } else if (ret == FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED) {
+        if (e4crypt_install_keyring()) {
+            return -1;
+        }
+        property_set("ro.crypto.state", "encrypted");
+        property_set("vold.decrypt", "trigger_restart_min_framework");
     } else if (ret > 0) {
         ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret);
     }
@@ -866,3 +909,12 @@
     } else
         return -1;
 }
+
+int do_installkey(int nargs, char **args)
+{
+    if (nargs == 2) {
+        return e4crypt_install_key(args[1]);
+    }
+
+    return -1;
+}