refactoring: group path resolving ops into a class 03/203203/5
authorAdrian Szyndela <adrian.s@samsung.com>
Wed, 10 Apr 2019 14:04:13 +0000 (16:04 +0200)
committerAdrian Szyndela <adrian.s@samsung.com>
Thu, 11 Apr 2019 15:16:45 +0000 (17:16 +0200)
This introduces BusPathResolver class.

Change-Id: I56d22e0b6b5e565415b1ff6d070986efa97c7502

src/libdbuspolicy1.cpp

index f6cf758..394e685 100644 (file)
@@ -36,9 +36,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#define KDBUS_PATH_PREFIX "/sys/fs/kdbus/"
-#define KDBUS_SYSTEM_BUS_PATH KDBUS_PATH_PREFIX"0-system/bus"
-
 using ldp_xml_parser::DecisionResult;
 using ldp_xml_parser::MatchItemSend;
 using ldp_xml_parser::MatchItemReceive;
@@ -208,90 +205,88 @@ private:
 
 };
 
-static std::shared_ptr<const char> bus_type_from_path(const char *bus_path, BusType &bus_type)
-{
-       assert(bus_path);
-
-       std::shared_ptr<const char> p(realpath(bus_path, nullptr), [](const char *a) { free(const_cast<char*>(a)); });
-       if (!p)
-               return nullptr;
-
-       if (0 == strcmp(p.get(), KDBUS_SYSTEM_BUS_PATH)) {
-               bus_type = SYSTEM_BUS;
-               return p;
-       }
-
-       if (0 == strncmp(p.get(), KDBUS_PATH_PREFIX, strlen(KDBUS_PATH_PREFIX))) {
-               bus_type = SESSION_BUS;
-               return p;
-       }
-
-       return nullptr;
-}
-
-// We will never get 0 as a session bus owner (0 uses "0-system" bus),
-// so it's OK to assume that bus_owner==0 always means error.
-static uid_t bus_owner_from_path(const char *resolved_path) noexcept
-{
-       boost::string_ref user_suffix("-user/bus");
-       boost::string_ref ps(resolved_path);
-
-       if (!ps.ends_with(user_suffix))
-               return 0;
-
-       ps.remove_suffix(user_suffix.length());
-
-       size_t last_slash = ps.find_last_of('/');
-       if (last_slash == boost::string_ref::npos || last_slash == ps.length() - 1)
-               return 0;
-
-       ps = ps.substr(last_slash+1);
+/*
+ * This class encapsulates functions used to analyze passed path to kdbus bus file.
+ * It recognizes system and session paths.
+ * If it recognizes path as a session bus, then it extracts owner's uid.
+ */
+class BusPathResolver {
+       std::shared_ptr<const char> resolved_path;
+       BusType type{SESSION_BUS};
+       uid_t owner{0};
+       bool ok{false};
+
+       // We will never get 0 as a session bus owner (0 uses "0-system" bus),
+       // so it's OK to assume that bus_owner==0 always means error.
+       bool extract_bus_owner() noexcept
+       {
+               boost::string_ref user_suffix("-user/bus");
+               boost::string_ref ps(resolved_path.get());
 
-       errno = 0;
-       uid_t bus_owner = strtol(ps.data(), NULL, 10);
-       if (errno)
-               return 0;
+               if (!ps.ends_with(user_suffix))
+                       return false;
 
-       return bus_owner;
-}
+               ps.remove_suffix(user_suffix.length());
 
-static std::shared_ptr<const char> bus_path_resolve(const char *bus_path, BusType &bus_type, uid_t &bus_owner)
-{
-       assert(bus_path);
+               size_t last_slash = ps.find_last_of('/');
+               if (last_slash == boost::string_ref::npos || last_slash == ps.length() - 1)
+                       return false;
 
-       auto resolved_path = bus_type_from_path(bus_path, bus_type);
+               ps = ps.substr(last_slash+1);
 
-       if (nullptr == resolved_path)
-               return nullptr;
+               errno = 0;
+               uid_t bus_owner = strtol(ps.data(), NULL, 10);
+               if (errno)
+                       return false;
 
-       if (bus_type == SESSION_BUS) {
-               auto result = bus_owner_from_path(resolved_path.get());
-               if (result > 0)
-                       bus_owner = result;
-               else
-                       return nullptr;
+               owner = bus_owner;
+               type = SESSION_BUS;
+               return true;
        }
+#define STR_SIZE(x) (x), sizeof(x)-1
+       static constexpr boost::string_ref KDBUS_PATH_PREFIX{STR_SIZE("/sys/fs/kdbus/")};
+       static constexpr boost::string_ref KDBUS_SYSTEM_BUS_PATH{STR_SIZE("/sys/fs/kdbus/0-system/bus")};
+#undef STR_SIZE
 
-       return resolved_path;
-}
+public:
+       BusPathResolver(const char *bus_path)
+               : resolved_path(realpath(bus_path, nullptr), [](const char *a) { free(const_cast<char*>(a)); })
+       {
+               if (!resolved_path)
+                       return;
+
+               // recognize bus type
+               if (KDBUS_SYSTEM_BUS_PATH == resolved_path.get()) {
+                       type = SYSTEM_BUS;
+                       ok = true;
+               } else if (boost::string_ref(resolved_path.get()).starts_with(KDBUS_PATH_PREFIX)) {
+                       ok = extract_bus_owner();
+               }
+       }
+       operator bool() { return ok; }
+       const char *path() { return resolved_path.get(); }
+       BusType bus_type() { return type; }
+       uid_t bus_owner() { return owner; }
+};
 
 DBUSPOLICY1_EXPORT void* dbuspolicy1_init_shared(const char *bus_path, int fd)
 {
-       BusType bus_type = SESSION_BUS;
-       uid_t bus_owner = 0;
+       assert(bus_path);
 
-       auto resolved_path = bus_path_resolve(bus_path, bus_type, bus_owner);
-       if (nullptr == resolved_path) {
+       BusPathResolver path_resolver(bus_path);
+       if (!path_resolver) {
                LOGE("Error resolving bus path: %s", bus_path);
                return nullptr;
        }
 
        g_udesc.init();
 
+       auto bus_type = path_resolver.bus_type();
+
        kconn *result = nullptr;
-       if (Checker::get(bus_type).can_open_owned_by(bus_owner)) {
+       if (Checker::get(bus_type).can_open_owned_by(path_resolver.bus_owner())) {
                if (-1 == fd) {
-                       result = &kconn::get(bus_type, resolved_path.get());
+                       result = &kconn::get(bus_type, path_resolver.path());
                } else {
                        result = kconn::get_shared(bus_type, fd);
                }