am 71ebe154: Add mkdirs() command.

* commit '71ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5':
  Add mkdirs() command.
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 6bfb8da..0ac656b 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -200,6 +200,12 @@
                     (enabled ? "Share enabled" : "Share disabled"), false);
         }
         return 0;
+    } else if (!strcmp(argv[1], "mkdirs")) {
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mkdirs <path>", false);
+            return 0;
+        }
+        rc = vm->mkdirs(argv[2]);
     } else {
         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false);
     }
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 180387c..f606b5b 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -32,6 +32,7 @@
 
 #include <openssl/md5.h>
 
+#include <cutils/fs.h>
 #include <cutils/log.h>
 
 #include <sysutils/NetlinkEvent.h>
@@ -1577,6 +1578,26 @@
     }
 
     return rc;
-
 }
 
+int VolumeManager::mkdirs(char* path) {
+    // Require that path lives under a volume we manage
+    const char* emulated_source = getenv("EMULATED_STORAGE_SOURCE");
+    const char* root = NULL;
+    if (!strncmp(path, emulated_source, strlen(emulated_source))) {
+        root = emulated_source;
+    } else {
+        Volume* vol = getVolumeForFile(path);
+        if (vol) {
+            root = vol->getMountpoint();
+        }
+    }
+
+    if (!root) {
+        SLOGE("Failed to find volume for %s", path);
+        return -EINVAL;
+    }
+
+    /* fs_mkdirs() does symlink checking and relative path enforcement */
+    return fs_mkdirs(path, 0700);
+}
diff --git a/VolumeManager.h b/VolumeManager.h
index be78516..9d69d6a 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -140,6 +140,15 @@
     int getDirectVolumeList(struct volume_info *vol_list);
     int unmountAllAsecsInDir(const char *directory);
 
+    /*
+     * Ensure that all directories along given path exist, creating parent
+     * directories as needed.  Validates that given path is absolute and that
+     * it contains no relative "." or ".." paths or symlinks.  Last path segment
+     * is treated as filename and ignored, unless the path ends with "/".  Also
+     * ensures that path belongs to a volume managed by vold.
+     */
+    int mkdirs(char* path);
+
 private:
     VolumeManager();
     void readInitialState();