Merge "libdm: Implement GetDmDevicePathByName()."
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 8bd3b9d..b96f4c1 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -17,6 +17,7 @@
 #include "libdm/dm.h"
 
 #include <sys/ioctl.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 
 #include <android-base/macros.h>
@@ -258,8 +259,17 @@
 
 // Accepts a device mapper device name (like system_a, vendor_b etc) and
 // returns the path to it's device node (or symlink to the device node)
-std::string DeviceMapper::GetDmDevicePathByName(const std::string& /* name */) {
-    return "";
+bool DeviceMapper::GetDmDevicePathByName(const std::string& name, std::string* path) {
+    struct dm_ioctl io;
+    InitIo(&io, name);
+    if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) {
+        PLOG(ERROR) << "DM_DEV_STATUS failed for " << name;
+        return false;
+    }
+
+    uint32_t dev_num = minor(io.dev);
+    *path = "/dev/block/dm-" + std::to_string(dev_num);
+    return true;
 }
 
 // private methods of DeviceMapper
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 8d23b2c..60bceed 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -104,8 +104,9 @@
     bool GetAvailableDevices(std::vector<DmBlockDevice>* devices);
 
     // Returns the path to the device mapper device node in '/dev' corresponding to
-    // 'name'.
-    std::string GetDmDevicePathByName(const std::string& name);
+    // 'name'. If the device does not exist, false is returned, and the path
+    // parameter is not set.
+    bool GetDmDevicePathByName(const std::string& name, std::string* path);
 
     // The only way to create a DeviceMapper object.
     static DeviceMapper& Instance();
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index c15173f..9d48b8c 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -49,6 +49,7 @@
     std::cerr << "  create <dm-name> [-ro] <targets...>" << std::endl;
     std::cerr << "  delete <dm-name>" << std::endl;
     std::cerr << "  list <devices | targets>" << std::endl;
+    std::cerr << "  getpath <dm-name>" << std::endl;
     std::cerr << "  help" << std::endl;
     std::cerr << std::endl;
     std::cerr << "Target syntax:" << std::endl;
@@ -241,11 +242,30 @@
     return 0;
 }
 
+static int GetPathCmdHandler(int argc, char** argv) {
+    if (argc != 1) {
+        std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl;
+        return -EINVAL;
+    }
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    std::string path;
+    if (!dm.GetDmDevicePathByName(argv[0], &path)) {
+        std::cerr << "Could not query path of device \"" << argv[0] << "\"." << std::endl;
+        return -EINVAL;
+    }
+    std::cout << path << std::endl;
+    return 0;
+}
+
 static std::map<std::string, std::function<int(int, char**)>> cmdmap = {
+        // clang-format off
         {"create", DmCreateCmdHandler},
         {"delete", DmDeleteCmdHandler},
         {"list", DmListCmdHandler},
         {"help", HelpCmdHandler},
+        {"getpath", GetPathCmdHandler},
+        // clang-format on
 };
 
 int main(int argc, char** argv) {