add basic vconf listener
authorMaciej Slodczyk <m.slodczyk2@partner.samsung.com>
Fri, 15 Feb 2019 15:13:53 +0000 (16:13 +0100)
committerMaciej Slodczyk <m.slodczyk2@partner.samsung.com>
Fri, 22 Feb 2019 14:05:07 +0000 (15:05 +0100)
Signed-off-by: Maciej Slodczyk <m.slodczyk2@partner.samsung.com>
Makefile.am
configure.ac
modules.conf.d/vconf_listener.conf.d/50-default.conf [new file with mode: 0644]
packaging/faultd.spec
src/event_types/vconf_key_changed_event.c [new file with mode: 0644]
src/event_types/vconf_key_changed_event.h [new file with mode: 0644]
src/faultd.c
src/listeners/vconf.c [new file with mode: 0644]
src/util/common.c
src/util/common.h

index 3e0518248ebc31c7de83bae46b36376209272cec..d6cdadc580994111ecd1cad0e886cd18d7567f35 100644 (file)
@@ -49,6 +49,7 @@ AM_CFLAGS = \
        -fPIE \
        -rdynamic \
        $(GLIB_CFLAGS) \
+       $(VCONF_CFLAGS) \
        -D"FAULTD_MODNAME_T=$(call name_fix,$(modname))"
 
 AM_LDFLAGS = \
@@ -57,6 +58,7 @@ AM_LDFLAGS = \
        -avoid-version \
        -module \
        -shared \
+       $(VCONF_LIBS) \
        -pie
 
 SED_PROCESS = \
@@ -98,6 +100,7 @@ faultdlib_SOURCES = \
     src/event_types/action_executed_event.c \
     src/event_types/decision_made_event.c \
     src/event_types/resource_violation_event.c \
+    src/event_types/vconf_key_changed_event.c \
     src/event_types/service_failed_event.c \
     src/event_types/faultd_started_event.c \
     src/event_types/system_booted_event.c \
@@ -122,6 +125,7 @@ EXTRA_faultd_SOURCES = \
     src/listeners/audit.c \
     src/listeners/systemd.c \
     src/listeners/startup.c \
+    src/listeners/vconf.c \
     src/database/sqlite.c \
     src/decision_makers/vip_fault_dm.c \
     src/decision_makers/rv_dm.c \
@@ -139,6 +143,7 @@ modulesdir = $(pkglibdir)/available-modules
 modules_LTLIBRARIES = audit_listener.la \
                  systemd_listener.la \
                  startup_listener.la \
+                 vconf_listener.la \
                  sqlite_dbadapter.la \
                  vip_fault_eh.la \
                  resource_violation_eh.la \
@@ -153,6 +158,9 @@ audit_listener_la_SOURCES = src/listeners/audit.c
 audit_listener_la_LIBADD = $(AUDIT_LIBS)
 systemd_listener_la_SOURCES = src/listeners/systemd.c
 startup_listener_la_SOURCES = src/listeners/startup.c
+vconf_listener_la_SOURCES = src/listeners/vconf.c
+vconf_listener_config_DATA = modules.conf.d/vconf_listener.conf.d/50-default.conf
+vconf_listener_configdir = $(modulesconfigdir)/vconf_listener.conf.d
 sqlite_dbadapter_la_SOURCES = src/database/sqlite.c
 sqlite_dbadapter_la_LIBADD = $(SQLITE3_LIBS)
 vip_fault_eh_la_SOURCES = src/decision_makers/vip_fault_dm.c
@@ -230,7 +238,8 @@ if UNIT_TESTS
 check_PROGRAMS = test
 
 test_LDFLAGS = -ldl \
-       $(GLIB_LIBS)
+       $(GLIB_LIBS) \
+       $(VCONF_LIBS)
 
 test_LDADD = \
     $(faultd_LDADD) \
@@ -242,6 +251,7 @@ test_CFLAGS = -I${top_srcdir}/src/util \
        -D"FAULTD_MODNAME_T=$(call name_fix,$(modname))" \
        -DTEST_BUILD \
        $(GLIB_CFLAGS) \
+       $(VCONF_CFLAGS) \
        --coverage
 
 test_SOURCES = \
