Merge "Add allow_other mount option for appfuse."
diff --git a/Android.mk b/Android.mk
index d83e650..4ab719f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -126,7 +126,7 @@
 LOCAL_CLANG := true
 LOCAL_SRC_FILES:= secdiscard.cpp
 LOCAL_MODULE:= secdiscard
-LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SHARED_LIBRARIES := libbase
 LOCAL_CFLAGS := $(vold_cflags)
 LOCAL_CONLYFLAGS := $(vold_conlyflags)
 
diff --git a/AutoCloseFD.h b/AutoCloseFD.h
index f9d7c86..9b68469 100644
--- a/AutoCloseFD.h
+++ b/AutoCloseFD.h
@@ -21,6 +21,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <android-base/logging.h>
+
 // File descriptor which is automatically closed when this object is destroyed.
 // Cannot be copied, since that would cause double-closes.
 class AutoCloseFD {
@@ -33,7 +35,7 @@
         if (fd != -1) {
             int preserve_errno = errno;
             if (close(fd) == -1) {
-                SLOGE("close(2) failed: %s", strerror(errno));
+                PLOG(ERROR) << "close(2) failed";
             };
             errno = preserve_errno;
         }
diff --git a/CommandListener.cpp b/CommandListener.cpp
index ac166c2..edbb776 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -626,6 +626,18 @@
 
 static size_t kAppFuseMaxMountPointName = 32;
 
+static bool isValidAppFuseMountName(const std::string& name) {
+    if (name.size() > kAppFuseMaxMountPointName) {
+        return false;
+    }
+    for (size_t i = 0; i < name.size(); i++) {
+        if (!isalnum(name[i])) {
+            return false;
+        }
+    }
+    return true;
+}
+
 CommandListener::AppFuseCmd::AppFuseCmd() : VoldCommand("appfuse") {}
 
 int CommandListener::AppFuseCmd::runCommand(SocketClient *cli,
@@ -644,17 +656,7 @@
         const std::string name(argv[3]);
 
         // Check mount point name.
-        bool invalidName = false;
-        if (name.size() > kAppFuseMaxMountPointName) {
-            invalidName = true;
-        }
-        for (size_t i = 0; i < name.size(); i++) {
-            if (!isalnum(name[i])) {
-                invalidName = true;
-                break;
-            }
-        }
-        if (invalidName) {
+        if (!isValidAppFuseMountName(name)) {
             return cli->sendMsg(
                     ResponseCode::CommandParameterError,
                     "Invalid mount point name.",
@@ -707,6 +709,24 @@
         const int result = sendFd(cli, device_fd);
         close(device_fd);
         return result;
+    } else if (command == "unmount" && argc == 4) {
+        const uid_t uid = atoi(argv[2]);
+        const std::string name(argv[3]);
+
+        // Check mount point name.
+        if (!isValidAppFuseMountName(name)) {
+            return cli->sendMsg(
+                    ResponseCode::CommandParameterError,
+                    "Invalid mount point name.",
+                    false);
+        }
+
+        // Unmount directory.
+        char path[PATH_MAX];
+        snprintf(path, PATH_MAX, "/mnt/appfuse/%d_%s", uid, name.c_str());
+        umount2(path, UMOUNT_NOFOLLOW | MNT_DETACH);
+
+        return sendGenericOkFail(cli, /* success */ 0);
     }
 
     return cli->sendMsg(
diff --git a/cryptfs.c b/cryptfs.c
index b0aafc2..3aa3403 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -2428,7 +2428,8 @@
         data->count = 0;
 
         for (block = 0; block < block_count; block++) {
-            int used = bitmap_get_bit(block_bitmap, block);
+            int used = (aux_info.bg_desc[i].bg_flags & EXT4_BG_BLOCK_UNINIT) ?
+                    0 : bitmap_get_bit(block_bitmap, block);
             update_progress(data, used);
             if (used) {
                 if (data->count == 0) {
diff --git a/secdiscard.cpp b/secdiscard.cpp
index f7adb0d..5c12cdd 100644
--- a/secdiscard.cpp
+++ b/secdiscard.cpp
@@ -28,8 +28,7 @@
 #include <linux/fiemap.h>
 #include <mntent.h>
 
-#define LOG_TAG "secdiscard"
-#include "cutils/log.h"
+#include <android-base/logging.h>
 
 #include <AutoCloseFD.h>
 
@@ -53,21 +52,21 @@
 }
 
 int main(int argc, const char * const argv[]) {
+    android::base::InitLogging(const_cast<char **>(argv));
     Options options;
     if (!read_command_line(argc, argv, options)) {
         usage(argv[0]);
         return -1;
     }
     for (auto target: options.targets) {
-        SLOGD("Securely discarding '%s' unlink=%d", target.c_str(), options.unlink);
+        LOG(DEBUG) << "Securely discarding '" << target << "' unlink=" << options.unlink;
         secdiscard_path(target);
         if (options.unlink) {
             if (unlink(target.c_str()) != 0 && errno != ENOENT) {
-                SLOGE("Unable to unlink %s: %s",
-                    target.c_str(), strerror(errno));
+                PLOG(ERROR) << "Unable to unlink: " << target;
             }
         }
-        SLOGD("Discarded %s", target.c_str());
+        LOG(DEBUG) << "Discarded: " << target;
     }
     return 0;
 }
@@ -107,7 +106,7 @@
     }
     AutoCloseFD fs_fd(block_device, O_RDWR | O_LARGEFILE);
     if (!fs_fd) {
-        SLOGE("Failed to open device %s: %s", block_device.c_str(), strerror(errno));
+        PLOG(ERROR) << "Failed to open device " << block_device;
         return -1;
     }
     for (uint32_t i = 0; i < fiemap->fm_mapped_extents; i++) {
@@ -115,7 +114,7 @@
         range[0] = fiemap->fm_extents[i].fe_physical;
         range[1] = fiemap->fm_extents[i].fe_length;
         if (ioctl(fs_fd.get(), BLKSECDISCARD, range) == -1) {
-            SLOGE("Unable to BLKSECDISCARD %s: %s", path.c_str(), strerror(errno));
+            PLOG(ERROR) << "Unable to BLKSECDISCARD " << path;
             return -1;
         }
     }
@@ -128,20 +127,21 @@
     AutoCloseFD fd(path);
     if (!fd) {
         if (errno == ENOENT) {
-            SLOGD("Unable to open %s: %s", path.c_str(), strerror(errno));
+            PLOG(DEBUG) << "Unable to open " << path;
         } else {
-            SLOGE("Unable to open %s: %s", path.c_str(), strerror(errno));
+            PLOG(ERROR) << "Unable to open " << path;
         }
         return nullptr;
     }
     auto fiemap = alloc_fiemap(extent_count);
     if (ioctl(fd.get(), FS_IOC_FIEMAP, fiemap.get()) != 0) {
-        SLOGE("Unable to FIEMAP %s: %s", path.c_str(), strerror(errno));
+        PLOG(ERROR) << "Unable to FIEMAP " << path;
         return nullptr;
     }
     auto mapped = fiemap->fm_mapped_extents;
     if (mapped < 1 || mapped > extent_count) {
-        SLOGE("Extent count not in bounds 1 <= %u <= %u in %s", mapped, extent_count, path.c_str());
+        LOG(ERROR) << "Extent count not in bounds 1 <= " << mapped << " <= " << extent_count
+            << " in " << path;
         return nullptr;
     }
     return fiemap;
@@ -151,13 +151,13 @@
 bool check_fiemap(const struct fiemap &fiemap, const std::string &path) {
     auto mapped = fiemap.fm_mapped_extents;
     if (!(fiemap.fm_extents[mapped - 1].fe_flags & FIEMAP_EXTENT_LAST)) {
-        SLOGE("Extent %u was not the last in %s", mapped - 1, path.c_str());
+        LOG(ERROR) << "Extent " << mapped -1 << " was not the last in " << path;
         return false;
     }
     for (uint32_t i = 0; i < mapped; i++) {
         auto flags = fiemap.fm_extents[i].fe_flags;
         if (flags & (FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_NOT_ALIGNED)) {
-            SLOGE("Extent %u has unexpected flags %ulx: %s", i, flags, path.c_str());
+            LOG(ERROR) << "Extent " << i << " has unexpected flags " << flags << ": " << path;
             return false;
         }
     }
@@ -182,7 +182,7 @@
 {
     std::unique_ptr<FILE, int(*)(FILE*)> mnts(setmntent("/proc/mounts", "re"), endmntent);
     if (!mnts) {
-        SLOGE("Unable to open /proc/mounts: %s", strerror(errno));
+        PLOG(ERROR) << "Unable to open /proc/mounts";
         return "";
     }
     std::string result;
@@ -199,10 +199,10 @@
         }
     }
     if (result.empty()) {
-        SLOGE("Didn't find a mountpoint to match path %s", path.c_str());
+        LOG(ERROR) <<"Didn't find a mountpoint to match path " << path;
         return "";
     }
-    SLOGD("For path %s block device is %s", path.c_str(), result.c_str());
+    LOG(DEBUG) << "For path " << path << " block device is " << result;
     return result;
 }