return 0;
}
+
+
+int cgroup_dictionary_create(struct cgroup_dictionary **dict,
+ int flags)
+{
+ *dict = (struct cgroup_dictionary *) calloc(
+ 1, sizeof(struct cgroup_dictionary));
+
+ if (!dict)
+ return ECGFAIL;
+ (*dict)->flags = flags;
+ return 0;
+}
+
+
+int cgroup_dictionary_add(struct cgroup_dictionary *dict,
+ const char *name, const char *value)
+{
+ struct cgroup_dictionary_item *it;
+
+ if (!dict)
+ return ECGINVAL;
+
+ it = (struct cgroup_dictionary_item *) malloc(
+ sizeof(struct cgroup_dictionary_item));
+ if (!it)
+ return ECGFAIL;
+
+ it->next = NULL;
+ it->name = name;
+ it->value = value;
+
+ if (dict->tail) {
+ dict->tail->next = it;
+ dict->tail = it;
+ } else {
+ /* it is the first item */
+ dict->tail = it;
+ dict->head = it;
+ }
+ return 0;
+}
+
+int cgroup_dictionary_free(struct cgroup_dictionary *dict)
+{
+ struct cgroup_dictionary_item *it;
+
+ if (!dict)
+ return ECGINVAL;
+
+ it = dict->head;
+ while (it) {
+ struct cgroup_dictionary_item *del = it;
+ it = it->next;
+ if (!(dict->flags & CG_DICT_DONT_FREE_ITEMS)) {
+ free((void *)del->value);
+ free((void *)del->name);
+ }
+ free(del);
+ }
+
+ free(dict);
+ return 0;
+}
+
+int cgroup_dictionary_iterator_begin(struct cgroup_dictionary *dict,
+ void **handle, const char **name, const char **value)
+{
+ struct cgroup_dictionary_iterator *iter;
+
+ *handle = NULL;
+
+ if (!dict)
+ return ECGINVAL;
+
+ iter = (struct cgroup_dictionary_iterator *) malloc(
+ sizeof(struct cgroup_dictionary_iterator));
+ if (!iter)
+ return ECGFAIL;
+
+ iter->item = dict->head;
+ *handle = iter;
+ return cgroup_dictionary_iterator_next(handle, name, value);
+}
+
+int cgroup_dictionary_iterator_next(void **handle,
+ const char **name, const char **value)
+{
+ struct cgroup_dictionary_iterator *iter;
+
+ if (!handle)
+ return ECGINVAL;
+
+ iter = *handle;
+ if (!iter->item)
+ return ECGEOF;
+
+ *name = iter->item->name;
+ *value = iter->item->value;
+ iter->item = iter->item->next;
+ return 0;
+}
+
+void cgroup_dictionary_iterator_end(void **handle)
+{
+ if (!handle)
+ return;
+
+ free(*handle);
+ *handle = NULL;
+}
+
int flags;
};
+/**
+ * Internal item of dictionary. Linked list is sufficient for now - we need
+ * only 'add' operation and simple iterator. In future, this might be easily
+ * rewritten to dynamic array when random access is needed,
+ * just keep in mind that the order is important and the iterator should
+ * return the items in the order they were added there.
+ */
+struct cgroup_dictionary_item {
+ const char *name;
+ const char *value;
+ struct cgroup_dictionary_item *next;
+};
+
+/* Flags for cgroup_dictionary_create */
+/**
+ * All items (i.e. both name and value strings) stored in the dictionary
+ * should *NOT* be free()d on cgroup_dictionary_free(),
+ * only the dictionary helper structures (i.e. underlying linked list)
+ * should be freed.
+ */
+#define CG_DICT_DONT_FREE_ITEMS 1
+
+/**
+ * Dictionary of (name, value) items.
+ * The dictionary keeps its order, iterator iterates in the same order
+ * as the items were added there. It is *not* hash-style structure,
+ * it does not provide random access to its items nor quick search.
+ * This structure should be opaque to users of the dictionary, underlying data
+ * structure might change anytime and without warnings.
+ */
+struct cgroup_dictionary {
+ struct cgroup_dictionary_item *head;
+ struct cgroup_dictionary_item *tail;
+ int flags;
+};
+
+/** Opaque iterator of an dictionary. */
+struct cgroup_dictionary_iterator {
+ struct cgroup_dictionary_item *item;
+};
+
/**
* per thread errno variable, to be used when return code is ECGOTHER
*/
int cgroup_config_insert_into_namespace_table(char *name, char *mount_point);
void cgroup_config_cleanup_mount_table(void);
void cgroup_config_cleanup_namespace_table(void);
+
+/**
+ * Create an empty dictionary.
+ */
+extern int cgroup_dictionary_create(struct cgroup_dictionary **dict,
+ int flags);
+/**
+ * Add an item to existing dictionary.
+ */
+extern int cgroup_dictionary_add(struct cgroup_dictionary *dict,
+ const char *name, const char *value);
+/**
+ * Fully destroy existing dictionary. Depending on flags passed to
+ * cgroup_dictionary_create(), names and values might get destroyed too.
+ */
+extern int cgroup_dictionary_free(struct cgroup_dictionary *dict);
+
+/**
+ * Start iterating through a dictionary. The items are returned in the same
+ * order as they were added using cgroup_dictionary_add().
+ */
+extern int cgroup_dictionary_iterator_begin(struct cgroup_dictionary *dict,
+ void **handle, const char **name, const char **value);
+/**
+ * Continue iterating through the dictionary.
+ */
+extern int cgroup_dictionary_iterator_next(void **handle,
+ const char **name, const char **value);
+/**
+ * Finish iteration through the dictionary.
+ */
+extern void cgroup_dictionary_iterator_end(void **handle);
+
__END_DECLS
#endif