index 791870e328922f54b5f65c65c0aa65ea12a20640..b0215c4e9338fcb409dd4c13778321b682013212 100644 (file)
@@ -150,6 +150,13 @@ PKG_CHECK_MODULES(JSON_C,
 AS_IF([test "x$have_json_c" = "xno"],
       AC_MSG_ERROR([json-c not found]))
 
+PKG_CHECK_MODULES(VCONF,
+        [vconf],
+        have_vconf=yes,
+        have_vconf=no)
+AS_IF([test "x$have_vconf" = "xno"],
+      AC_MSG_ERROR([vconf not found]))
+
 AC_CHECK_FUNCS([ \
        printf\
 ])
@@ -176,6 +183,7 @@ AC_MSG_RESULT([
 
         libsystemd:             ${have_libsystemd}
         glib                    ${have_glib}
+        vconf                    ${have_vconf}
 
         modules:                ${ENABLED_MODULES/ /}
 ])
diff --git a/modules.conf.d/vconf_listener.conf.d/50-default.conf b/modules.conf.d/vconf_listener.conf.d/50-default.conf
new file mode 100644 (file)
index 0000000..d03206b
--- /dev/null
@@ -0,0 +1,4 @@
+{
+       "keys_count" : 3,
+       "keys":[ "db/test/key1", "db/test/key2", "db/test/key3" ]
+}
index 60de1149788a3b0e09b5594ed047f07f5cfbce88..5b0c0b5bf2e7ab33e06c8f54ce929d76fcb0d5cb 100644 (file)
@@ -7,7 +7,7 @@ Source1001: %{name}.manifest
 Summary:    Fault detection daemon
 Group:      System/Monitoring
 
-%define with_faultd_glib_support 0
+%define with_faultd_glib_support 1
 %define database_module sqlite_dbadapter
 
 BuildRequires: pkgconfig(libsystemd)
@@ -17,6 +17,7 @@ BuildRequires: pkgconfig(sqlite3)
 %if %{with_faultd_glib_support}
 BuildRequires: pkgconfig(glib-2.0)
 %endif
+BuildRequires: pkgconfig(vconf)
 
 %description
 faultd monitors system services, detects their abnormal execution and
@@ -85,6 +86,7 @@ for mod in audit_listener \
        standard_fault_eh \
        standard_reboot_eh \
        startup_listener \
+       vconf_listener \
        system_reboot_to_recovery_action
 do
        ln -s %{moduledir}/${mod}.so %{buildroot}/%{moduleconfdir}/${mod}.so;
@@ -121,6 +123,7 @@ echo %{enabled_moduledir}/%{database_module}.so >> faultd-extra-files;
 %files extra -f faultd-extra-files
 %{_prefix}/lib/faultd/modules.conf.d/standard_fault_eh.conf.d/50-default.conf
 %{_prefix}/lib/faultd/modules.conf.d/standard_reboot_eh.conf.d/50-default.conf
+%{_prefix}/lib/faultd/modules.conf.d/vconf_listener.conf.d/50-default.conf
 
 %files test-services
 %{_bindir}/faultd/leaker
diff --git a/src/event_types/vconf_key_changed_event.c b/src/event_types/vconf_key_changed_event.c
new file mode 100644 (file)
index 0000000..e363b8d
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * This file is part of faultd.
+ *
+ * Copyright © 2017 Samsung Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include "vconf_key_changed_event.h"
+
+static int allocate_vkc_event(struct faultd_event_type *type,
+                                                        void *data, struct faultd_event **ev)
+{
+       struct vconf_key_changed_event *vkc_ev;
+       struct vconf_key_changed_event_data *vkc_ev_data = data;
+       int ret;
+
+       vkc_ev = calloc(1, sizeof(*vkc_ev));
+       if (!vkc_ev)
+               return -ENOMEM;
+
+       ret = faultd_event_init_internal(type, &vkc_ev->event);
+       if (ret)
+               goto cleanup;
+
+       vkc_ev->event_time = vkc_ev_data->event_time;
+       vkc_ev->key_name = vkc_ev_data->key_name;
+       vkc_ev->oldval = vkc_ev_data->oldval;
+       vkc_ev->newval = vkc_ev_data->newval;
+
+       *ev = &vkc_ev->event;
+       return 0;
+cleanup:
+       free(vkc_ev);
+
+       return ret;
+}
+
+static int deserialize_vkc_event(struct faultd_event_type *type,
+                                                               struct faultd_object *data, struct faultd_event **ev)
+{
+       int ret = -EINVAL;
+       struct vconf_key_changed_event_data vkc_ev_data;
+       struct faultd_object *obj;
+       memset(&vkc_ev_data, 0, sizeof(vkc_ev_data));
+
+       list_for_each_entry(obj, &data->val.children, node) {
+               if ((obj->type == TYPE_STRING) &&
+                                       (strcmp(VKC_EV_NAME, obj->key) == 0)) {
+                       vkc_ev_data.key_name = obj->val.s;
+               } else if ((obj->type == TYPE_BOOL) &&
+                                       (strcmp(VKC_EV_OLDVAL, obj->key) == 0)) {
+                       vkc_ev_data.oldval.value.b = obj->val.b;
+                       vkc_ev_data.oldval.type = VKC_BOOL;
+               } else if ((obj->type == TYPE_INT) &&
+                                       (strcmp(VKC_EV_OLDVAL, obj->key) == 0)) {
+                       vkc_ev_data.oldval.value.i = obj->val.i;
+                       vkc_ev_data.oldval.type = VKC_INT;
+               } else if ((obj->type == TYPE_DOUBLE) &&
+                                       (strcmp(VKC_EV_OLDVAL, obj->key) == 0)) {
+                       vkc_ev_data.oldval.value.d = obj->val.d;
+                       vkc_ev_data.oldval.type = VKC_DOUBLE;
+               } else if ((obj->type == TYPE_STRING) &&
+                                       (strcmp(VKC_EV_OLDVAL, obj->key) == 0)) {
+                       vkc_ev_data.oldval.value.s = obj->val.s; //strdup()?
+                       vkc_ev_data.oldval.type = VKC_STRING;
+               } else if ((obj->type == TYPE_BOOL) &&
+                                       (strcmp(VKC_EV_NEWVAL, obj->key) == 0)) {
+                       vkc_ev_data.newval.value.b = obj->val.b;
+                       vkc_ev_data.newval.type = VKC_BOOL;
+               } else if ((obj->type == TYPE_INT) &&
+                                       (strcmp(VKC_EV_NEWVAL, obj->key) == 0)) {
+                       vkc_ev_data.newval.value.i = obj->val.i;
+                       vkc_ev_data.newval.type = VKC_INT;
+               } else if ((obj->type == TYPE_DOUBLE) &&
+                                       (strcmp(VKC_EV_NEWVAL, obj->key) == 0)) {
+                       vkc_ev_data.newval.value.d = obj->val.d;
+                       vkc_ev_data.newval.type = VKC_DOUBLE;
+               } else if ((obj->type == TYPE_STRING) &&
+                                       (strcmp(VKC_EV_NEWVAL, obj->key) == 0)) {
+                       vkc_ev_data.newval.value.s = obj->val.s; //strdup()?
+                       vkc_ev_data.newval.type = VKC_STRING;
+               } else if ((obj->type == TYPE_TIME_T) &&
+                                       (strcmp(VKC_EV_TIME, obj->key) == 0)) {
+                       vkc_ev_data.event_time = obj->val.time;
+               }
+       }
+
+       ret = allocate_vkc_event(type, &vkc_ev_data, ev);
+       if (ret < 0)
+               goto finish;
+
+       ret = faultd_event_deserialize_internal(data, type, *ev);
+       if (ret < 0) {
+               struct vconf_key_changed_event *vkc_ev =
+                       to_vconf_key_changed_event(*ev);
+               free(vkc_ev);
+               goto finish;
+       }
+       ret = 0;
+finish:
+       return ret;
+}
+
+static void vkc_event_release(struct faultd_event *ev)
+{
+       struct vconf_key_changed_event *vkc_ev =
+               to_vconf_key_changed_event(ev);
+
+       if (vkc_ev->key_name)
+               free(vkc_ev->key_name);
+       if (vkc_ev->oldval.type == VKC_STRING)
+               free(vkc_ev->oldval.value.s);
+       if (vkc_ev->newval.type == VKC_STRING)
+               free(vkc_ev->newval.value.s);
+
+       faultd_event_cleanup_internal(&vkc_ev->event);
+       free(vkc_ev);
+}
+
+static void vkc_event_serialize(struct faultd_event *ev, struct faultd_object *out)
+{
+       struct vconf_key_changed_event *vkc_ev =
+               to_vconf_key_changed_event(ev);
+       faultd_event_serialize_internal(ev, out);
+       faultd_object_append_string(out, VKC_EV_NAME, vkc_ev->key_name);
+
+       switch (vkc_ev->oldval.type) {
+       case VKC_BOOL:
+               faultd_object_append_bool(out, VKC_EV_OLDVAL, vkc_ev->oldval.value.b);
+               break;
+       case VKC_INT:
+               faultd_object_append_int(out, VKC_EV_OLDVAL, vkc_ev->oldval.value.i);
+               break;
+       case VKC_DOUBLE:
+               faultd_object_append_double(out, VKC_EV_OLDVAL, vkc_ev->oldval.value.d);
+               break;
+       case VKC_STRING:
+               faultd_object_append_string(out, VKC_EV_OLDVAL, vkc_ev->oldval.value.s);
+               break;
+       }
+
+       switch (vkc_ev->newval.type) {
+       case VKC_BOOL:
+               faultd_object_append_bool(out, VKC_EV_NEWVAL, vkc_ev->newval.value.b);
+               break;
+       case VKC_INT:
+               faultd_object_append_int(out, VKC_EV_NEWVAL, vkc_ev->newval.value.i);
+               break;
+       case VKC_DOUBLE:
+               faultd_object_append_double(out, VKC_EV_NEWVAL, vkc_ev->newval.value.d);
+               break;
+       case VKC_STRING:
+               faultd_object_append_string(out, VKC_EV_NEWVAL, vkc_ev->newval.value.s);
+               break;
+       }
+       faultd_object_append_time_t(out, VKC_EV_TIME, vkc_ev->event_time);
+}
+
+static struct faultd_event_type vconf_key_changed_event_type = {
+       .name = VCONF_KEY_CHANGED_EVENT_ID,
+       .default_ops = {
+               .release = vkc_event_release,
+               .serialize = vkc_event_serialize,
+       },
+       .allocate_event = allocate_vkc_event,
+       .deserialize_event = deserialize_vkc_event,
+       .node = LIST_HEAD_INIT(vconf_key_changed_event_type.node),
+};
+
+FAULTD_EVENT_TYPE_REGISTER(vconf_key_changed_event_type, vconf_key_changed_et)
diff --git a/src/event_types/vconf_key_changed_event.h b/src/event_types/vconf_key_changed_event.h
new file mode 100644 (file)
index 0000000..380d303
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This file is a part of faultd.
+ *
+ * Copyright © 2017 Samsung Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _FAULTD_VCONF_KEY_CHANGED_EVENT_H
+#define _FAULTD_VCONF_KEY_CHANGED_EVENT_H
+
+#include <time.h>
+#include "event.h"
+
+#define VCONF_KEY_CHANGED_EVENT_ID "vconf_key_changed"
+#define VKC_EV_TIME "et"
+#define VKC_EV_NAME "name"
+#define VKC_EV_OLDVAL "oldval"
+#define VKC_EV_NEWVAL "newval"
+
+enum vkc_type {
+       VKC_BOOL,
+       VKC_INT,
+       VKC_DOUBLE,
+       VKC_STRING
+};
+
+struct vkc_value {
+       enum vkc_type type;
+       size_t size;
+       union {
+               bool b;
+               int i;
+               double d;
+               char *s;
+       } value;
+};
+
+struct vconf_key_changed_event {
+       struct faultd_event event;
+       char *key_name;
+       struct vkc_value oldval;
+       struct vkc_value newval;
+       time_t event_time;
+};
+
+struct vconf_key_changed_event_data {
+       char *key_name;
+       struct vkc_value oldval;
+       struct vkc_value newval;
+       time_t event_time;
+};
+
+#define to_vconf_key_changed_event(EVENT)                                              \
+       container_of(EVENT, struct vconf_key_changed_event, event)
+
+#endif /* _FAULTD_VCONF_KEY_CHANGED_EVENT_H */
index 43d57fda9234e6ed9abe2d3c6b2a9ea99de283c5..504ed53a98ddaf6e5186b2c606b1b3c8830a2a56 100644 (file)
@@ -36,6 +36,8 @@
 #include "json-config.h"
 #include "database.h"
 
+#define FAULTD_GLIB_MAINLOOP
+
 static int terminate = 0;
 
 enum faultd_running_modes {
diff --git a/src/listeners/vconf.c b/src/listeners/vconf.c
new file mode 100644 (file)
index 0000000..2ca9431
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * This file is part of faultd.
+ *
+ * Copyright © 2017 Samsung Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vconf.h>
+#include <glib.h>
+#include <time.h>
+
+#include "log.h"
+#include "module.h"
+#include "common.h"
+#include "list.h"
+#include "json-config.h"
+#include "event_processor.h"
+#include "vconf_key_changed_event.h"
+
+struct vconf_kv {
+       char *name;
+       struct vkc_value val;
+       struct list_head node;
+};
+
+struct vconf_listener {
+       struct faultd_module module;
+       struct list_head keys;
+};
+
+#define to_vconf_listener(MOD)                                         \
+       container_of(MOD, struct vconf_listener, module)
+
+static struct vconf_kv *find_vconf_kv(struct vconf_listener *l, const char *name)
+{
+       struct vconf_kv *k = NULL;
+
+       list_for_each_entry(k, &l->keys, node) {
+               if (!strcmp(k->name, name))
+                       return k;
+       }
+       return NULL;
+}
+
+static void copy_vkc_value(struct vkc_value *from, struct vkc_value *to)
+{
+       to->type = from->type;
+       to->size = from->size;
+       switch (from->type){
+       case VKC_BOOL:
+               to->value.i = from->value.i;
+               break;
+       case VKC_INT:
+               to->value.i = from->value.i;
+               break;
+       case VKC_DOUBLE:
+               to->value.d = from->value.d;
+               break;
+       case VKC_STRING:
+               to->value.s = strdup(from->value.s);
+               to->size = strlen (to->value.s);
+               break;
+       }
+       return;
+}
+
+static int set_object_value(struct vconf_kv *k, keynode_t *node)
+{
+       assert (k);
+       assert (node);
+       int ret = 0;
+
+       switch(vconf_keynode_get_type(node)) {
+       case VCONF_TYPE_INT:{
+               int value = vconf_keynode_get_int(node);
+               //if (value == 0) {
+               //      ret = -1;
+               //      break;
+               //}
+               k->val.value.i = value;
+               k->val.type = VKC_INT;
+               k->val.size = sizeof(int);
+               }break;
+       case VCONF_TYPE_BOOL:{
+               int value = vconf_keynode_get_bool(node);
+               if (value ==  -1) {
+                       ret = -1;
+                       break;
+               }
+               k->val.value.b = value;
+               k->val.type = VKC_BOOL;
+               k->val.size = sizeof(bool);
+               }break;
+       case VCONF_TYPE_DOUBLE:{
+               double value = vconf_keynode_get_dbl(node);
+               //if (value == 0.0) {
+               //      ret = -1;
+               //      break;
+               //}
+               k->val.value.d = value;
+               k->val.type = VKC_DOUBLE;
+               k->val.size = sizeof(double);
+               }break;
+       case VCONF_TYPE_STRING:{
+               char *value = vconf_keynode_get_str(node);
+               if (!value) {
+                       ret = -1;
+                       break;
+               }
+               k->val.value.s = strdup(value);
+               if (!k->val.value.s)
+                       return -1;
+               k->val.type = VKC_STRING;
+               k->val.size = strlen(value);
+               }break;
+       default:
+               ret = -1;
+               break;
+       }
+
+       return ret;
+}
+
+static void on_vconf_key_changed(keynode_t *key, void *data)
+{
+       struct vconf_listener *l = (struct vconf_listener *)data;
+       char *name = NULL;
+       struct vconf_key_changed_event_data vkc_ev_data = {};
+       struct faultd_event *ev;
+       struct timespec ts;
+       int ret = 0;
+
+       if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
+               log_error_errno(errno, "Unable to get timestamp : %m");
+               return;
+       }
+
+       name = vconf_keynode_get_name(key);
+       if (!name) {
+               log_debug("vconf:  key name not found (key=%s)", name);
+               return;
+       }
+
+       struct vconf_kv *k = find_vconf_kv(l, name);
+       if (!k) {
+               log_debug("vconf: key-value pair not found (key=%s)", name);
+               return;
+       }
+
+       vkc_ev_data.event_time = ts.tv_sec;
+       vkc_ev_data.key_name = strdup(name);
+       if (vkc_ev_data.key_name == NULL)
+               goto finish;
+
+       copy_vkc_value(&k->val, &vkc_ev_data.oldval);
+       if (k->val.type == VKC_STRING) {
+               free(k->val.value.s);
+               k->val.value.s = NULL;
+       }
+
+       if (set_object_value(k, key) < 0)
+               goto finish;
+
+       copy_vkc_value(&k->val, &vkc_ev_data.newval);
+
+       ret = faultd_event_create(VCONF_KEY_CHANGED_EVENT_ID, &vkc_ev_data, &ev);
+       if (ret) {
+               log_error_errno(ret, "Unable to allocate an event: %m.");
+               goto finish;
+       }
+
+       ret = event_processor_report_event(ev);
+       faultd_event_unref(ev);
+       if (ret)
+               log_error_errno(ret, "Unable to report event: %m");
+       return;
+finish:
+       free(vkc_ev_data.key_name);
+       if (vkc_ev_data.oldval.type == VKC_STRING)
+               free(vkc_ev_data.oldval.value.s);
+       if (vkc_ev_data.newval.type == VKC_STRING)
+               free(vkc_ev_data.newval.value.s);
+
+       return;
+}
+
+static int add_key(struct vconf_listener *l, const char *key, keynode_t *node)
+{
+       int ret = 0;
+       struct vconf_kv *k;
+
+       assert (l);
+       assert (key);
+       assert (node);
+
+       k = (struct vconf_kv*)malloc(sizeof(struct vconf_kv));
+       if (k == NULL) {
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       k->name = strdup(key);
+       if (k->name == NULL) {
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       if (set_object_value(k, node) < 0) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       list_add_tail(&k->node, &l->keys);
+       vconf_notify_key_changed(key, on_vconf_key_changed, l);
+       return 0;
+
+cleanup:
+       if (k) {
+               free(k->name);
+               free(k);
+       }
+       return ret;
+}
+
+static void cleanup(struct vconf_listener *l)
+{
+       struct vconf_kv *k, *next;
+
+       list_for_each_entry_safe(k, next, &l->keys, node) {
+               list_del(&k->node);
+               free(k->name);
+               if (k->val.type == VKC_STRING)
+                       free(k->val.value.s);
+               free(k);
+       }
+}
+
+static int vconf_listener_init(struct faultd_module *module,
+                                                                struct faultd_config *config,
+                                                                sd_event* event)
+{
+       struct vconf_listener *listener = to_vconf_listener(module);
+       int ret = 0;
+       json_object *arr, *val;
+       keylist_t *klist;
+       keynode_t *knode;
+
+       INIT_LIST_HEAD(&listener->keys);
+
+       if (!json_object_object_get_ex(config->root, "keys", &arr)) {
+               log_error("Config does not contain 'keys' parameter.");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       if (!json_object_is_type(arr, json_type_array)) {
+               log_error("Config value is not an array");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       for (size_t i = 0; i < json_object_array_length(arr); i++) {
+               val = json_object_array_get_idx(arr, i);
+               if (val == NULL) {
+                       log_error("vconf: no specified key (%d)\n", i);
+                       ret = -EINVAL;
+                       goto cleanup;
+               }
+
+               klist = vconf_keylist_new();
+               if (!klist) {
+                       log_error("vconf: could not create keylist for %s\n", json_object_get_string(val));
+                       continue;
+               }
+
+               ret = vconf_get(klist, json_object_get_string(val), VCONF_GET_ALL);
+               if (ret < 0) {
+                       log_debug("vconf: keylist does not contain key %s\n", json_object_get_string(val));
+                       goto free_list;
+               }
+
+               ret = vconf_keylist_lookup(klist, json_object_get_string(val), &knode);
+               if (ret < 0) {
+                       log_debug("vconf_keylist_lookup failed for %s\n", json_object_get_string(val));
+                       goto free_list;
+               }
+
+               ret = add_key(listener, json_object_get_string(val), knode);
+               if (ret < 0)
+                       log_error("vconf: could not add key\n");
+
+               free_list:
+                       vconf_keylist_free(klist);
+       }
+       return 0;
+
+cleanup:
+       cleanup(listener);
+       return ret;
+}
+
+static void vconf_listener_cleanup(struct faultd_module *module)
+{
+       struct vconf_listener *listener = to_vconf_listener(module);
+       cleanup(listener);
+}
+
+struct vconf_listener vconf_listener = {
+       .module = {
+               .name = "vconf_listener",
+               .type = FAULTD_MODULE_TYPE_LISTENER,
+
+               .init = vconf_listener_init,
+               .cleanup = vconf_listener_cleanup,
+               .node = LIST_HEAD_INIT(vconf_listener.module.node),
+       },
+};
+
+FAULTD_MODULE_REGISTER(&vconf_listener.module)
index b9b53bc49c008349beedd0bf23647bd1845e9c5c..e2e8df03b6552c191b40b446b11c898eb096c580 100644 (file)
@@ -47,6 +47,8 @@ static const size_t data_size[] = {
        [TYPE_INT] = sizeof(int),
        [TYPE_TIMESPEC] = sizeof(struct timespec),
        [TYPE_TIME_T] = sizeof(time_t),
+       [TYPE_BOOL] = sizeof(bool),
+       [TYPE_DOUBLE] = sizeof(double),
        [TYPE_UUID] = sizeof(sd_id128_t),
        [TYPE_OBJECT] = sizeof(struct list_head),
 };
@@ -57,6 +59,8 @@ static char *faultd_object_type_names[] = {
        [TYPE_INT] = "TYPE_INT",
        [TYPE_TIMESPEC] = "TYPE_TIMESPEC",
        [TYPE_TIME_T] = "TYPE_TIME_T",
+       [TYPE_BOOL] = "TYPE_BOOL",
+       [TYPE_DOUBLE] = "TYPE_DOUBLE",
        [TYPE_UUID] = "TYPE_UUID",
        [TYPE_OBJECT] = "TYPE_OBJECT",
 };
index 2db6c366a9bbe0d4f397730480faf0bbb3135b7d..0413dc6491f711495420a3de5b717efc37043e20 100644 (file)
@@ -76,6 +76,8 @@ enum faultd_object_type {
        TYPE_INT,
        TYPE_TIMESPEC,
        TYPE_TIME_T,
+       TYPE_BOOL,
+       TYPE_DOUBLE,
        TYPE_UUID,
        TYPE_OBJECT,
 };
@@ -103,6 +105,8 @@ union faultd_object_value {
        int i;
        struct timespec ts;
        time_t time;
+       bool b;
+       double d;
        sd_id128_t uuid;
        struct list_head children;
 };
@@ -163,6 +167,18 @@ static inline int faultd_object_append_int(struct faultd_object *obj,
        return faultd_object_append_new(obj, key, TYPE_INT, &val);
 }
 
+static inline int faultd_object_append_bool(struct faultd_object *obj,
+                                                                                  const char *key, bool val)
+{
+       return faultd_object_append_new(obj, key, TYPE_BOOL, &val);
+}
+
+static inline int faultd_object_append_double(struct faultd_object *obj,
+                                                                                  const char *key, double val)
+{
+       return faultd_object_append_new(obj, key, TYPE_DOUBLE, &val);
+}
+
 static inline int faultd_object_append_time_t(struct faultd_object *obj,
                                                                                          const char *key, time_t val)
 {
@@ -192,6 +208,18 @@ static inline int faultd_object_get_string(struct faultd_object *obj,
        return faultd_object_get_val(obj, key, TYPE_STRING, val);
 }
 
+static inline int faultd_object_get_double(struct faultd_object *obj,
+                                                                                  const char *key, double *val)
+{
+       return faultd_object_get_val(obj, key, TYPE_DOUBLE, val);
+}
+
+static inline int faultd_object_get_bool(struct faultd_object *obj,
+                                                                                  const char *key, bool *val)
+{
+       return faultd_object_get_val(obj, key, TYPE_BOOL, val);
+}
+
 static inline int faultd_object_get_oid(struct faultd_object *obj,
                                                                                const char *key, faultd_oid_t *val)
 {