Unify internal error code to DBus name mappings 08/275708/6
authorMichal Bloch <m.bloch@samsung.com>
Mon, 30 May 2022 19:55:18 +0000 (21:55 +0200)
committerArkadiusz Nowak <a.nowak3@samsung.com>
Thu, 2 Jun 2022 12:59:20 +0000 (14:59 +0200)
Change-Id: I37ef2cfefd2c30a77286b2444c57acdccf3d96c9
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
CMakeLists.txt
common/CMakeLists.txt [new file with mode: 0644]
common/include/sessiond-internal.h [new file with mode: 0644]
libsessiond/CMakeLists.txt
libsessiond/include/sessiond-internal.h [deleted file]
libsessiond/include/sessiond.h
sessiond/CMakeLists.txt
sessiond/src/main.cpp

index 22e12fd164365bdcd780639050ef40cac00a7f9d..cc387142a7393b1338f4a7234a1345ebdfc1ce84 100644 (file)
@@ -10,6 +10,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fPIE -Wno-error=shadow -Werror=missin
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIE -Wno-error=shadow -Werror=missing-field-initializers")
 set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
 
+add_subdirectory(common)
 add_subdirectory(libsessiond)
 add_subdirectory(sessiond)
 
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6d9ced1
--- /dev/null
@@ -0,0 +1,8 @@
+set(
+       sessiond_common_SRCS
+)
+
+add_library(sessiond_common INTERFACE)
+target_include_directories(sessiond_common INTERFACE include/ ${CMAKE_SOURCE_DIR}/libsessiond/include/)
+
+install(TARGETS sessiond_common)
diff --git a/common/include/sessiond-internal.h b/common/include/sessiond-internal.h
new file mode 100644 (file)
index 0000000..399c0a5
--- /dev/null
@@ -0,0 +1,65 @@
+/* MIT License
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE. */
+
+#pragma once
+
+#include "sessiond.h"
+
+#ifdef __cplusplus
+
+/* Our toolchain doesn't support `std::span` for some reason, so to make it
+ * easier to work with this array in C++ we make it into a proper container
+ * instead of wrapping over the oldschool C-style array.
+ *
+ * The price is that the C and C++ versions cannot be used alongside each other
+ * for linker reasons, but since this is an internal file it's acceptable.
+ *
+ * Ideally the messages would be `std::string_view`, but I couldn't get it
+ * to work with the macro. This is fine since the main use case so far wants
+ * C style strings anyway. */
+
+#include <array>
+#include <utility>
+
+#define MP(x, y) std::make_pair(x, y)
+
+static constexpr std::array error_mappings =
+
+#else
+typedef struct {
+       const char *dbus_error_msg;
+       int code;
+} error_mapping_t;
+
+#define MP(x, y) {x, y}
+
+static error_mapping_t error_mappings [] =
+
+#endif
+       { MP("org.tizen.sessiond.Error.InvalidParameter"       , SUBSESSION_ERROR_INVALID_PARAMETER)
+       , MP("org.tizen.sessiond.Error.IOError"                , SUBSESSION_ERROR_IO_ERROR         )
+       , MP("org.tizen.sessiond.Error.SubsessionAlreadyExists", SUBSESSION_ERROR_ALREADY_EXISTS   )
+       , MP("org.tizen.sessiond.Error.SubsessionDoesNotExist" , SUBSESSION_ERROR_NOT_AVAILABLE    )
+       , MP("org.tizen.sessiond.Error.UserIsActive"           , SUBSESSION_ERROR_RESOURCE_BUSY    )
+};
+
+#undef MP
index cef1569bac1f89474b7eb24cda23e2252fbf272f..b74e33520bc4954c0d4e20ca1ad123687b88ce1a 100644 (file)
@@ -6,7 +6,7 @@ set(
        src/lib.c
 )
 add_library(libsessiond SHARED ${libsessiond_SRCS})
