#include <ejdb/bson.h>
#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
return (char *)bson_iterator_string(&it);
}
+
+static const size_t data_size[] = {
+ [TYPE_OID] = sizeof(faultd_oid_t),
+ [TYPE_STRING] = sizeof(char *),
+ [TYPE_INT] = sizeof(int),
+ [TYPE_TIMESPEC] = sizeof(struct timespec),
+ [TYPE_TIME_T] = sizeof(time_t),
+ [TYPE_UUID] = sizeof(sd_id128_t),
+ [TYPE_OBJECT] = sizeof(struct list_head),
+};
+
+static inline void copy_obj_val(struct faultd_object *obj, void *val)
+{
+ memcpy(&obj->val, val, data_size[obj->type]);
+}
+
+static void release_faultd_object(struct uref *uref)
+{
+ struct faultd_object *obj = container_of(uref, struct faultd_object, uref);
+
+ faultd_object_destroy(obj);
+ free(obj);
+}
+
+static inline void init_obj(struct faultd_object *obj, int type, void *val)
+{
+ assert(val != NULL || type == TYPE_OBJECT);
+
+ obj->type = type;
+ obj->key = NULL;
+ uref_init(&obj->uref, release_faultd_object);
+ INIT_LIST_HEAD(&obj->node);
+
+ if (type == TYPE_OBJECT && val == NULL)
+ INIT_LIST_HEAD(&obj->val.children);
+ else
+ copy_obj_val(obj, val);
+}
+
+static struct faultd_object *new_object_node(int type, void *val)
+{
+ struct faultd_object *obj;
+
+ assert(type >= 0);
+
+ obj = calloc(1, sizeof(*obj));
+ if (!obj)
+ return NULL;
+
+ init_obj(obj, type, val);
+
+ return obj;
+}
+
+int faultd_object_fill_empty(struct faultd_object *obj)
+{
+ return 0;
+}
+
+int faultd_object_new(struct faultd_object **obj)
+{
+ assert(obj);
+
+ *obj = new_object_node(TYPE_OBJECT, NULL);
+ if (!*obj)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void faultd_object_init(struct faultd_object *obj)
+{
+ assert(obj);
+
+ init_obj(obj, TYPE_OBJECT, NULL);
+}
+
+void faultd_object_destroy(struct faultd_object *obj)
+{
+ struct faultd_object *child, *next;
+
+ switch (obj->type) {
+ case TYPE_OBJECT:
+ list_for_each_entry_safe(child, next, &obj->val.children, node) {
+ list_del_init(&child->node);
+ faultd_object_unref(child);
+ }
+ break;
+ case TYPE_STRING:
+ free(obj->val.s);
+ break;
+ default:
+ break;
+ };
+
+ free(obj->key);
+}
+
+static int object_append(struct faultd_object *obj, const char *key, struct faultd_object *child)
+{
+ child->key = strdup(key);
+ if (!child->key)
+ return -ENOMEM;
+
+ list_add_tail(&child->node, &obj->val.children);
+ return 0;
+}
+
+int faultd_object_append_new(struct faultd_object *parent, const char *key,
+ int type, void *val)
+{
+ struct faultd_object *child;
+ int ret;
+
+ assert(parent);
+ assert(parent->type == TYPE_OBJECT);
+ assert(key);
+ assert(val);
+
+ child = new_object_node(type, val);
+ if (!child)
+ return -ENOMEM;
+
+ ret = object_append(parent, key, child);
+ if (ret < 0)
+ goto unref_child;
+
+ return 0;
+
+unref_child:
+ faultd_object_unref(child);
+ return ret;
+}
+
+int faultd_object_append_string(struct faultd_object *obj, const char *key, const char *val)
+{
+ char *val_copy;
+ int ret;
+
+ val_copy = strdup(val);
+ if (!val_copy)
+ return -ENOMEM;
+
+ ret = faultd_object_append_new(obj, key, TYPE_STRING, &val_copy);
+ if (ret < 0)
+ goto free_val_copy;
+
+ return 0;
+free_val_copy:
+ free(val_copy);
+ return ret;
+}
+
+int faultd_object_append_object(struct faultd_object *obj, const char *key,
+ struct faultd_object *val)
+{
+ return object_append(obj, key, faultd_object_ref(val));
+}
+
+static struct faultd_object *find_child(struct faultd_object *obj, const char *key)
+{
+ struct faultd_object *child;
+ size_t len;
+ char *dot;
+
+ assert(key);
+
+ dot = strchr(key, '.');
+ if (dot)
+ len = dot - key;
+ else
+ len = strlen(key);
+
+ list_for_each_entry(child, &obj->val.children, node) {
+ if (strncmp(key, child->key, len))
+ continue;
+
+ if (child->key[len] != '\0')
+ continue;
+
+ /* is this end of key? */
+ if (!dot)
+ return child;
+
+ /* Can search we recursively? */
+ if (child->type == TYPE_OBJECT)
+ return find_child(obj, dot + 1);
+ else
+ break;
+ }
+
+ return NULL;
+}
+
+int faultd_object_get_val(struct faultd_object *obj, const char *key,
+ int type, void *val)
+{
+ struct faultd_object *child;
+
+ assert(obj);
+ assert(obj->type == TYPE_OBJECT);
+ assert(key);
+
+ child = find_child(obj, key);
+ if (!child)
+ return -ENOENT;
+
+ if (child->type != type)
+ return -EFAULT;
+
+ memcpy(val, &child->val, data_size[child->type]);
+ return 0;
+}
+
+int faultd_object_get_object(struct faultd_object *obj, const char *key, struct faultd_object **val)
+{
+ struct faultd_object *child;
+
+ child = find_child(obj, key);
+ if (!child)
+ return -ENOENT;
+
+ if (child->type != TYPE_OBJECT)
+ return -EFAULT;
+
+ *val = child;
+ return 0;
+}
+
+int faultd_oid_from_string(faultd_oid_t *oid, const char *s)
+{
+ return sd_id128_from_string(s, &oid->uuid);
+}
#include <stdlib.h>
#include <time.h>
#include <errno.h>
+#include <systemd/sd-id128.h>
+
+#include "list.h"
+#include "uref.h"
/*
* Value taken from linux kernel.
char *bson_get_string(bson *b, char *fieldpath);
+enum faultd_type {
+ TYPE_OID,
+ TYPE_STRING,
+ TYPE_INT,
+ TYPE_TIMESPEC,
+ TYPE_TIME_T,
+ TYPE_UUID,
+ TYPE_OBJECT,
+};
+
+typedef union {
+ bson_oid_t bson;
+ sd_id128_t uuid;
+} faultd_oid_t;
+
+#define FAULTD_OID_IS_ZERO(o) (o.bson.ints[0] == 0 && \
+ o.bson.ints[1] == 0 && \
+ o.bson.ints[2] == 0)
+
+struct faultd_object {
+ char *key;
+ int type;
+ union {
+ faultd_oid_t oid;
+ char *s;
+ int i;
+ struct timespec ts;
+ time_t time;
+ sd_id128_t uuid;
+ struct list_head children;
+ } val;
+
+ struct uref uref;
+ struct list_head node;
+};
+
+static inline void faultd_object_unref(struct faultd_object *obj)
+{
+ if (!obj)
+ return;
+
+ uref_put(&obj->uref);
+}
+
+static inline struct faultd_object *faultd_object_ref(struct faultd_object *obj)
+{
+ if (!obj)
+ return NULL;
+
+ uref_get(&obj->uref);
+ return obj;
+}
+
+int faultd_object_new(struct faultd_object **obj);
+void faultd_object_init(struct faultd_object *obj);
+void faultd_object_destroy(struct faultd_object *obj);
+
+int faultd_object_append_new(struct faultd_object *parent, const char *key,
+ int type, void *val);
+
+int faultd_object_append_string(struct faultd_object *obj, const char *key,
+ const char *val);
+int faultd_object_append_object(struct faultd_object *obj, const char *key,
+ struct faultd_object *val);
+
+static inline int faultd_object_append_oid(struct faultd_object *obj,
+ const char *key, faultd_oid_t *oid)
+{
+ return faultd_object_append_new(obj, key, TYPE_OID, oid);
+}
+
+static inline int faultd_object_append_int(struct faultd_object *obj,
+ const char *key, int val)
+{
+ return faultd_object_append_new(obj, key, TYPE_INT, &val);
+}
+
+static inline int faultd_object_append_time_t(struct faultd_object *obj,
+ const char *key, time_t val)
+{
+ return faultd_object_append_new(obj, key, TYPE_TIME_T, &val);
+}
+
+static inline int faultd_object_append_timespec(struct faultd_object *obj,
+ const char *key,
+ struct timespec *val)
+{
+ return faultd_object_append_new(obj, key, TYPE_TIMESPEC, val);
+}
+
+static inline int faultd_object_append_uuid(struct faultd_object *obj,
+ const char *key, sd_id128_t *val)
+{
+ return faultd_object_append_new(obj, key, TYPE_UUID, val);
+}
+
+
+int faultd_object_get_val(struct faultd_object *obj, const char *key,
+ int type, void *val);
+
+static inline int faultd_object_get_string(struct faultd_object *obj,
+ const char *key, char **val)
+{
+ return faultd_object_get_val(obj, key, TYPE_STRING, val);
+}
+
+static inline int faultd_object_get_int(struct faultd_object *obj,
+ const char *key, int *val)
+{
+ return faultd_object_get_val(obj, key, TYPE_INT, val);
+}
+
+static inline int faultd_object_get_timespec(struct faultd_object *obj,
+ const char *key, struct timespec *val)
+{
+ return faultd_object_get_val(obj, key, TYPE_TIMESPEC, val);
+}
+
+static inline int faultd_object_get_time_t(struct faultd_object *obj,
+ const char *key, time_t *val)
+{
+ return faultd_object_get_val(obj, key, TYPE_TIME_T, val);
+}
+
+static inline int faultd_object_get_uuid(struct faultd_object *obj,
+ const char *key, sd_id128_t *val)
+{
+ return faultd_object_get_val(obj, key, TYPE_UUID, val);
+}
+
+int faultd_object_get_object(struct faultd_object *obj, const char *key, struct faultd_object **val);
+
+int faultd_object_fill_empty(struct faultd_object *obj);
+
+int faultd_oid_from_string(faultd_oid_t *oid, const char *s);
+
#endif /* FAULTD_COMMON_H */