Extract UUID and label from inserted volumes.

Uses "blkid" tool to extract metadata from an inserted volume, and
reports it up to the framework.  This needs to happen in vold, since
only the FUSE-wrapped volume is visible to userspace.

Remove autorun sanitization, since FUSE takes care of this now.

Bug: 11175082
Change-Id: Ie69b38011ad6011bfb50e40d4f35a29e02150c19
diff --git a/Android.mk b/Android.mk
index 8d0b249..cecab1e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,10 +23,13 @@
 	$(KERNEL_HEADERS) \
 	system/extras/ext4_utils \
 	external/openssl/include \
+	external/stlport/stlport \
+	bionic \
 	external/scrypt/lib/crypto
 
 common_shared_libraries := \
 	libsysutils \
+	libstlport \
 	libcutils \
 	liblog \
 	libdiskconfig \
diff --git a/ResponseCode.h b/ResponseCode.h
index dccacb8..5e4c6fa 100644
--- a/ResponseCode.h
+++ b/ResponseCode.h
@@ -57,6 +57,8 @@
     static const int VolumeMountFailedBlank         = 610;
     static const int VolumeMountFailedDamaged       = 611;
     static const int VolumeMountFailedNoMedia       = 612;
+    static const int VolumeUuidChange               = 613;
+    static const int VolumeUserLabelChange          = 614;
 
     static const int ShareAvailabilityChange        = 620;
 
diff --git a/Volume.cpp b/Volume.cpp
index 7d33919..cbec5d4 100644
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -40,6 +40,8 @@
 #include <cutils/fs.h>
 #include <cutils/log.h>
 
+#include <string>
+
 #include "Volume.h"
 #include "VolumeManager.h"
 #include "ResponseCode.h"
@@ -80,6 +82,8 @@
  */
 const char *Volume::LOOPDIR           = "/mnt/obb";
 
+const char *Volume::BLKID_PATH = "/system/bin/blkid";
+
 static const char *stateToStr(int state) {
     if (state == Volume::State_Init)
         return "Initializing";
@@ -109,6 +113,8 @@
     mVm = vm;
     mDebug = false;
     mLabel = strdup(rec->label);
+    mUuid = NULL;
+    mUserLabel = NULL;
     mState = Volume::State_Init;
     mFlags = flags;
     mCurrentlyMountedKdev = -1;
@@ -118,25 +124,8 @@
 
 Volume::~Volume() {
     free(mLabel);
-}
-
-void Volume::protectFromAutorunStupidity() {
-    char filename[255];
-
-    snprintf(filename, sizeof(filename), "%s/autorun.inf", getMountpoint());
-    if (!access(filename, F_OK)) {
-        SLOGW("Volume contains an autorun.inf! - removing");
-        /*
-         * Ensure the filename is all lower-case so
-         * the process killer can find the inode.
-         * Probably being paranoid here but meh.
-         */
-        rename(filename, filename);
-        Process::killProcessesWithOpenFiles(filename, 2);
-        if (unlink(filename)) {
-            SLOGE("Failed to remove %s (%s)", filename, strerror(errno));
-        }
-    }
+    free(mUuid);
+    free(mUserLabel);
 }
 
 void Volume::setDebug(bool enable) {
@@ -162,6 +151,46 @@
     return -1;
 }
 
+void Volume::setUuid(const char* uuid) {
+    char msg[256];
+
+    if (mUuid) {
+        free(mUuid);
+    }
+
+    if (uuid) {
+        mUuid = strdup(uuid);
+        snprintf(msg, sizeof(msg), "%s %s \"%s\"", getLabel(),
+                getFuseMountpoint(), mUuid);
+    } else {
+        mUuid = NULL;
+        snprintf(msg, sizeof(msg), "%s %s", getLabel(), getFuseMountpoint());
+    }
+
+    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeUuidChange, msg,
+            false);
+}
+
+void Volume::setUserLabel(const char* userLabel) {
+    char msg[256];
+
+    if (mUserLabel) {
+        free(mUserLabel);
+    }
+
+    if (userLabel) {
+        mUserLabel = strdup(userLabel);
+        snprintf(msg, sizeof(msg), "%s %s \"%s\"", getLabel(),
+                getFuseMountpoint(), mUserLabel);
+    } else {
+        mUserLabel = NULL;
+        snprintf(msg, sizeof(msg), "%s %s", getLabel(), getFuseMountpoint());
+    }
+
+    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeUserLabelChange,
+            msg, false);
+}
+
 void Volume::setState(int state) {
     char msg[255];
     int oldState = mState;
@@ -274,7 +303,6 @@
             fclose(fp);
             return true;
         }
