Add support for synchronous LUKS API to ode-admin-cli 81/156881/4
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Mon, 23 Oct 2017 14:01:37 +0000 (16:01 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Mon, 23 Oct 2017 14:05:03 +0000 (16:05 +0200)
Change-Id: I86efa9e434b3726fb7947a4e81f048908a5b9ac3

tools/cli/ode-admin-cli.cpp

index a6565c2..424d78c 100644 (file)
@@ -28,6 +28,7 @@
 #include <vector>
 #include <iostream>
 #include <condition_variable>
+#include <stdexcept>
 
 #include <ode/secure-erase.h>
 #include <ode/internal-encryption.h>
@@ -41,18 +42,24 @@ static inline int usage(const std::string name)
        std::cout << "Usage: " << name << " [Option]" << std::endl
                          << std::endl
                          << "Options :" << std::endl
-                         << "   -m, --mount=internal|external              mount" << std::endl
-                         << "   -u, --umount=internal|external             umount" << std::endl
-                         << "   -e, --encrypt=internal|external            encrypt" << std::endl
-                         << "   -d, --decrypt=internal|external            decrypt" << std::endl
-                         << "   -l  --luks=format|open|close|wait          perform LUKS operation or wait for completion. May  also require -D and/or -M option." << std::endl
-                         << "   -D  --device=<device>                      device path required for LUKS format and LUKS open operations" << std::endl
-                         << "   -M  --mapping=<mapping>                    mapping name required for LUKS open and LUKS close operations" << std::endl
-                         << "   -p, --changepw=internal|external           change password" << std::endl
-                         << "   -s, --state=internal|external              get state" << std::endl
-                         << "   -w, --waitmnt=internal|external            wait for mount"<< std::endl
-                         << "   -c, --clean=DIRECTORY                      secure-clean" << std::endl
-                         << "   -h, --help                                 show this" << std::endl
+                         << "  -m, --mount=internal|external      mount" << std::endl
+                         << "  -u, --umount=internal|external     umount" << std::endl
+                         << "  -e, --encrypt=internal|external    encrypt" << std::endl
+                         << "  -d, --decrypt=internal|external    decrypt" << std::endl
+                         << "  -l  --luks=format|open|close|wait  perform LUKS operation using asynchronous" << std::endl
+                         << "                                     API or wait for completion. May also" << std::endl
+                         << "                                     require -D and/or -M option." << std::endl
+                         << "  -L  --luks_sync=format|open|close  perform LUKS operation using synchronous" << std::endl
+                         << "                                     API. May also require -D and/or -M option." << std::endl
+                         << "  -D  --device=<device>              device path required for LUKS format and" << std::endl
+                         << "                                     LUKS open operations" << std::endl
+                         << "  -M  --mapping=<mapping>            mapping name required for LUKS open and" << std::endl
+                         << "                                     LUKS close operations" << std::endl
+                         << "  -p, --changepw=internal|external   change password" << std::endl
+                         << "  -s, --state=internal|external      get state" << std::endl
+                         << "  -w, --waitmnt=internal|external    wait for mount"<< std::endl
+                         << "  -c, --clean=DIRECTORY              secure-clean" << std::endl
+                         << "  -h, --help                         show this" << std::endl
                          << std::endl;
 
        return -1;
@@ -266,11 +273,96 @@ static inline int decrypt_storage(const std::string name)
        return ret;
 }
 
