Merge "Move to modern utility methods from android::base."
diff --git a/Devmapper.cpp b/Devmapper.cpp
index 2cbed86..2510771 100644
--- a/Devmapper.cpp
+++ b/Devmapper.cpp
@@ -30,11 +30,8 @@
 
 #include <linux/kdev_t.h>
 
-#define LOG_TAG "Vold"
-
-#include <cutils/log.h>
-
 #include <android-base/logging.h>
+#include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 #include <utils/Trace.h>
 
@@ -62,42 +59,6 @@
     }
 }
 
-int Devmapper::lookupActive(const char *name_raw, char *ubuffer, size_t len) {
-    auto name_string = StringPrintf("%s%s", kVoldPrefix, name_raw);
-    const char* name = name_string.c_str();
-
-    char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
-    if (!buffer) {
-        SLOGE("Error allocating memory (%s)", strerror(errno));
-        return -1;
-    }
-
-    int fd;
-    if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
-        SLOGE("Error opening devmapper (%s)", strerror(errno));
-        free(buffer);
-        return -1;
-    }
-
-    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
- 
-    ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
-    if (ioctl(fd, DM_DEV_STATUS, io)) {
-        if (errno != ENXIO) {
-            SLOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno));
-        }
-        free(buffer);
-        close(fd);
-        return -1;
-    }
-    close(fd);
-
-    unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
-    free(buffer);
-    snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
-    return 0;
-}
-
 int Devmapper::create(const char *name_raw, const char *loopFile, const char *key,
                       unsigned long numSectors, char *ubuffer, size_t len) {
     auto name_string = StringPrintf("%s%s", kVoldPrefix, name_raw);
@@ -105,13 +66,13 @@
 
     char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
     if (!buffer) {
-        SLOGE("Error allocating memory (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed malloc";
         return -1;
     }
 
     int fd;
     if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
-        SLOGE("Error opening devmapper (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed open";
         free(buffer);
         return -1;
     }
@@ -122,7 +83,7 @@
     ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
 
     if (ioctl(fd, DM_DEV_CREATE, io)) {
-        SLOGE("Error creating device mapping (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed DM_DEV_CREATE";
         free(buffer);
         close(fd);
         return -1;
@@ -137,7 +98,7 @@
     geoParams += strlen(geoParams) + 1;
     geoParams = (char *) _align(geoParams, 8);
     if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) {
-        SLOGE("Error setting device geometry (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed DM_DEV_SET_GEOMETRY";
         free(buffer);
         close(fd);
         return -1;
@@ -146,7 +107,7 @@
     // Retrieve the device number we were allocated
     ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
     if (ioctl(fd, DM_DEV_STATUS, io)) {
-        SLOGE("Error retrieving devmapper status (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed DM_DEV_STATUS";
         free(buffer);
         close(fd);
         return -1;
@@ -177,7 +138,7 @@
     tgt->next = cryptParams - buffer;
 
     if (ioctl(fd, DM_TABLE_LOAD, io)) {
-        SLOGE("Error loading mapping table (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed DM_TABLE_LOAD";
         free(buffer);
         close(fd);
         return -1;
@@ -187,7 +148,7 @@
     ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
 
     if (ioctl(fd, DM_DEV_SUSPEND, io)) {
-        SLOGE("Error Resuming (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed DM_DEV_SUSPEND";
         free(buffer);
         close(fd);
         return -1;
@@ -205,13 +166,13 @@
 
     char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
     if (!buffer) {
-        SLOGE("Error allocating memory (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed malloc";
         return -1;
     }
 
     int fd;
     if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
-        SLOGE("Error opening devmapper (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed open";
         free(buffer);
         return -1;
     }
@@ -223,7 +184,7 @@
 
     if (ioctl(fd, DM_DEV_REMOVE, io)) {
         if (errno != ENXIO) {
-            SLOGE("Error destroying device mapping (%s)", strerror(errno));
+            PLOG(ERROR) << "Failed DM_DEV_REMOVE";
         }
         free(buffer);
         close(fd);
@@ -239,21 +200,21 @@
     ATRACE_NAME("Devmapper::destroyAll");
     char *buffer = (char *) malloc(1024 * 64);
     if (!buffer) {
-        SLOGE("Error allocating memory (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed malloc";
         return -1;
     }
     memset(buffer, 0, (1024 * 64));
 
     char *buffer2 = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
     if (!buffer2) {
-        SLOGE("Error allocating memory (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed malloc";
         free(buffer);
         return -1;
     }
 
     int fd;
     if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
-        SLOGE("Error opening devmapper (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed open";
         free(buffer);
         free(buffer2);
         return -1;
@@ -263,7 +224,7 @@
     ioctlInit(io, (1024 * 64), NULL, 0);
 
     if (ioctl(fd, DM_LIST_DEVICES, io)) {
-        SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed DM_LIST_DEVICES";
         free(buffer);
         free(buffer2);
         close(fd);
@@ -281,19 +242,20 @@
     unsigned nxt = 0;
     do {
         n = (struct dm_name_list *) (((char *) n) + nxt);
-        if (strncmp(n->name, kVoldPrefix, strlen(kVoldPrefix)) == 0) {
-            LOG(DEBUG) << "Tearing down stale dm device named " << n->name;
+        auto name = std::string(n->name);
+        if (android::base::StartsWith(name, kVoldPrefix)) {
+            LOG(DEBUG) << "Tearing down stale dm device named " << name;
 
             memset(buffer2, 0, DEVMAPPER_BUFFER_SIZE);
             struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2;
             ioctlInit(io2, DEVMAPPER_BUFFER_SIZE, n->name, 0);
             if (ioctl(fd, DM_DEV_REMOVE, io2)) {
                 if (errno != ENXIO) {
-                    PLOG(WARNING) << "Failed to destroy dm device named " << n->name;
+                    PLOG(WARNING) << "Failed to destroy dm device named " << name;
                 }
             }
         } else {
-            LOG(VERBOSE) << "Found unmanaged dm device named " << n->name;
+            LOG(VERBOSE) << "Found unmanaged dm device named " << name;
         }
         nxt = n->next;
     } while (nxt);
diff --git a/Devmapper.h b/Devmapper.h
index 086ad78..7bb9786 100644
--- a/Devmapper.h
+++ b/Devmapper.h
@@ -26,7 +26,6 @@
                       unsigned long numSectors, char *buffer, size_t len);
     static int destroy(const char *name);
     static int destroyAll();
-    static int lookupActive(const char *name, char *buffer, size_t len);
 
 private:
     static void *_align(void *ptr, unsigned int a);
diff --git a/Loop.cpp b/Loop.cpp
index 1eb9865..3736d6a 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -31,11 +31,8 @@
 
 #include <linux/kdev_t.h>
 
-#define LOG_TAG "Vold"
-
-#include <cutils/log.h>
-
 #include <android-base/logging.h>
+#include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <utils/Trace.h>
@@ -49,161 +46,6 @@
 
 static const char* kVoldPrefix = "vold:";
 
-int Loop::lookupActive(const char *id_raw, char *buffer, size_t len) {
-    auto id_string = StringPrintf("%s%s", kVoldPrefix, id_raw);
-    const char* id = id_string.c_str();
-
-    int i;
-    int fd;
-    char filename[256];
-
-    memset(buffer, 0, len);
-
-    for (i = 0; i < LOOP_MAX; i++) {
-        struct loop_info64 li;
-        int rc;
-
-        snprintf(filename, sizeof(filename), "/dev/block/loop%d", i);
-
-        if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
-            if (errno != ENOENT) {
-                SLOGE("Unable to open %s (%s)", filename, strerror(errno));
-            } else {
-                continue;
-            }
-            return -1;
-        }
-
-        rc = ioctl(fd, LOOP_GET_STATUS64, &li);
-        if (rc < 0 && errno == ENXIO) {
-            close(fd);
-            continue;
-        }
-        close(fd);
-
-        if (rc < 0) {
-            SLOGE("Unable to get loop status for %s (%s)", filename,
-                 strerror(errno));
-            return -1;
-        }
-        if (!strncmp((const char*) li.lo_crypt_name, id, LO_NAME_SIZE)) {
-            break;
-        }
-    }
-
-    if (i == LOOP_MAX) {
-        errno = ENOENT;
-        return -1;
-    }
-    strlcpy(buffer, filename, len);
-    return 0;
-}
-
-int Loop::create(const char *id_raw, const char *loopFile, char *loopDeviceBuffer, size_t len) {
-    auto id_string = StringPrintf("%s%s", kVoldPrefix, id_raw);
-    const char* id = id_string.c_str();
-
-    int i;
-    int fd;
-    char filename[256];
-
-    for (i = 0; i < LOOP_MAX; i++) {
-        struct loop_info64 li;
-        int rc;
-        char *secontext = NULL;
-
-        snprintf(filename, sizeof(filename), "/dev/block/loop%d", i);
-
-        /*
-         * The kernel starts us off with 8 loop nodes, but more
-         * are created on-demand if needed.
-         */
-        mode_t mode = 0660 | S_IFBLK;
-        unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8);
-
-        if (sehandle) {
-            rc = selabel_lookup(sehandle, &secontext, filename, S_IFBLK);
-            if (rc == 0)
-                setfscreatecon(secontext);
-        }
-
-        if (mknod(filename, mode, dev) < 0) {
-            if (errno != EEXIST) {
-                int sverrno = errno;
-                SLOGE("Error creating loop device node (%s)", strerror(errno));
-                if (secontext) {
-                    freecon(secontext);
-                    setfscreatecon(NULL);
-                }
-                errno = sverrno;
-                return -1;
-            }
-        }
-        if (secontext) {
-            freecon(secontext);
-            setfscreatecon(NULL);
-        }
-
-        if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
-            SLOGE("Unable to open %s (%s)", filename, strerror(errno));
-            return -1;
-        }
-
-        rc = ioctl(fd, LOOP_GET_STATUS64, &li);
-        if (rc < 0 && errno == ENXIO)
-            break;
-
-        close(fd);
-
-        if (rc < 0) {
-            SLOGE("Unable to get loop status for %s (%s)", filename,
-                 strerror(errno));
-            return -1;
-        }
-    }
-
-    if (i == LOOP_MAX) {
-        SLOGE("Exhausted all loop devices");
-        errno = ENOSPC;
-        return -1;
-    }
-
-    strlcpy(loopDeviceBuffer, filename, len);
-
-    int file_fd;
-
-    if ((file_fd = open(loopFile, O_RDWR | O_CLOEXEC)) < 0) {
-        SLOGE("Unable to open %s (%s)", loopFile, strerror(errno));
-        close(fd);
-        return -1;
-    }
-
-    if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) {
-        SLOGE("Error setting up loopback interface (%s)", strerror(errno));
-        close(file_fd);
-        close(fd);
-        return -1;
-    }
-
-    struct loop_info64 li;
-
-    memset(&li, 0, sizeof(li));
-    strlcpy((char*) li.lo_crypt_name, id, LO_NAME_SIZE);
-    strlcpy((char*) li.lo_file_name, loopFile, LO_NAME_SIZE);
-
-    if (ioctl(fd, LOOP_SET_STATUS64, &li) < 0) {
-        SLOGE("Error setting loopback status (%s)", strerror(errno));
-        close(file_fd);
-        close(fd);
-        return -1;
-    }
-
-    close(fd);
-    close(file_fd);
-
-    return 0;
-}
-
 int Loop::create(const std::string& target, std::string& out_device) {
     unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
     if (ctl_fd.get() == -1) {
@@ -251,12 +93,12 @@
 
     device_fd = open(loopDevice, O_RDONLY | O_CLOEXEC);
     if (device_fd < 0) {
-        SLOGE("Failed to open loop (%d)", errno);
+        PLOG(ERROR) << "Failed to open " << loopDevice;
         return -1;
     }
 
     if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
-        SLOGE("Failed to destroy loop (%d)", errno);
+        PLOG(ERROR) << "Failed to destroy " << loopDevice;
         close(device_fd);
         return -1;
     }
@@ -279,7 +121,8 @@
 
     // Poke through all devices looking for loops
     while ((de = readdir(dir))) {
-        if (strncmp(de->d_name, "loop", 4) != 0) continue;
+        auto test = std::string(de->d_name);
+        if (!android::base::StartsWith(test, "loop")) continue;
 
         auto path = root + de->d_name;
         unique_fd fd(open(path.c_str(), O_RDWR | O_CLOEXEC));
@@ -296,8 +139,8 @@
             continue;
         }
 
-        char* id = (char*) li.lo_crypt_name;
-        if (strncmp(id, kVoldPrefix, strlen(kVoldPrefix)) == 0) {
+        auto id = std::string((char*) li.lo_crypt_name);
+        if (android::base::StartsWith(id, kVoldPrefix)) {
             LOG(DEBUG) << "Tearing down stale loop device at " << path << " named " << id;
 
             if (ioctl(fd.get(), LOOP_CLR_FD, 0) < 0) {
@@ -332,22 +175,22 @@
     int fd;
 
     if ((fd = open(file, O_RDWR | O_CLOEXEC)) < 0) {
-        SLOGE("Error opening imagefile (%s)", strerror(errno));
+        PLOG(ERROR) << "Failed to open " << file;
         return -1;
     }
 
-    SLOGD("Attempting to increase size of %s to %lu sectors.", file, numSectors);
+    LOG(DEBUG) << "Attempting to increase " << file << " to " << numSectors;
 
     if (fallocate(fd, 0, 0, numSectors * 512)) {
         if (errno == ENOSYS || errno == ENOTSUP) {
-            SLOGW("fallocate not found. Falling back to ftruncate.");
+            PLOG(WARNING) << "fallocate not found. Falling back to ftruncate.";
             if (ftruncate(fd, numSectors * 512) < 0) {
-                SLOGE("Error truncating imagefile (%s)", strerror(errno));
+                PLOG(ERROR) << "Failed to ftruncate";
                 close(fd);
                 return -1;
             }
         } else {
-            SLOGE("Error allocating space (%s)", strerror(errno));
+            PLOG(ERROR) << "Failed to fallocate";
             close(fd);
             return -1;
         }
diff --git a/Loop.h b/Loop.h
index 654b8ad..130c5b6 100644
--- a/Loop.h
+++ b/Loop.h
@@ -25,8 +25,6 @@
 public:
     static const int LOOP_MAX = 4096;
 public:
-    static int lookupActive(const char *id, char *buffer, size_t len);
-    static int create(const char *id, const char *loopFile, char *loopDeviceBuffer, size_t len);
     static int create(const std::string& file, std::string& out_device);
     static int destroyByDevice(const char *loopDevice);
     static int destroyAll();
diff --git a/NetlinkHandler.cpp b/NetlinkHandler.cpp
index ecda2a0..92131e9 100644
--- a/NetlinkHandler.cpp
+++ b/NetlinkHandler.cpp
@@ -19,9 +19,7 @@
 #include <errno.h>
 #include <string.h>
 
-#define LOG_TAG "Vold"
-
-#include <cutils/log.h>
+#include <android-base/logging.h>
 
 #include <sysutils/NetlinkEvent.h>
 #include "NetlinkHandler.h"
@@ -47,11 +45,11 @@
     const char *subsys = evt->getSubsystem();
 
     if (!subsys) {
-        SLOGW("No subsystem found in netlink event");
+        LOG(WARNING) << "No subsystem found in netlink event";
         return;
     }
 
-    if (!strcmp(subsys, "block")) {
+    if (std::string(subsys) == "block") {
         vm->handleBlockEvent(evt);
     }
 }
diff --git a/NetlinkManager.cpp b/NetlinkManager.cpp
index 90e3c6c..409cdc8 100644
--- a/NetlinkManager.cpp
+++ b/NetlinkManager.cpp
@@ -26,9 +26,7 @@
 
 #include <linux/netlink.h>
 
-#define LOG_TAG "Vold"
-
-#include <cutils/log.h>
+#include <android-base/logging.h>
 
 #include "NetlinkManager.h"
 #include "NetlinkHandler.h"
@@ -60,7 +58,7 @@
 
     if ((mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC,
             NETLINK_KOBJECT_UEVENT)) < 0) {
-        SLOGE("Unable to create uevent socket: %s", strerror(errno));
+        PLOG(ERROR) << "Unable to create uevent socket";
         return -1;
     }
 
@@ -69,23 +67,23 @@
     // Try using SO_RCVBUF if that fails.
     if ((setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) &&
         (setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)) {
-        SLOGE("Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option: %s", strerror(errno));
+        PLOG(ERROR) << "Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option";
         goto out;
     }
 
     if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
-        SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));
+        PLOG(ERROR) << "Unable to set uevent socket SO_PASSCRED option";
         goto out;
     }
 
     if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
-        SLOGE("Unable to bind uevent socket: %s", strerror(errno));
+        PLOG(ERROR) << "Unable to bind uevent socket";
         goto out;
     }
 
     mHandler = new NetlinkHandler(mSock);
     if (mHandler->start()) {
-        SLOGE("Unable to start NetlinkHandler: %s", strerror(errno));
+        PLOG(ERROR) << "Unable to start NetlinkHandler";
         goto out;
     }
 
@@ -100,7 +98,7 @@
     int status = 0;
 
     if (mHandler->stop()) {
-        SLOGE("Unable to stop NetlinkHandler: %s", strerror(errno));
+        PLOG(ERROR) << "Unable to stop NetlinkHandler";
         status = -1;
     }
     delete mHandler;
diff --git a/Process.cpp b/Process.cpp
index 1c0f504..042ba2d 100644
--- a/Process.cpp
+++ b/Process.cpp
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <string.h>
 #include <fcntl.h>
+#include <fts.h>
 #include <dirent.h>
 #include <ctype.h>
 #include <pwd.h>
@@ -27,196 +28,98 @@
 #include <sys/stat.h>
 #include <signal.h>
 
-#define LOG_TAG "ProcessKiller"
+#include <fstream>
+#include <unordered_set>
 
 #include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 #include <android-base/logging.h>
-#include <cutils/log.h>
 
 #include "Process.h"
 
-using android::base::ReadFileToString;
 using android::base::StringPrintf;
 
-int Process::readSymLink(const char *path, char *link, size_t max) {
-    struct stat s;
-    int length;
+namespace android {
+namespace vold {
 
-    if (lstat(path, &s) < 0)
-        return 0;
-    if ((s.st_mode & S_IFMT) != S_IFLNK)
-        return 0;
-
-    // we have a symlink
-    length = readlink(path, link, max- 1);
-    if (length <= 0)
-        return 0;
-    link[length] = 0;
-    return 1;
-}
-
-int Process::pathMatchesMountPoint(const char* path, const char* mountPoint) {
-    int length = strlen(mountPoint);
-    if (length > 1 && strncmp(path, mountPoint, length) == 0) {
-        // we need to do extra checking if mountPoint does not end in a '/'
-        if (mountPoint[length - 1] == '/')
-            return 1;
-        // if mountPoint does not have a trailing slash, we need to make sure
-        // there is one in the path to avoid partial matches.
-        return (path[length] == 0 || path[length] == '/');
-    }
-    
-    return 0;
-}
-
-void Process::getProcessName(int pid, std::string& out_name) {
-    if (!ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &out_name)) {
-        out_name = "???";
-    }
-}
-
-int Process::checkFileDescriptorSymLinks(int pid, const char *mountPoint) {
-    return checkFileDescriptorSymLinks(pid, mountPoint, NULL, 0);
-}
-
-int Process::checkFileDescriptorSymLinks(int pid, const char *mountPoint, char *openFilename, size_t max) {
-
-
-    // compute path to process's directory of open files
-    char    path[PATH_MAX];
-    snprintf(path, sizeof(path), "/proc/%d/fd", pid);
-    DIR *dir = opendir(path);
-    if (!dir)
-        return 0;
-
-    // remember length of the path
-    int parent_length = strlen(path);
-    // append a trailing '/'
-    path[parent_length++] = '/';
-
-    struct dirent* de;
-    while ((de = readdir(dir))) {
-        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")
-                || strlen(de->d_name) + parent_length + 1 >= PATH_MAX)
-            continue;
-        
-        // append the file name, after truncating to parent directory
-        path[parent_length] = 0;
-        strlcat(path, de->d_name, PATH_MAX);
-
-        char link[PATH_MAX];
-
-        if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) {
-            if (openFilename) {
-                memset(openFilename, 0, max);
-                strlcpy(openFilename, link, max);
+static bool checkMaps(const std::string& path, const std::string& prefix) {
+    bool found = false;
+    std::ifstream infile(path);
+    std::string line;
+    while (std::getline(infile, line)) {
+        std::string::size_type pos = line.find('/');
+        if (pos != std::string::npos) {
+            line = line.substr(pos);
+            if (android::base::StartsWith(line, prefix.c_str())) {
+                LOG(WARNING) << "Found map " << path << " referencing " << line;
+                found = true;
             }
-            closedir(dir);
-            return 1;
         }
     }
-
-    closedir(dir);
-    return 0;
+    return found;
 }
 
-int Process::checkFileMaps(int pid, const char *mountPoint) {
-    return checkFileMaps(pid, mountPoint, NULL, 0);
-}
-
-int Process::checkFileMaps(int pid, const char *mountPoint, char *openFilename, size_t max) {
-    FILE *file;
-    char buffer[PATH_MAX + 100];
-
-    snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid);
-    file = fopen(buffer, "re");
-    if (!file)
-        return 0;
-    
-    while (fgets(buffer, sizeof(buffer), file)) {
-        // skip to the path
-        const char* path = strchr(buffer, '/');
-        if (path && pathMatchesMountPoint(path, mountPoint)) {
-            if (openFilename) {
-                memset(openFilename, 0, max);
-                strlcpy(openFilename, path, max);
-            }
-            fclose(file);
-            return 1;
+static bool checkSymlink(const std::string& path, const std::string& prefix) {
+    std::string res;
+    if (android::base::Readlink(path, &res)) {
+        if (android::base::StartsWith(res, prefix.c_str())) {
+            LOG(WARNING) << "Found symlink " << path << " referencing " << res;
+            return true;
         }
     }
-    
-    fclose(file);
-    return 0;
+    return false;
 }
 
-int Process::checkSymLink(int pid, const char *mountPoint, const char *name) {
-    char    path[PATH_MAX];
-    char    link[PATH_MAX];
+int KillProcessesWithOpenFiles(const std::string& prefix, int signal) {
+    std::unordered_set<pid_t> pids;
 
-    snprintf(path, sizeof(path), "/proc/%d/%s", pid, name);
-    if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) 
-        return 1;
-    return 0;
-}
-
-int Process::getPid(const char *s) {
-    int result = 0;
-    while (*s) {
-        if (!isdigit(*s)) return -1;
-        result = 10 * result + (*s++ - '0');
-    }
-    return result;
-}
-
-extern "C" void vold_killProcessesWithOpenFiles(const char *path, int signal) {
-	Process::killProcessesWithOpenFiles(path, signal);
-}
-
-/*
- * Hunt down processes that have files open at the given mount point.
- */
-int Process::killProcessesWithOpenFiles(const char *path, int signal) {
-    int count = 0;
-    DIR* dir;
-    struct dirent* de;
-
-    if (!(dir = opendir("/proc"))) {
-        SLOGE("opendir failed (%s)", strerror(errno));
-        return count;
+    auto proc_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/proc"), closedir);
+    if (!proc_d) {
+        PLOG(ERROR) << "Failed to open proc";
+        return -1;
     }
 
-    while ((de = readdir(dir))) {
-        int pid = getPid(de->d_name);
-        if (pid == -1)
-            continue;
+    struct dirent* proc_de;
+    while ((proc_de = readdir(proc_d.get())) != nullptr) {
+        // We only care about valid PIDs
+        pid_t pid;
+        if (proc_de->d_type != DT_DIR) continue;
+        if (!android::base::ParseInt(proc_de->d_name, &pid)) continue;
 
-        std::string name;
-        getProcessName(pid, name);
+        // Look for references to prefix
+        bool found = false;
+        auto path = StringPrintf("/proc/%d", pid);
+        found |= checkMaps(path + "/maps", prefix);
+        found |= checkSymlink(path + "/cwd", prefix);
+        found |= checkSymlink(path + "/root", prefix);
+        found |= checkSymlink(path + "/exe", prefix);
 
-        char openfile[PATH_MAX];
-
-        if (checkFileDescriptorSymLinks(pid, path, openfile, sizeof(openfile))) {
-            SLOGE("Process %s (%d) has open file %s", name.c_str(), pid, openfile);
-        } else if (checkFileMaps(pid, path, openfile, sizeof(openfile))) {
-            SLOGE("Process %s (%d) has open filemap for %s", name.c_str(), pid, openfile);
-        } else if (checkSymLink(pid, path, "cwd")) {
-            SLOGE("Process %s (%d) has cwd within %s", name.c_str(), pid, path);
-        } else if (checkSymLink(pid, path, "root")) {
-            SLOGE("Process %s (%d) has chroot within %s", name.c_str(), pid, path);
-        } else if (checkSymLink(pid, path, "exe")) {
-            SLOGE("Process %s (%d) has executable path within %s", name.c_str(), pid, path);
+        auto fd_path = path + "/fd";
+        auto fd_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(fd_path.c_str()), closedir);
+        if (!fd_d) {
+            PLOG(WARNING) << "Failed to open " << fd_path;
         } else {
-            continue;
+            struct dirent* fd_de;
+            while ((fd_de = readdir(fd_d.get())) != nullptr) {
+                if (fd_de->d_type != DT_LNK) continue;
+                found |= checkSymlink(fd_path + "/" + fd_de->d_name, prefix);
+            }
         }
 
-        if (signal != 0) {
-            SLOGW("Sending %s to process %d", strsignal(signal), pid);
-            kill(pid, signal);
-            count++;
+        if (found) {
+            pids.insert(pid);
         }
     }
-    closedir(dir);
-    return count;
+    if (signal != 0) {
+        for (const auto& pid : pids) {
+            LOG(WARNING) << "Sending " << strsignal(signal) << " to " << pid;
+            kill(pid, signal);
+        }
+    }
+    return pids.size();
 }
+
+}  // namespace vold
+}  // namespace android
diff --git a/Process.h b/Process.h
index 4ddbdb9..1406782 100644
--- a/Process.h
+++ b/Process.h
@@ -17,28 +17,12 @@
 #ifndef _PROCESS_H
 #define _PROCESS_H
 
-#ifdef __cplusplus
+namespace android {
+namespace vold {
 
-class Process {
-public:
-    static int killProcessesWithOpenFiles(const char *path, int signal);
-    static int getPid(const char *s);
-    static int checkSymLink(int pid, const char *path, const char *name);
-    static int checkFileMaps(int pid, const char *path);
-    static int checkFileMaps(int pid, const char *path, char *openFilename, size_t max);
-    static int checkFileDescriptorSymLinks(int pid, const char *mountPoint);
-    static int checkFileDescriptorSymLinks(int pid, const char *mountPoint, char *openFilename, size_t max);
-    static void getProcessName(int pid, std::string& out_name);
-private:
-    static int readSymLink(const char *path, char *link, size_t max);
-    static int pathMatchesMountPoint(const char *path, const char *mountPoint);
-};
+int KillProcessesWithOpenFiles(const std::string& path, int signal);
 
-extern "C" {
-#endif /* __cplusplus */
-	void vold_killProcessesWithOpenFiles(const char *path, int signal);
-#ifdef __cplusplus
-}
-#endif
+}  // namespace vold
+}  // namespace android
 
 #endif
diff --git a/TrimTask.cpp b/TrimTask.cpp
index fafb345..2718095 100644
--- a/TrimTask.cpp
+++ b/TrimTask.cpp
@@ -20,7 +20,6 @@
 
 #include <android-base/stringprintf.h>
 #include <android-base/logging.h>
-#include <cutils/properties.h>
 #include <fs_mgr.h>
 #include <private/android_filesystem_config.h>
 #include <hardware_legacy/power.h>
@@ -67,9 +66,9 @@
     struct fstab_rec *prev_rec = NULL;
 
     for (int i = 0; i < fstab->num_entries; i++) {
+        auto fs_type = std::string(fstab->recs[i].fs_type);
         /* Skip raw partitions */
-        if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
-            !strcmp(fstab->recs[i].fs_type, "mtd")) {
+        if (fs_type == "emmc" || fs_type == "mtd") {
             continue;
         }
         /* Skip read-only filesystems */
diff --git a/Utils.cpp b/Utils.cpp
index a9350e8..484de90 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -22,6 +22,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 #include <cutils/fs.h>
 #include <logwrap/logwrap.h>
@@ -129,19 +130,19 @@
     // we start sending signals
     if (!VolumeManager::shutting_down) sleep(5);
 
-    Process::killProcessesWithOpenFiles(cpath, SIGINT);
+    KillProcessesWithOpenFiles(path, SIGINT);
     if (!VolumeManager::shutting_down) sleep(5);
     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
         return OK;
     }
 
-    Process::killProcessesWithOpenFiles(cpath, SIGTERM);
+    KillProcessesWithOpenFiles(path, SIGTERM);
     if (!VolumeManager::shutting_down) sleep(5);
     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
         return OK;
     }
 
-    Process::killProcessesWithOpenFiles(cpath, SIGKILL);
+    KillProcessesWithOpenFiles(path, SIGKILL);
     if (!VolumeManager::shutting_down) sleep(5);
     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
         return OK;
@@ -151,25 +152,24 @@
 }
 
 status_t KillProcessesUsingPath(const std::string& path) {
-    const char* cpath = path.c_str();
-    if (Process::killProcessesWithOpenFiles(cpath, SIGINT) == 0) {
+    if (KillProcessesWithOpenFiles(path, SIGINT) == 0) {
         return OK;
     }
     if (!VolumeManager::shutting_down) sleep(5);
 
-    if (Process::killProcessesWithOpenFiles(cpath, SIGTERM) == 0) {
+    if (KillProcessesWithOpenFiles(path, SIGTERM) == 0) {
         return OK;
     }
     if (!VolumeManager::shutting_down) sleep(5);
 
-    if (Process::killProcessesWithOpenFiles(cpath, SIGKILL) == 0) {
+    if (KillProcessesWithOpenFiles(path, SIGKILL) == 0) {
         return OK;
     }
     if (!VolumeManager::shutting_down) sleep(5);
 
     // Send SIGKILL a second time to determine if we've
     // actually killed everyone with open files
-    if (Process::killProcessesWithOpenFiles(cpath, SIGKILL) == 0) {
+    if (KillProcessesWithOpenFiles(path, SIGKILL) == 0) {
         return OK;
     }
     PLOG(ERROR) << "Failed to kill processes using " << path;
@@ -184,11 +184,28 @@
     return OK;
 }
 
-static status_t readMetadata(const std::string& path, std::string& fsType,
-        std::string& fsUuid, std::string& fsLabel, bool untrusted) {
-    fsType.clear();
-    fsUuid.clear();
-    fsLabel.clear();
+bool FindValue(const std::string& raw, const std::string& key, std::string* value) {
+    auto qual = key + "=\"";
+    auto start = raw.find(qual);
+    if (start > 0 && raw[start - 1] != ' ') {
+        start = raw.find(qual, start + 1);
+    }
+
+    if (start == std::string::npos) return false;
+    start += qual.length();
+
+    auto end = raw.find("\"", start);
+    if (end == std::string::npos) return false;
+
+    *value = raw.substr(start, end - start);
+    return true;
+}
+
+static status_t readMetadata(const std::string& path, std::string* fsType,
+        std::string* fsUuid, std::string* fsLabel, bool untrusted) {
+    fsType->clear();
+    fsUuid->clear();
+    fsLabel->clear();
 
     std::vector<std::string> cmd;
     cmd.push_back(kBlkidPath);
@@ -209,36 +226,23 @@
         return res;
     }
 
-    char value[128];
     for (const auto& line : output) {
         // Extract values from blkid output, if defined
-        const char* cline = line.c_str();
-        const char* start = strstr(cline, "TYPE=");
-        if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
-            fsType = value;
-        }
-
-        start = strstr(cline, "UUID=");
-        if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
-            fsUuid = value;
-        }
-
-        start = strstr(cline, "LABEL=");
-        if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
-            fsLabel = value;
-        }
+        FindValue(line, "TYPE", fsType);
+        FindValue(line, "UUID", fsUuid);
+        FindValue(line, "LABEL", fsLabel);
     }
 
     return OK;
 }
 
-status_t ReadMetadata(const std::string& path, std::string& fsType,
-        std::string& fsUuid, std::string& fsLabel) {
+status_t ReadMetadata(const std::string& path, std::string* fsType,
+        std::string* fsUuid, std::string* fsLabel) {
     return readMetadata(path, fsType, fsUuid, fsLabel, false);
 }
 
-status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType,
-        std::string& fsUuid, std::string& fsLabel) {
+status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType,
+        std::string* fsUuid, std::string* fsLabel) {
     return readMetadata(path, fsType, fsUuid, fsLabel, true);
 }
 
@@ -673,15 +677,27 @@
     return OK;
 }
 
-status_t SaneReadLinkAt(int dirfd, const char* path, char* buf, size_t bufsiz) {
-    ssize_t len = readlinkat(dirfd, path, buf, bufsiz);
-    if (len < 0) {
-        return -1;
-    } else if (len == (ssize_t) bufsiz) {
-        return -1;
-    } else {
-        buf[len] = '\0';
-        return 0;
+bool Readlinkat(int dirfd, const std::string& path, std::string* result) {
+    // Shamelessly borrowed from android::base::Readlink()
+    result->clear();
+
+    // Most Linux file systems (ext2 and ext4, say) limit symbolic links to
+    // 4095 bytes. Since we'll copy out into the string anyway, it doesn't
+    // waste memory to just start there. We add 1 so that we can recognize
+    // whether it actually fit (rather than being truncated to 4095).
+    std::vector<char> buf(4095 + 1);
+    while (true) {
+        ssize_t size = readlinkat(dirfd, path.c_str(), &buf[0], buf.size());
+        // Unrecoverable error?
+        if (size == -1)
+            return false;
+        // It fit! (If size == buf.size(), it may have been truncated.)
+        if (static_cast<size_t>(size) < buf.size()) {
+            result->assign(&buf[0], size);
+            return true;
+        }
+        // Double our buffer and try again.
+        buf.resize(buf.size() * 2);
     }
 }
 
diff --git a/Utils.h b/Utils.h
index 8d09ddf..9163006 100644
--- a/Utils.h
+++ b/Utils.h
@@ -53,13 +53,15 @@
 /* Creates bind mount from source to target */
 status_t BindMount(const std::string& source, const std::string& target);
 
+bool FindValue(const std::string& raw, const std::string& key, std::string* value);
+
 /* Reads filesystem metadata from device at path */
-status_t ReadMetadata(const std::string& path, std::string& fsType,
-        std::string& fsUuid, std::string& fsLabel);
+status_t ReadMetadata(const std::string& path, std::string* fsType,
+        std::string* fsUuid, std::string* fsLabel);
 
 /* Reads filesystem metadata from untrusted device at path */
-status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType,
-        std::string& fsUuid, std::string& fsLabel);
+status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType,
+        std::string* fsUuid, std::string* fsLabel);
 
 /* Returns either WEXITSTATUS() status, or a negative errno */
 status_t ForkExecvp(const std::vector<std::string>& args);
@@ -112,7 +114,8 @@
 
 status_t RestoreconRecursive(const std::string& path);
 
-status_t SaneReadLinkAt(int dirfd, const char* path, char* buf, size_t bufsiz);
+// TODO: promote to android::base
+bool Readlinkat(int dirfd, const std::string& path, std::string* result);
 
 /* Checks if Android is running in QEMU */
 bool IsRunningInEmulator();
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index a900ba1..c82eb92 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -37,10 +37,6 @@
 #include <private/android_filesystem_config.h>
 #include <utils/Trace.h>
 
-#ifndef LOG_TAG
-#define LOG_TAG "vold"
-#endif
-
 using android::base::StringPrintf;
 using std::endl;
 
@@ -423,7 +419,7 @@
     CHECK_ARGUMENT_PATH(path);
     ACQUIRE_LOCK;
 
-    return translate(VolumeManager::Instance()->mkdirs(path.c_str()));
+    return translate(VolumeManager::Instance()->mkdirs(path));
 }
 
 binder::Status VoldNativeService::createObb(const std::string& sourcePath,
@@ -519,7 +515,7 @@
         if (rc == 0) {
             return 0;
         } else if (tries == 0) {
-            Process::killProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL);
+            KillProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL);
         }
     }
 
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index d441297..c1d51d9 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -19,7 +19,6 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <fts.h>
 #include <mntent.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -34,14 +33,11 @@
 
 #include <linux/kdev_t.h>
 
-#define LOG_TAG "Vold"
-
-#include <openssl/md5.h>
-
 #include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 #include <cutils/fs.h>
-#include <cutils/log.h>
 #include <utils/Trace.h>
 
 #include <selinux/android.h>
@@ -98,7 +94,7 @@
 
 int VolumeManager::updateVirtualDisk() {
     ATRACE_NAME("VolumeManager::updateVirtualDisk");
-    if (property_get_bool(kPropVirtualDisk, false)) {
+    if (android::base::GetBoolProperty(kPropVirtualDisk, false)) {
         if (access(kPathVirtualDisk, F_OK) != 0) {
             Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512);
         }
@@ -323,13 +319,12 @@
     std::string target(StringPrintf("/mnt/user/%d/primary", userId));
     if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) {
         if (errno != ENOENT) {
-            SLOGW("Failed to unlink %s: %s", target.c_str(), strerror(errno));
+            PLOG(WARNING) << "Failed to unlink " << target;
         }
     }
     LOG(DEBUG) << "Linking " << source << " to " << target;
     if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) {
-        SLOGW("Failed to link %s to %s: %s", source.c_str(), target.c_str(),
-                strerror(errno));
+        PLOG(WARNING) << "Failed to link";
         return -errno;
     }
     return 0;
@@ -372,12 +367,10 @@
     return 0;
 }
 
-static int unmount_tree(const char* path) {
-    size_t path_len = strlen(path);
-
+static int unmount_tree(const std::string& prefix) {
     FILE* fp = setmntent("/proc/mounts", "r");
     if (fp == NULL) {
-        ALOGE("Error opening /proc/mounts: %s", strerror(errno));
+        PLOG(ERROR) << "Failed to open /proc/mounts";
         return -errno;
     }
 
@@ -386,15 +379,16 @@
     std::list<std::string> toUnmount;
     mntent* mentry;
     while ((mentry = getmntent(fp)) != NULL) {
-        if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
-            toUnmount.push_front(std::string(mentry->mnt_dir));
+        auto test = std::string(mentry->mnt_dir) + "/";
+        if (android::base::StartsWith(test, prefix.c_str())) {
+            toUnmount.push_front(test);
         }
     }
     endmntent(fp);
 
     for (const auto& path : toUnmount) {
         if (umount2(path.c_str(), MNT_DETACH)) {
-            ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
+            PLOG(ERROR) << "Failed to unmount " << path;
         }
     }
     return 0;
@@ -405,8 +399,8 @@
 
     DIR* dir;
     struct dirent* de;
-    char rootName[PATH_MAX];
-    char pidName[PATH_MAX];
+    std::string rootName;
+    std::string pidName;
     int pidFd;
     int nsFd;
     struct stat sb;
@@ -418,8 +412,8 @@
     }
 
     // Figure out root namespace to compare against below
-    if (android::vold::SaneReadLinkAt(dirfd(dir), "1/ns/mnt", rootName, PATH_MAX) == -1) {
-        PLOG(ERROR) << "Failed to readlink";
+    if (!android::vold::Readlinkat(dirfd(dir), "1/ns/mnt", &rootName)) {
+        PLOG(ERROR) << "Failed to read root namespace";
         closedir(dir);
         return -1;
     }
@@ -443,11 +437,11 @@
 
         // Matches so far, but refuse to touch if in root namespace
         LOG(DEBUG) << "Found matching PID " << de->d_name;
-        if (android::vold::SaneReadLinkAt(pidFd, "ns/mnt", pidName, PATH_MAX) == -1) {
+        if (!android::vold::Readlinkat(pidFd, "ns/mnt", &pidName)) {
             PLOG(WARNING) << "Failed to read namespace for " << de->d_name;
             goto next;
         }
-        if (!strcmp(rootName, pidName)) {
+        if (rootName == pidName) {
             LOG(WARNING) << "Skipping due to root namespace";
             goto next;
         }
@@ -465,7 +459,7 @@
                 _exit(1);
             }
 
-            unmount_tree("/storage");
+            unmount_tree("/storage/");
 
             std::string storageSource;
             if (mode == "default") {
@@ -568,7 +562,7 @@
     // force unmount those just to be safe.
     FILE* fp = setmntent("/proc/mounts", "r");
     if (fp == NULL) {
-        SLOGE("Error opening /proc/mounts: %s", strerror(errno));
+        PLOG(ERROR) << "Failed to open /proc/mounts";
         return -errno;
     }
 
@@ -577,9 +571,10 @@
     std::list<std::string> toUnmount;
     mntent* mentry;
     while ((mentry = getmntent(fp)) != NULL) {
-        if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0
-                || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) {
-            toUnmount.push_front(std::string(mentry->mnt_dir));
+        auto test = std::string(mentry->mnt_dir);
+        if (android::base::StartsWith(test, "/mnt/")
+                || android::base::StartsWith(test, "/storage/")) {
+            toUnmount.push_front(test);
         }
     }
     endmntent(fp);
@@ -597,13 +592,13 @@
     return vm->unmountAll();
 }
 
-int VolumeManager::mkdirs(const char* path) {
+int VolumeManager::mkdirs(const std::string& path) {
     // Only offer to create directories for paths managed by vold
-    if (strncmp(path, "/storage/", 9) == 0) {
+    if (android::base::StartsWith(path, "/storage/")) {
         // fs_mkdirs() does symlink checking and relative path enforcement
-        return fs_mkdirs(path, 0700);
+        return fs_mkdirs(path.c_str(), 0700);
     } else {
-        SLOGE("Failed to find mounted volume for %s", path);
+        LOG(ERROR) << "Failed to find mounted volume for " << path;
         return -EINVAL;
     }
 }
@@ -694,21 +689,14 @@
 
     // Matches so far, but refuse to touch if in root namespace
     {
-        char rootName[PATH_MAX];
-        char pidName[PATH_MAX];
-        const int root_result =
-                android::vold::SaneReadLinkAt(dir.get(), "1/ns/mnt", rootName, PATH_MAX);
-        const int pid_result =
-                android::vold::SaneReadLinkAt(pid_fd.get(), "ns/mnt", pidName, PATH_MAX);
-        if (root_result == -1) {
-            LOG(ERROR) << "Failed to readlink for /proc/1/ns/mnt";
+        std::string rootName;
+        std::string pidName;
+        if (!android::vold::Readlinkat(dir.get(), "1/ns/mnt", &rootName)
+                || !android::vold::Readlinkat(pid_fd.get(), "ns/mnt", &pidName)) {
+            PLOG(ERROR) << "Failed to read namespaces";
             return -EPERM;
         }
-        if (pid_result == -1) {
-            LOG(ERROR) << "Failed to readlink for /proc/" << pid << "/ns/mnt";
-            return -EPERM;
-        }
-        if (!strcmp(rootName, pidName)) {
+        if (rootName == pidName) {
             LOG(ERROR) << "Don't mount appfuse in root namespace";
             return -EPERM;
         }
diff --git a/VolumeManager.h b/VolumeManager.h
index dcfbdad..4f62de9 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -123,7 +123,7 @@
      * is treated as filename and ignored, unless the path ends with "/".  Also
      * ensures that path belongs to a volume managed by vold.
      */
-    int mkdirs(const char* path);
+    int mkdirs(const std::string& path);
 
     int createObb(const std::string& path, const std::string& key, int32_t ownerGid,
             std::string* outVolId);
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 08a3d16..ae9b0af 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -1277,10 +1277,10 @@
         if (kill) {
             if (i == (WAIT_UNMOUNT_COUNT - 3)) {
                 SLOGW("sending SIGHUP to processes with open files\n");
-                vold_killProcessesWithOpenFiles(mountpoint, SIGTERM);
+                android::vold::KillProcessesWithOpenFiles(mountpoint, SIGTERM);
             } else if (i == (WAIT_UNMOUNT_COUNT - 2)) {
                 SLOGW("sending SIGKILL to processes with open files\n");
-                vold_killProcessesWithOpenFiles(mountpoint, SIGKILL);
+                android::vold::KillProcessesWithOpenFiles(mountpoint, SIGKILL);
             }
         }
 
@@ -1291,7 +1291,7 @@
       SLOGD("unmounting %s succeeded\n", mountpoint);
       rc = 0;
     } else {
-      vold_killProcessesWithOpenFiles(mountpoint, 0);
+      android::vold::KillProcessesWithOpenFiles(mountpoint, 0);
       SLOGE("unmounting %s failed: %s\n", mountpoint, strerror(err));
       rc = -1;
     }
diff --git a/fs/Ext4.cpp b/fs/Ext4.cpp
index 1898155..89b8414 100644
--- a/fs/Ext4.cpp
+++ b/fs/Ext4.cpp
@@ -146,7 +146,7 @@
     rc = mount(c_source, c_target, "ext4", flags, NULL);
 
     if (rc && errno == EROFS) {
-        SLOGE("%s appears to be a read only filesystem - retrying mount RO", c_source);
+        LOG(ERROR) << source << " appears to be a read only filesystem - retrying mount RO";
         flags |= MS_RDONLY;
         rc = mount(c_source, c_target, "ext4", flags, NULL);
     }
diff --git a/fs/Vfat.cpp b/fs/Vfat.cpp
index dc1fe33..538178e 100644
--- a/fs/Vfat.cpp
+++ b/fs/Vfat.cpp
@@ -35,12 +35,8 @@
 
 #include <linux/kdev_t.h>
 
-#define LOG_TAG "Vold"
-
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
 #include <selinux/selinux.h>
 
 #include <logwrap/logwrap.h>
@@ -65,11 +61,6 @@
 }
 
 status_t Check(const std::string& source) {
-    if (access(kFsckPath, X_OK)) {
-        SLOGW("Skipping fs checks\n");
-        return 0;
-    }
-
     int pass = 1;
     int rc = 0;
     do {
@@ -83,38 +74,37 @@
         rc = ForkExecvp(cmd, sFsckUntrustedContext);
 
         if (rc < 0) {
-            SLOGE("Filesystem check failed due to logwrap error");
+            LOG(ERROR) << "Filesystem check failed due to logwrap error";
             errno = EIO;
             return -1;
         }
 
         switch(rc) {
         case 0:
-            SLOGI("Filesystem check completed OK");
+            LOG(INFO) << "Filesystem check completed OK";
             return 0;
 
         case 2:
-            SLOGE("Filesystem check failed (not a FAT filesystem)");
+            LOG(ERROR) << "Filesystem check failed (not a FAT filesystem)";
             errno = ENODATA;
             return -1;
 
         case 4:
             if (pass++ <= 3) {
-                SLOGW("Filesystem modified - rechecking (pass %d)",
-                        pass);
+                LOG(WARNING) << "Filesystem modified - rechecking (pass " << pass << ")";
                 continue;
             }
-            SLOGE("Failing check after too many rechecks");
+            LOG(ERROR) << "Failing check after too many rechecks";
             errno = EIO;
             return -1;
 
         case 8:
-            SLOGE("Filesystem check failed (no filesystem)");
+            LOG(ERROR) << "Filesystem check failed (no filesystem)";
             errno = ENODATA;
             return -1;
 
         default:
-            SLOGE("Filesystem check failed (unknown exit code %d)", rc);
+            LOG(ERROR) << "Filesystem check failed (unknown exit code " << rc << ")";
             errno = EIO;
             return -1;
         }
@@ -128,7 +118,6 @@
         bool createLost) {
     int rc;
     unsigned long flags;
-    char mountData[255];
 
     const char* c_source = source.c_str();
     const char* c_target = target.c_str();
@@ -139,31 +128,29 @@
     flags |= (ro ? MS_RDONLY : 0);
     flags |= (remount ? MS_REMOUNT : 0);
 
-    snprintf(mountData, sizeof(mountData),
+    auto mountData = android::base::StringPrintf(
             "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
             ownerUid, ownerGid, permMask, permMask);
 
-    rc = mount(c_source, c_target, "vfat", flags, mountData);
+    rc = mount(c_source, c_target, "vfat", flags, mountData.c_str());
 
     if (rc && errno == EROFS) {
-        SLOGE("%s appears to be a read only filesystem - retrying mount RO", c_source);
+        LOG(ERROR) << source << " appears to be a read only filesystem - retrying mount RO";
         flags |= MS_RDONLY;
-        rc = mount(c_source, c_target, "vfat", flags, mountData);
+        rc = mount(c_source, c_target, "vfat", flags, mountData.c_str());
     }
 
     if (rc == 0 && createLost) {
-        char *lost_path;
-        asprintf(&lost_path, "%s/LOST.DIR", c_target);
-        if (access(lost_path, F_OK)) {
+        auto lost_path = android::base::StringPrintf("%s/LOST.DIR", target.c_str());
+        if (access(lost_path.c_str(), F_OK)) {
             /*
              * Create a LOST.DIR in the root so we have somewhere to put
              * lost cluster chains (fsck_msdos doesn't currently do this)
              */
-            if (mkdir(lost_path, 0755)) {
-                SLOGE("Unable to create LOST.DIR (%s)", strerror(errno));
+            if (mkdir(lost_path.c_str(), 0755)) {
+                PLOG(ERROR) << "Unable to create LOST.DIR";
             }
         }
-        free(lost_path);
     }
 
     return rc;
@@ -189,16 +176,16 @@
 
     int rc = ForkExecvp(cmd);
     if (rc < 0) {
-        SLOGE("Filesystem format failed due to logwrap error");
+        LOG(ERROR) << "Filesystem format failed due to logwrap error";
         errno = EIO;
         return -1;
     }
 
     if (rc == 0) {
-        SLOGI("Filesystem formatted OK");
+        LOG(INFO) << "Filesystem formatted OK";
         return 0;
     } else {
-        SLOGE("Format failed (unknown exit code %d)", rc);
+        LOG(ERROR) << "Format failed (unknown exit code " << rc << ")";
         errno = EIO;
         return -1;
     }
diff --git a/main.cpp b/main.cpp
index 30f60a1..cca738e 100644
--- a/main.cpp
+++ b/main.cpp
@@ -25,9 +25,9 @@
 #include "sehandle.h"
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <cutils/klog.h>
-#include <cutils/properties.h>
 #include <utils/Trace.h>
 
 #include <stdio.h>
@@ -88,7 +88,7 @@
         exit(1);
     }
 
-    if (property_get_bool("vold.debug", false)) {
+    if (android::base::GetBoolProperty("vold.debug", false)) {
         vm->setDebug(true);
     }
 
@@ -120,8 +120,8 @@
 
     // This call should go after listeners are started to avoid
     // a deadlock between vold and init (see b/34278978 for details)
-    property_set("vold.has_adoptable", has_adoptable ? "1" : "0");
-    property_set("vold.has_quota", has_quota ? "1" : "0");
+    android::base::SetProperty("vold.has_adoptable", has_adoptable ? "1" : "0");
+    android::base::SetProperty("vold.has_quota", has_quota ? "1" : "0");
 
     // Do coldboot here so it won't block booting,
     // also the cold boot is needed in case we have flash drive
@@ -240,7 +240,7 @@
                 *has_adoptable = true;
             }
             if (fs_mgr_is_noemulatedsd(rec)
-                    || property_get_bool("vold.debug.default_primary", false)) {
+                    || android::base::GetBoolProperty("vold.debug.default_primary", false)) {
                 flags |= android::vold::Disk::Flags::kDefaultPrimary;
             }
 
diff --git a/model/Disk.cpp b/model/Disk.cpp
index 5b0c981..291c2e1 100644
--- a/model/Disk.cpp
+++ b/model/Disk.cpp
@@ -26,6 +26,8 @@
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/parseint.h>
 #include <diskconfig/diskconfig.h>
 #include <ext4_utils/ext4_crypt.h>
 
@@ -263,7 +265,11 @@
             PLOG(WARNING) << "Failed to read manufacturer from " << path;
             return -errno;
         }
-        uint64_t manfid = strtoll(tmp.c_str(), nullptr, 16);
+        int64_t manfid;
+        if (!android::base::ParseInt(tmp, &manfid)) {
+            PLOG(WARNING) << "Failed to parse manufacturer " << tmp;
+            return -EINVAL;
+        }
         // Our goal here is to give the user a meaningful label, ideally
         // matching whatever is silk-screened on the card.  To reduce
         // user confusion, this list doesn't contain white-label manfid.
@@ -295,7 +301,7 @@
 }
 
 status_t Disk::readPartitions() {
-    int8_t maxMinors = getMaxMinors();
+    int maxMinors = getMaxMinors();
     if (maxMinors < 0) {
         return -ENOTSUP;
     }
@@ -324,31 +330,40 @@
     Table table = Table::kUnknown;
     bool foundParts = false;
     for (const auto& line : output) {
-        char* cline = (char*) line.c_str();
-        char* token = strtok(cline, kSgdiskToken);
-        if (token == nullptr) continue;
+        auto split = android::base::Split(line, kSgdiskToken);
+        auto it = split.begin();
+        if (it == split.end()) continue;
 
-        if (!strcmp(token, "DISK")) {
-            const char* type = strtok(nullptr, kSgdiskToken);
-            if (!strcmp(type, "mbr")) {
+        if (*it == "DISK") {
+            if (++it == split.end()) continue;
+            if (*it == "mbr") {
                 table = Table::kMbr;
-            } else if (!strcmp(type, "gpt")) {
+            } else if (*it == "gpt") {
                 table = Table::kGpt;
+            } else {
+                LOG(WARNING) << "Invalid partition table " << *it;
+                continue;
             }
-        } else if (!strcmp(token, "PART")) {
+        } else if (*it == "PART") {
             foundParts = true;
-            int i = strtol(strtok(nullptr, kSgdiskToken), nullptr, 10);
-            if (i <= 0 || i > maxMinors) {
-                LOG(WARNING) << mId << " is ignoring partition " << i
-                        << " beyond max supported devices";
+
+            if (++it == split.end()) continue;
+            int i = 0;
+            if (!android::base::ParseInt(*it, &i, 1, maxMinors)) {
+                LOG(WARNING) << "Invalid partition number " << *it;
                 continue;
             }
             dev_t partDevice = makedev(major(mDevice), minor(mDevice) + i);
 
             if (table == Table::kMbr) {
-                const char* type = strtok(nullptr, kSgdiskToken);
+                if (++it == split.end()) continue;
+                int type = 0;
+                if (!android::base::ParseInt("0x" + *it, &type)) {
+                    LOG(WARNING) << "Invalid partition type " << *it;
+                    continue;
+                }
 
-                switch (strtol(type, nullptr, 16)) {
+                switch (type) {
                 case 0x06: // FAT16
                 case 0x0b: // W95 FAT32 (LBA)
                 case 0x0c: // W95 FAT32 (LBA)
@@ -357,12 +372,14 @@
                     break;
                 }
             } else if (table == Table::kGpt) {
-                const char* typeGuid = strtok(nullptr, kSgdiskToken);
-                const char* partGuid = strtok(nullptr, kSgdiskToken);
+                if (++it == split.end()) continue;
+                auto typeGuid = *it;
+                if (++it == split.end()) continue;
+                auto partGuid = *it;
 
-                if (!strcasecmp(typeGuid, kGptBasicData)) {
+                if (android::base::EqualsIgnoreCase(typeGuid, kGptBasicData)) {
                     createPublicVolume(partDevice);
-                } else if (!strcasecmp(typeGuid, kGptAndroidExpand)) {
+                } else if (android::base::EqualsIgnoreCase(typeGuid, kGptAndroidExpand)) {
                     createPrivateVolume(partDevice, partGuid);
                 }
             }
@@ -375,7 +392,7 @@
 
         std::string fsType;
         std::string unused;
-        if (ReadMetadataUntrusted(mDevPath, fsType, unused, unused) == OK) {
+        if (ReadMetadataUntrusted(mDevPath, &fsType, &unused, &unused) == OK) {
             createPublicVolume(mDevice);
         } else {
             LOG(WARNING) << mId << " failed to identify, giving up";
diff --git a/model/PrivateVolume.cpp b/model/PrivateVolume.cpp
index 3152313..48d041b 100644
--- a/model/PrivateVolume.cpp
+++ b/model/PrivateVolume.cpp
@@ -53,7 +53,7 @@
 }
 
 status_t PrivateVolume::readMetadata() {
-    status_t res = ReadMetadata(mDmDevPath, mFsType, mFsUuid, mFsLabel);
+    status_t res = ReadMetadata(mDmDevPath, &mFsType, &mFsUuid, &mFsLabel);
 
     auto listener = getListener();
     if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index f80f59e..98c897f 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -52,7 +52,7 @@
 }
 
 status_t PublicVolume::readMetadata() {
-    status_t res = ReadMetadataUntrusted(mDevPath, mFsType, mFsUuid, mFsLabel);
+    status_t res = ReadMetadataUntrusted(mDevPath, &mFsType, &mFsUuid, &mFsLabel);
 
     auto listener = getListener();
     if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
diff --git a/tests/Android.mk b/tests/Android.mk
index 3127352..8f2cda7 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -12,6 +12,7 @@
 
 LOCAL_SRC_FILES := \
 	cryptfs_test.cpp \
+	Utils_test.cpp \
 	VolumeManager_test.cpp \
 
 LOCAL_MODULE := vold_tests
diff --git a/tests/Utils_test.cpp b/tests/Utils_test.cpp
new file mode 100644
index 0000000..ab9809e
--- /dev/null
+++ b/tests/Utils_test.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "../Utils.h"
+
+namespace android {
+namespace vold {
+
+class UtilsTest : public testing::Test {
+};
+
+TEST_F(UtilsTest, FindValueTest) {
+    std::string tmp;
+
+    ASSERT_FALSE(FindValue("", "KEY", &tmp));
+    ASSERT_FALSE(FindValue("BADKEY=\"VALUE\"", "KEY", &tmp));
+
+    ASSERT_TRUE(FindValue("KEY=\"VALUE\"", "KEY", &tmp));
+    ASSERT_EQ("VALUE", tmp);
+
+    ASSERT_TRUE(FindValue("FOO=\"BAR\" KEY=\"VALUE VALUE\" BAR=\"BAZ\"", "KEY", &tmp));
+    ASSERT_EQ("VALUE VALUE", tmp);
+
+    ASSERT_TRUE(FindValue("BADKEY=\"VALUE\" KEY=\"BAZ\"", "KEY", &tmp));
+    ASSERT_EQ("BAZ", tmp);
+}
+
+}
+}