vold: Bugfixes & cleanups

  - Fix issue where container-names > 64 bytes were getting truncated in the
    kernel. lo_name is only 64 bytes in length, so we now hash the container
    id via md5
  - Add 'dump' command to dump loop and devicemapper status
  - Add 'debug' command to enable more detailed logging at runtime
  - Log vold IPC arguments (minus encryption keys)
  - Fix premature return from Loop::lookupActive() and friends

Change-Id: I0e833261a445ce9dc1a8187e5501d27daba1ca76
Signed-off-by: San Mehat <san@google.com>
diff --git a/Devmapper.cpp b/Devmapper.cpp
index c1aa713..ec36fdb 100644
--- a/Devmapper.cpp
+++ b/Devmapper.cpp
@@ -24,12 +24,92 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 
+#include <linux/kdev_t.h>
+
 #define LOG_TAG "Vold"
 
 #include <cutils/log.h>
 
+#include <sysutils/SocketClient.h>
+
 #include "Devmapper.h"
 
+int Devmapper::dumpState(SocketClient *c) {
+
+    char *buffer = (char *) malloc(1024 * 64);
+    if (!buffer) {
+        LOGE("Error allocating memory (%s)", strerror(errno));
+        return -1;
+    }
+    memset(buffer, 0, (1024 * 64));
+
+    char *buffer2 = (char *) malloc(4096);
+    if (!buffer2) {
+        LOGE("Error allocating memory (%s)", strerror(errno));
+        free(buffer);
+        return -1;
+    }
+
+    int fd;
+    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
+        LOGE("Error opening devmapper (%s)", strerror(errno));
+        free(buffer);
+        free(buffer2);
+        return -1;
+    }
+
+    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
+    ioctlInit(io, (1024 * 64), NULL, 0);
+
+    if (ioctl(fd, DM_LIST_DEVICES, io)) {
+        LOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno));
+        free(buffer);
+        free(buffer2);
+        close(fd);
+        return -1;
+    }
+
+    struct dm_name_list *n = (struct dm_name_list *) (((char *) buffer) + io->data_start);
+    if (!n->dev) {
+        free(buffer);
+        free(buffer2);
+        close(fd);
+        return 0;
+    }
+
+    unsigned nxt = 0;
+    do {
+        n = (struct dm_name_list *) (((char *) n) + nxt);
+
+        memset(buffer2, 0, 4096);
+        struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2;
+        ioctlInit(io2, 4096, n->name, 0);
+        if (ioctl(fd, DM_DEV_STATUS, io2)) {
+            if (errno != ENXIO) {
+                LOGE("DM_DEV_STATUS ioctl failed (%s)", strerror(errno));
+            }
+            io2 = NULL;
+        }
+
+        char *tmp;
+        if (!io2) {
+            asprintf(&tmp, "%s %llu:%llu (no status available)", n->name, MAJOR(n->dev), MINOR(n->dev));
+        } else {
+            asprintf(&tmp, "%s %llu:%llu %d %d 0x%.8x %llu:%llu", n->name, MAJOR(n->dev),
+                    MINOR(n->dev), io2->target_count, io2->open_count, io2->flags, MAJOR(io2->dev),
+                            MINOR(io2->dev));
+        }
+        c->sendMsg(0, tmp, false);
+        free(tmp);
+        nxt = n->next;
+    } while (nxt);
+
+    free(buffer);
+    free(buffer2);
+    close(fd);
+    return 0;
+}
+
 void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize,
                           const char *name, unsigned flags) {
     memset(io, 0, dataSize);
@@ -39,7 +119,9 @@
     io->version[1] = 0;
     io->version[2] = 0;
     io->flags = flags;
-    strncpy(io->name, name, sizeof(io->name));
+    if (name) {
+        strncpy(io->name, name, sizeof(io->name));
+    }
 }
 
 int Devmapper::lookupActive(const char *name, char *ubuffer, size_t len) {