-fPIE \
-rdynamic \
$(GLIB_CFLAGS) \
+ $(VCONF_CFLAGS) \
-D"FAULTD_MODNAME_T=$(call name_fix,$(modname))"
AM_LDFLAGS = \
-avoid-version \
-module \
-shared \
+ $(VCONF_LIBS) \
-pie
SED_PROCESS = \
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 \
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 \
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 \
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
check_PROGRAMS = test
test_LDFLAGS = -ldl \
- $(GLIB_LIBS)
+ $(GLIB_LIBS) \
+ $(VCONF_LIBS)
test_LDADD = \
$(faultd_LDADD) \
-D"FAULTD_MODNAME_T=$(call name_fix,$(modname))" \
-DTEST_BUILD \
$(GLIB_CFLAGS) \
+ $(VCONF_CFLAGS) \
--coverage
test_SOURCES = \
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\
])
libsystemd: ${have_libsystemd}
glib ${have_glib}
+ vconf ${have_vconf}
modules: ${ENABLED_MODULES/ /}
])
--- /dev/null
+{
+ "keys_count" : 3,
+ "keys":[ "db/test/key1", "db/test/key2", "db/test/key3" ]
+}
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)
%if %{with_faultd_glib_support}
BuildRequires: pkgconfig(glib-2.0)
%endif
+BuildRequires: pkgconfig(vconf)
%description
faultd monitors system services, detects their abnormal execution and
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;
%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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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 */
#include "json-config.h"
#include "database.h"
+#define FAULTD_GLIB_MAINLOOP
+
static int terminate = 0;
enum faultd_running_modes {
--- /dev/null
+/*
+ * 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)
[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),
};
[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",
};
TYPE_INT,
TYPE_TIMESPEC,
TYPE_TIME_T,
+ TYPE_BOOL,
+ TYPE_DOUBLE,
TYPE_UUID,
TYPE_OBJECT,
};
int i;
struct timespec ts;
time_t time;
+ bool b;
+ double d;
sd_id128_t uuid;
struct list_head children;
};
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)
{
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)
{