-target_link_libraries(libsessiond PRIVATE PkgConfig::DEPS)
+target_link_libraries(libsessiond PRIVATE PkgConfig::DEPS sessiond_common)
 target_include_directories(libsessiond PUBLIC include)
 set_target_properties(
        libsessiond PROPERTIES
diff --git a/libsessiond/include/sessiond-internal.h b/libsessiond/include/sessiond-internal.h
deleted file mode 100644 (file)
index 470cf97..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* MIT License
- *
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is furnished
- * to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE. */
-
-#pragma once
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
-       const char *dbus_error_msg;
-       int code;
-} error_mapping_t;
-
-static error_mapping_t error_mappings[] = {
-       { "org.tizen.sessiond.Error.InvalidParameter",        SUBSESSION_ERROR_INVALID_PARAMETER },
-       { "org.tizen.sessiond.Error.IOError",                 SUBSESSION_ERROR_IO_ERROR },
-       { "org.tizen.sessiond.Error.SubsessionAlreadyExists", SUBSESSION_ERROR_ALREADY_EXISTS },
-       { "org.tizen.sessiond.Error.SubsessionDoesNotExist",  SUBSESSION_ERROR_NOT_AVAILABLE },
-       { "org.tizen.sessiond.Error.UserIsActive",            SUBSESSION_ERROR_RESOURCE_BUSY },
-};
-
-#ifdef __cplusplus
-}
-#endif
index 9171b34a0a75a6ae27f04c187ec8a3a6175dccc2..f74ddcbdd24e3a1824d783294bfc9a7c4eb79955 100644 (file)
@@ -33,15 +33,15 @@ extern "C" {
  * @since_tizen 7.0
  */
 typedef enum {
-       SUBSESSION_ERROR_NONE                      = TIZEN_ERROR_NONE,              /**< Successful */
-       SUBSESSION_ERROR_INVALID_PARAMETER         = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
-       SUBSESSION_ERROR_IO_ERROR                  = TIZEN_ERROR_IO_ERROR,          /**< I/O error */
-       SUBSESSION_ERROR_OUT_OF_MEMORY             = TIZEN_ERROR_OUT_OF_MEMORY,     /**< Out of memory */
-       SUBSESSION_ERROR_ALREADY_EXISTS            = TIZEN_ERROR_FILE_EXISTS,       /**< Resource already registered */
-       SUBSESSION_ERROR_NOT_AVAILABLE             = TIZEN_ERROR_NO_SUCH_DEVICE,    /**< Resource unavailable */
-       SUBSESSION_ERROR_RESOURCE_BUSY             = TIZEN_ERROR_RESOURCE_BUSY,     /**< Resource busy */
-       SUBSESSION_ERROR_PERMISSION_DENIED         = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
-       SUBSESSION_ERROR_NOT_SUPPORTED             = TIZEN_ERROR_NOT_SUPPORTED,     /**< Not supported */
+       SUBSESSION_ERROR_NONE              = TIZEN_ERROR_NONE,              /**< Successful */
+       SUBSESSION_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+       SUBSESSION_ERROR_IO_ERROR          = TIZEN_ERROR_IO_ERROR,          /**< I/O error */
+       SUBSESSION_ERROR_OUT_OF_MEMORY     = TIZEN_ERROR_OUT_OF_MEMORY,     /**< Out of memory */
+       SUBSESSION_ERROR_ALREADY_EXISTS    = TIZEN_ERROR_FILE_EXISTS,       /**< Resource already registered */
+       SUBSESSION_ERROR_NOT_AVAILABLE     = TIZEN_ERROR_NO_SUCH_DEVICE,    /**< Resource unavailable */
+       SUBSESSION_ERROR_RESOURCE_BUSY     = TIZEN_ERROR_RESOURCE_BUSY,     /**< Resource busy */
+       SUBSESSION_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+       SUBSESSION_ERROR_NOT_SUPPORTED     = TIZEN_ERROR_NOT_SUPPORTED,     /**< Not supported */
 } subsession_error_e;
 
 typedef enum {
index 389f4bcce7162575e5329349897c1fbc7bdfaf22..f8ad3579337785c3de8090fb8cdef7672c8ef2d5 100644 (file)
@@ -12,7 +12,7 @@ set(
 )
 add_executable(sessiond ${sessiond_SRCS})
 target_compile_features(sessiond PUBLIC cxx_std_20)
-target_link_libraries(sessiond PRIVATE PkgConfig::DEPS)
+target_link_libraries(sessiond PRIVATE PkgConfig::DEPS sessiond_common)
 install(TARGETS sessiond)
 
 INSTALL(FILES sessiond.service DESTINATION /usr/lib/systemd/system)
index 8a69bde2f02e4bca67b5dca24a432f0e4b59995a..f839cce9012cffa07696cec41270efd6cf7eec26 100644 (file)
 #include "tuple_hash.hpp"
 #include "wait_manager.hpp"
 
+#include "sessiond-internal.h"
+
+static constexpr const char * get_dbus_error_mapping (subsession_error_e subsession_error)
+{
+       /* I want this function to be evaluated at compile time
+        * and `std::find_if` is not constexpr/consteval-friendly,
+        * so caveman style iteration it is. */
+
+       const char *ret = nullptr;
+       for (const auto & x : error_mappings)
+               if (x.second == subsession_error)
+                       ret = x.first;
+
+       return ret ?: throw std::logic_error("Compile time get_dbus_error_mapping error");
+}
+
 using namespace std::string_view_literals;
 
 struct introspection_data {
@@ -126,12 +142,12 @@ struct sessiond_context {
        {
                if (session_uid <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
                        return true;
                }
                if (subsession_id <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative subsession_id passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative subsession_id passed");
                        return true;
                }
 
@@ -170,7 +186,7 @@ struct sessiond_context {
                        current_subsession_id = last_subsession_per_session.at(session_uid);
                if (subsession_id == current_subsession_id) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_RESOURCE_BUSY].second.data(), "Cannot remove currently active user");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_RESOURCE_BUSY), "Cannot remove currently active user");
                        return;
                }
 
@@ -193,19 +209,19 @@ struct sessiond_context {
 
                if (session_uid <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
                        return;
                }
                // N.B. Switch to user '0' is possible and it means no subsession is currently active
                if (next_subsession_id < 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative subsession_id passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative subsession_id passed");
                        return;
                }
 
                if (next_subsession_id > 0 && !fs_helpers::subsession_exists(session_uid, next_subsession_id)) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_NOT_AVAILABLE].second.data(), "Subsession does not exist");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_NOT_AVAILABLE), "Subsession does not exist");
                        return;
                }
 