-
     }
 
     fclose(fp);
@@ -413,7 +441,7 @@
             continue;
         }
 
-        protectFromAutorunStupidity();
+        extractMetadata(devicePath);
 
         if (providesAsec && mountAsecExternal() != 0) {
             SLOGE("Failed to mount secure area (%s)", strerror(errno));
@@ -550,6 +578,8 @@
         SLOGI("Encrypted volume %s reverted successfully", getMountpoint());
     }
 
+    setUuid(NULL);
+    setUserLabel(NULL);
     setState(Volume::State_Idle);
     mCurrentlyMountedKdev = -1;
     return 0;
@@ -608,3 +638,55 @@
 
     return rc;
 }
+
+/*
+ * Use blkid to extract UUID and label from device, since it handles many
+ * obscure edge cases around partition types and formats. Always broadcasts
+ * updated metadata values.
+ */
+int Volume::extractMetadata(const char* devicePath) {
+    int res = 0;
+
+    std::string cmd;
+    cmd = BLKID_PATH;
+    cmd += " -c /dev/null ";
+    cmd += devicePath;
+
+    FILE* fp = popen(cmd.c_str(), "r");
+    if (!fp) {
+        ALOGE("Failed to run %s: %s", cmd.c_str(), strerror(errno));
+        res = -1;
+        goto done;
+    }
+
+    char line[1024];
+    char value[128];
+    if (fgets(line, sizeof(line), fp) != NULL) {
+        ALOGD("blkid reported: %s", line);
+
+        char* start = strstr(line, "UUID=") + 5;
+        if (sscanf(start, "\"%127[^\"]\"", value) == 1) {
+            setUuid(value);
+        } else {
+            setUuid(NULL);
+        }
+
+        start = strstr(line, "LABEL=") + 6;
+        if (sscanf(start, "\"%127[^\"]\"", value) == 1) {
+            setUserLabel(value);
+        } else {
+            setUserLabel(NULL);
+        }
+    } else {
+        res = -1;
+    }
+
+    pclose(fp);
+
+done:
+    if (res == -1) {
+        setUuid(NULL);
+        setUserLabel(NULL);
+    }
+    return res;
+}
diff --git a/Volume.h b/Volume.h
index 194004c..1444ed3 100644
--- a/Volume.h
+++ b/Volume.h
@@ -45,11 +45,13 @@
     static const char *SEC_ASECDIR_EXT;
     static const char *SEC_ASECDIR_INT;
     static const char *ASECDIR;
-
     static const char *LOOPDIR;
+    static const char *BLKID_PATH;
 
 protected:
-    char *mLabel;
+    char* mLabel;
+    char* mUuid;
+    char* mUserLabel;
     VolumeManager *mVm;
     bool mDebug;
     int mPartIdx;
@@ -69,7 +71,9 @@
     int unmountVol(bool force, bool revert);
     int formatVol(bool wipe);
 
-    const char *getLabel() { return mLabel; }
+    const char* getLabel() { return mLabel; }
+    const char* getUuid() { return mUuid; }
+    const char* getUserLabel() { return mUserLabel; }
     int getState() { return mState; }
     int getFlags() { return mFlags; };
 
@@ -87,6 +91,8 @@
     virtual int getVolInfo(struct volume_info *v) = 0;
 
 protected:
+    void setUuid(const char* uuid);
+    void setUserLabel(const char* userLabel);
     void setState(int state);
 
     virtual int getDeviceNodes(dev_t *devs, int max) = 0;
@@ -101,7 +107,7 @@
     bool isMountpointMounted(const char *path);
     int mountAsecExternal();
     int doUnmount(const char *path, bool force);
-    void protectFromAutorunStupidity();
+    int extractMetadata(const char* devicePath);
 };
 
 typedef android::List<Volume *> VolumeCollection;