-class LuksListener {
+class LuksWrapper {
 public:
+       explicit LuksWrapper(bool sync) : synchronous(sync) {
+               if (synchronous)
+                       return;
+
+               int ret = ode_luks_set_event_cb(&LuksWrapper::StaticCallback, this);
+               if (ret != ODE_ERROR_NONE)
+                       throw std::runtime_error("Callback setting failed " + ret);
+       }
+
+       int format(const std::string& device)
+       {
+               std::cout << "New ";
+               std::string password = getPassword();
+
+               std::cout << "Confirm ";
+               std::string password2 = getPassword();
+               if (password != password2) {
+                       std::cerr << "Confirm password doesn't match" << std::endl;
+                       return -1;
+               }
+
+               int ret;
+               if (synchronous)
+                       ret = ode_luks_format_sync(device.c_str(), password.c_str());
+               else
+                       ret = ode_luks_format(device.c_str(), password.c_str());
+
+               if (ret != ODE_ERROR_NONE) {
+                       std::cerr << "ode_luks_format() failed " << ret << std::endl;
+                       return ret;
+               }
+               if (synchronous)
+                       return ret;
+
+               return WaitForCallback(ODE_LUKS_FORMAT);
+       }
+
+       int open(const std::string& device, const std::string& mapping)
+       {
+               std::string password = getPassword();
+               int ret;
+               if (synchronous)
+                       ret = ode_luks_open_sync(device.c_str(), password.c_str(), mapping.c_str());
+               else
+                       ret = ode_luks_open(device.c_str(), password.c_str(), mapping.c_str());
+
+               if (ret != ODE_ERROR_NONE) {
+                       std::cerr << "ode_luks_open() failed " << ret << std::endl;
+                       return ret;
+               }
+               if (synchronous)
+                       return ret;
+
+               return WaitForCallback(ODE_LUKS_OPEN);
+       }
+
+       int close(const std::string& mapping)
+       {
+               int ret;
+               if (synchronous)
+                       ret = ode_luks_close_sync(mapping.c_str());
+               else
+                       ret = ode_luks_close(mapping.c_str());
+
+               if (ret != ODE_ERROR_NONE) {
+                       std::cerr << "ode_luks_close() failed " << ret << std::endl;
+                       return ret;
+               }
+               if (synchronous)
+                       return ret;
+
+               return WaitForCallback(ODE_LUKS_CLOSE);
+       }
+
+       int wait()
+       {
+               return WaitForCallbackInternal([](ode_luks_operation_e) { return true; });
+       }
+
+       ~LuksWrapper() {
+               if (synchronous)
+                       ode_luks_unset_event_cb();
+       }
+
+private:
        static void StaticCallback(ode_luks_operation_e op, int ret, void* user_data)
        {
-               auto self = static_cast<LuksListener*>(user_data);
+               auto self = static_cast<LuksWrapper*>(user_data);
                self->Callback(op, ret);
        }
 
@@ -283,11 +375,6 @@ public:
                cond.notify_one();
        }
 
-       int WaitForCallback()
-       {
-               return WaitForCallbackInternal([](ode_luks_operation_e) { return true; });
-       }
-
        int WaitForCallback(ode_luks_operation_e expected)
        {
                return WaitForCallbackInternal([=](ode_luks_operation_e op) {
@@ -295,11 +382,6 @@ public:
                });
        }
 
-       ~LuksListener() {
-               ode_luks_unset_event_cb();
-       }
-
-private:
        int WaitForCallbackInternal(const std::function<bool(ode_luks_operation_e)>& opCheck)
        {
                std::unique_lock<std::mutex> lock(mutex);
@@ -332,95 +414,53 @@ private:
        };
 
        std::vector<result> results;
+       bool synchronous;
 };
 