@@ -234,7 +250,7 @@ struct sessiond_context {
 
                if (session_uid <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
                        return;
                }
 
@@ -250,7 +266,7 @@ struct sessiond_context {
 
                if (session_uid <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
                        return;
                }
 
@@ -266,7 +282,7 @@ struct sessiond_context {
 
                if (session_uid <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
                        return;
                }
 
@@ -308,7 +324,7 @@ struct sessiond_context {
 
                if (session_uid <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
                        return;
                }
 
@@ -324,7 +340,7 @@ struct sessiond_context {
 
                if (session_uid <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
                        return;
                }
 
@@ -345,7 +361,7 @@ struct sessiond_context {
 
                if (session_uid <= 0) {
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+                               get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
                        return;
                }
 
@@ -381,28 +397,28 @@ struct sessiond_context {
                (self->*(to_call->second))(invocation, std::string_view(sender), parameters);
        } catch (const std::invalid_argument &ex) {
                g_dbus_method_invocation_return_dbus_error(invocation,
-                       sessiond_errors[DBUS_ERROR_INVALID_PARAMETER].second.data(), ex.what());
+                       get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), ex.what());
                log_exception(ex, sender, method_name);
        } catch (const std::system_error &ex) {
                switch (ex.code().value()) {
                case EEXIST:
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_ALREADY_EXISTS].second.data(), ex.what());
+                               get_dbus_error_mapping(SUBSESSION_ERROR_ALREADY_EXISTS), ex.what());
                        break;
                case ENOENT:
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_NOT_AVAILABLE].second.data(), ex.what());
+                               get_dbus_error_mapping(SUBSESSION_ERROR_NOT_AVAILABLE), ex.what());
                        break;
                default:
                        g_dbus_method_invocation_return_dbus_error(invocation,
-                               sessiond_errors[DBUS_ERROR_IO_ERROR].second.data(),
+                               get_dbus_error_mapping(SUBSESSION_ERROR_IO_ERROR),
                                (std::string("Unable to complete requested operation: ") + ex.what()).c_str());
                        break;
                }
                log_exception(ex, sender, method_name);
        } catch (const std::runtime_error &ex) {
                g_dbus_method_invocation_return_dbus_error(invocation,
-                       sessiond_errors[DBUS_ERROR_IO_ERROR].second.data(),
+                       get_dbus_error_mapping(SUBSESSION_ERROR_IO_ERROR),
                        (std::string("Unable to complete requested operation: ") + ex.what()).c_str());
                log_exception(ex, sender, method_name);
                // Swallow the exception; the show must go on
@@ -518,14 +534,6 @@ struct sessiond_context {
                DBUS_ERROR_RESOURCE_BUSY,
        };
 
-       constexpr static std::array sessiond_errors = {
-               std::make_pair(DBUS_ERROR_INVALID_PARAMETER, "org.tizen.sessiond.Error.InvalidParameter"sv),
-               std::make_pair(DBUS_ERROR_IO_ERROR,          "org.tizen.sessiond.Error.IOError"sv),
-               std::make_pair(DBUS_ERROR_ALREADY_EXISTS,    "org.tizen.sessiond.Error.SubsessionAlreadyExists"sv),
-               std::make_pair(DBUS_ERROR_NOT_AVAILABLE,     "org.tizen.sessiond.Error.SubsessionDoesNotExist"sv),
-               std::make_pair(DBUS_ERROR_RESOURCE_BUSY,     "org.tizen.sessiond.Error.UserIsActive"sv),
-       };
-
        // TODO: Currently, the first parameter is always a single-element tuple.
        // Consider simplifying wait_manager.
        // N.B. Although GLib is multi-threaded, the following data structures do not need