-static inline int luks(const std::string& name,
+static inline int luks(bool sync,
+                                          const std::string& name,
                                           const std::string& device,
                                           const std::string& mapping)
 {
-       int ret;
-
-       if (name == "format") {
-               if (device.empty())
-                       return usage(name);
+       try {
+               if (name == "format") {
+                       if (device.empty())
+                               return usage(name);
 
-               LuksListener listener;
-               ret = ode_luks_set_event_cb(&LuksListener::StaticCallback, &listener);
-               if (ret != ODE_ERROR_NONE) {
-                       std::cerr << "Callback setting failed " << ret << std::endl;
-                       return ret;
+                       LuksWrapper wrapper(sync);
+                       return wrapper.format(device);
                }
 
-               std::cout << "New ";
-               std::string password = getPassword();
-
-               std::cout << "Confirm ";
-               std::string password2 = getPassword();
-               if (password != password2) {
-                       std::cerr << "Confirm password doesn't match" << std::endl;
-                       return -1;
-               }
+               if (name == "open") {
+                       if (device.empty() || mapping.empty())
+                               return usage(name);
 
-               ret = ode_luks_format(device.c_str(), password.c_str());
-               if (ret != ODE_ERROR_NONE) {
-                       std::cerr << "ode_luks_format() failed " << ret << std::endl;
-                       return ret;
+                       LuksWrapper wrapper(sync);
+                       return wrapper.open(device, mapping);
                }
-               return listener.WaitForCallback(ODE_LUKS_FORMAT);
-       }
 
-       if (name == "open") {
-               if (device.empty() || mapping.empty())
-                       return usage(name);
+               if (name == "close") {
+                       if (mapping.empty())
+                               return usage(name);
 
-               LuksListener listener;
-               ret = ode_luks_set_event_cb(&LuksListener::StaticCallback, &listener);
-               if (ret != ODE_ERROR_NONE) {
-                       std::cerr << "Callback setting failed " << ret << std::endl;
-                       return ret;
+                       LuksWrapper wrapper(sync);
+                       return wrapper.close(mapping);
                }
 
-               std::string password = getPassword();
-               ret = ode_luks_open(device.c_str(), password.c_str(), mapping.c_str());
-               if (ret != ODE_ERROR_NONE) {
-                       std::cerr << "ode_luks_open() failed " << ret << std::endl;
-                       return ret;
+               if (name == "wait" && !sync) {
+                       LuksWrapper wrapper(sync);
+                       return wrapper.wait();
                }
-               return listener.WaitForCallback(ODE_LUKS_OPEN);
-       }
-
-       if (name == "close") {
-               if (mapping.empty())
-                       return usage(name);
 
-               LuksListener listener;
-               ret = ode_luks_set_event_cb(&LuksListener::StaticCallback, &listener);
-               if (ret != ODE_ERROR_NONE) {
-                       std::cerr << "Callback setting failed " << ret << std::endl;
-                       return ret;
-               }
-
-               ret = ode_luks_close(mapping.c_str());
-               if (ret != ODE_ERROR_NONE) {
-                       std::cerr << "ode_luks_open() failed " << ret << std::endl;
-                       return ret;
-               }
-               return listener.WaitForCallback(ODE_LUKS_CLOSE);
-       }
-
-       if (name == "wait") {
-               LuksListener listener;
-               ret = ode_luks_set_event_cb(&LuksListener::StaticCallback, &listener);
-               if (ret != ODE_ERROR_NONE) {
-                       std::cerr << "Callback setting failed " << ret << std::endl;
-                       return ret;
-               }
-
-               return listener.WaitForCallback();
+               if (sync)
+                       std::cerr << "Wrong arguments (format|open|close)" << std::endl;
+               else
+                       std::cerr << "Wrong arguments (format|open|close|wait)" << std::endl;
+               return -1;
+       } catch (const std::runtime_error& e) {
+               std::cerr << e.what() << std::endl;
+               return -1;
        }
-
-       std::cerr << "Wrong arguments (format|open|close|wait)" << std::endl;
-       return -1;
 }
 
 static inline int change_password(const std::string name)
@@ -539,6 +579,7 @@ int main(int argc, char* argv[])
                {"encrypt", required_argument, 0, 'e'},
                {"decrypt", required_argument, 0, 'd'},
                {"luks" , required_argument, 0, 'l'},
+               {"luks_sync" , required_argument, 0, 'L'},
                {"state", required_argument, 0, 's'},
                {"waitmnt", required_argument, 0, 'w'},
                {"clean", required_argument, 0, 'c'},
@@ -548,6 +589,7 @@ int main(int argc, char* argv[])
        struct option luks_options[] = {
                {"device", required_argument, 0, 'D'},
                {"mapping", required_argument, 0, 'M'},
+               {"synchronous", no_argument, 0, 'S'},
                {0, 0, 0, 0}
        };
 
@@ -557,8 +599,9 @@ int main(int argc, char* argv[])
        }
 
        std::string mapping, device, op;
+       bool sync = true;
 
-       while ((opt = getopt_long(argc, argv, "m:u:e:d:l:p:s:w:c:h", options, &index)) != -1) {
+       while ((opt = getopt_long(argc, argv, "m:u:e:d:l:L:p:s:w:c:h", options, &index)) != -1) {
                switch (opt) {
                case 'm':
                        ret = mount(optarg);
@@ -573,6 +616,9 @@ int main(int argc, char* argv[])
                        ret = decrypt_storage(optarg);
                        break;
                case 'l':
+                       sync = false;
+                       // No break on purpose. Logic is the same just the flag is different.
+               case 'L':
                        op = optarg;
                        while ((luks_opt = getopt_long(argc, argv, "D:M:", luks_options, &index)) != -1) {
                                switch (luks_opt) {
@@ -587,7 +633,7 @@ int main(int argc, char* argv[])
                                }
                        }
                        if (ret == 0)
-                               ret = luks(op, device, mapping);
+                               ret = luks(sync, op, device, mapping);
                        break;
                case 'p':
                        ret = change_password(optarg);