* [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
@ 2007-04-20 13:34 Karl MacMillan
2007-04-20 19:55 ` Eamon Walsh
2007-04-24 16:42 ` Stephen Smalley
0 siblings, 2 replies; 17+ messages in thread
From: Karl MacMillan @ 2007-04-20 13:34 UTC (permalink / raw)
To: selinux
Add a generic iterator data structure and a linked-list implementation
based that uses the iterators to libsepol. Includes test cases for the
linked-list implementation.
This version is updated to remove improper use of void** based on comments
from James Antill.
Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
---
libsepol/include/sepol/errcodes.h | 3
libsepol/include/sepol/iter.h | 237 +++++++++++++++++++++
libsepol/include/sepol/list.h | 234 +++++++++++++++++++++
libsepol/src/iter.c | 186 ++++++++++++++++
libsepol/src/list.c | 419 +++++++++++++++++++++++++++++++++++++
libsepol/tests/libsepol-tests.c | 2
libsepol/tests/test-list.c | 373 +++++++++++++++++++++++++++++++++
libsepol/tests/test-list.h | 12 +
8 files changed, 1466 insertions(+), 0 deletions(-)
diff --git a/libsepol/include/sepol/errcodes.h b/libsepol/include/sepol/errcodes.h
index c6f3a8b..91cf569 100644
--- a/libsepol/include/sepol/errcodes.h
+++ b/libsepol/include/sepol/errcodes.h
@@ -22,4 +22,7 @@
#define SEPOL_EEXIST -EEXIST
#define SEPOL_ENOENT -ENOENT
+/* Custom error codes */
+#define SEPOL_ITERSTOP -500
+
#endif
diff --git a/libsepol/include/sepol/iter.h b/libsepol/include/sepol/iter.h
new file mode 100644
index 0000000..b95d9ca
--- /dev/null
+++ b/libsepol/include/sepol/iter.h
@@ -0,0 +1,237 @@
+/* Author : Karl MacMillan <kmacmillan@mentalrootkit.com> */
+
+#ifndef __sepol_iter_h__
+#define __sepol_iter_h__
+
+#include <sepol/handle.h>
+
+/**
+ * \defgroup libsepol_iter sepol_iter: generic iterators
+ * Iterators represent a position within a data structure. They are a
+ * generalization of the concept of pointers. Using iterators allows
+ * algorithms to be cleanly separated from data structures by
+ * abstracting the concept of position and movement. Once an iterator
+ * is created and its position initialized in a data structure
+ * specific way, looping and other control flow can be implemented
+ * only using the generic iterator functions.
+ *
+ * For example, consider the code below which loops through a list
+ * (the error handling and some initialization is ommitted for brevity):
+ * \code
+ * int ret;
+ * struct sepol_iter *iter;
+ * struct sepol_handle *h;
+ *
+ * sepol_iter_create(h, &iter);
+ * ret = sepol_list_begin(h, iter);
+ *
+ * while (ret == SEPOL_OK) {
+ * // process the data
+ * data = sepol_iter_get_data(h, iter);
+ * ret = sepol_iter_next(h, iter);
+ * }
+ * if (ret != SEPOL_ITERSTOP)
+ * // handle errors
+ * \endcode
+ */
+
+/**
+ * \ingroup libsepol_iter
+ * \struct sepol_iter
+ *
+ * Iterator data structuer.
+ *
+ * @see libsepol_iter
+ */
+struct sepol_iter;
+
+/**
+ * \ingroup libsepol_iter
+ * Create an iterator. The iterator is not valid
+ * until a data structure specific call has been
+ * made to initiliaze its position (e.g., sepol_list_begin).
+ *
+ * @param h sepol handle (can be NULL)
+ * @param iter pointer to allocated iterator
+ *
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ENOMEM out of memory
+ */
+extern int sepol_iter_create(struct sepol_handle *h, struct sepol_iter **iter);
+
+/**
+ * \ingroup libsepol_iter
+ * Free an iterator. This has no effect on the data structure or items
+ * that the iterator may represent - only the iterator is destroyed.
+ *
+ * @param h sepol handle (can be NULL)
+ * @param iter iterator to destroy
+ *
+ * \retval SEPOL_OK success
+ * \retval <0 other errors specific to the underlying data structure
+ */
+extern int sepol_iter_free(struct sepol_handle *h, struct sepol_iter *iter);
+
+/**
+ * \ingroup libsepol_iter
+ * Make a copy of an iterator. The new iterator will be at the
+ * same position as the old iterator.
+ *
+ * Warning: Not all iterators support copying. See the data structure
+ * documentation for details on whether iterators to a specific
+ * data structure support copying.
+ *
+ * @param h sepol handle (can be NULL)
+ * @param iter iterator to copy
+ * @param new_iter newly created iterator which is a copy of iter
+ *
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ENOMEM out of memory
+ * \retval SEPOL_ENOTSUP iterator copying not supported
+ */
+extern int sepol_iter_clone(struct sepol_handle *h, const struct sepol_iter *iter,
+ struct sepol_iter **new_iter);
+
+/**
+ * \ingroup libsepol_iter
+ * Return the data at this iterator location. The type
+ * of the returned data is data structure specific.
+ *
+ * @param h sepol handle (can be NULL)
+ * @param iter iterator from which to return data
+ *
+ * \retval non-NULL the data
+ * \retval NULL error
+ */
+extern void *sepol_iter_get_data(struct sepol_handle *h, struct sepol_iter *iter);
+
+/**
+ * \ingroup libsepol_iter
+ *
+ * Move the iterator to the next position. If SEPOL_ITERSTOP is
+ * returned, one past the end of the data structure has been reached.
+ * After SEPOL_ITERSTOP has been returned No other calls using this
+ * iterator are valid until a data structure specific call has been
+ * made to reset it to a valid position (e.g., sepol_list_begin).
+ *
+ * @param h sepol handle (can be NULL)
+ * @param iter iterator to advance
+ *
+ * \retval SEPOL_OK iterator successfully moved
+ * \retval SEPOL_ITERSTOP iteration should stop
+ * \retval <0 other errors specific to the underlying data structure
+ */
+extern int sepol_iter_next(struct sepol_handle *h, struct sepol_iter *iter);
+
+/**
+ * \ingroup libsepol_iter
+ * Move the iterator to the prev position. If SEPOL_ITERSTOP is
+ * returned, one before the beginning of the data structure has been
+ * reached. No other calls using this iterator are valid until a data
+ * structure specific call has been made to reset it to a valid
+ * position (e.g., sepol_list_end).
+ *
+ * Not all iterators support prev - the data structure specific
+ * iterator documentation should indicate whether prev is supported.
+ *
+ * @param h sepol handle (can be NULL)
+ * @param iter iterator to move to the previous position
+ *
+ * \retval SEPOL_OK iterator successfully moved
+ * \retval SEPOL_ITERSTOP iteration should stop
+ * \retval SEPOL_ENOTSUP previous iterator not supported for this
+ * data structure.
+ * \retval <0: other errors specific to the underlying data structure
+ */
+extern int sepol_iter_prev(struct sepol_handle *h, struct sepol_iter *iter);
+
+/**
+ * \ingroup libsepol_iter
+ * Move the iterator forward by distance. This does _not_ set the
+ * absolute position of the iterator. Rather, it moves in by distance
+ * from the current position. For example, moving an iterator at
+ * position 2 by 3 would put the iterator at position 5.
+ *
+ * @param h sepol handle (can be NULL)
+ * @param iter iterator to move forward
+ * @param distance distance to move iterator forward
+ *
+ * \retval SEPOL_OK iterator successfully moved
+ * \retval SEPOL_ITERSTOP iteration should stop
+ * \retval SEPOL_ENOTSUP previous iterator not supported for this
+ * data structure.
+ * \retval <0: other errors specific to the underlying data structure
+ */
+extern int sepol_iter_forward(struct sepol_handle *h, struct sepol_iter *iter,
+ unsigned int distance);
+
+/**
+ * \ingroup libsepol_iter
+ * Move the iterator backward by distance. This does _not_ set the
+ * absolute position of the iterator. Rather, it moves in by distance
+ * from the current position. For example, moving an iterator at
+ * position 2 by 1 would put the iterator at position 1.
+ *
+ * Iterator must support sepol_iter_prev.
+ *
+ * @param h sepol handle (can be NULL)
+ * @param iter iterator to move backward
+ * @param distance distance to move iterator
+ *
+ * \retval SEPOL_OK iterator successfully moved
+ * \retval SEPOL_ITERSTOP iteration should stop
+ * \retval SEPOL_ENOTSUP previous iterator not supported for this
+ * data structure.
+ * \retval <0: other errors specific to the underlying data structure
+ */
+extern int sepol_iter_backward(struct sepol_handle *h, struct sepol_iter *iter,
+ unsigned int distance);
+
+/**
+ * \ingroup libsepol_iter
+ * \def sepol_foreach
+ * Iterate over a sequence in a for-loop-like manner. This
+ * macro is a convenience wrapper around sepol_iter_next
+ * and sepol_iter_get_state. For example:
+ *
+ * \code
+ * int ret;
+ * struct sepol_iter *iter;
+ * char *name;
+ * // initialization omitted
+ * ret = sepol_list_begin(h, list, iter);
+ * sepol_foreach(h, ret, name, iter) {
+ * printf("%s\n", name);
+ * }
+ * if (ret != SEPOL_ITERSTOP)
+ * // handle error
+ * \endcode
+ *
+ * @param h sepol handle (can be NULL)
+ * @param ret int variable used to hold the return value
+ * of functions called by the macro.
+ * @param cur variable used to hold the results of sepol_iter_get_data.
+ * The type of the variable must be appropriate for the data stored
+ * in the data structure.
+ * @param iter iterator initialized to a valid position (e.g., after
+ * a call to sepol_list_begin).
+ */
+#define sepol_foreach(h, ret, cur, iter) \
+ for (; ret == SEPOL_OK && (cur = sepol_iter_get_data(h, iter)); \
+ ret = sepol_iter_next(h, iter)) \
+
+
+/* used by implementations of iterators */
+extern void sepol_iter_set_state(struct sepol_iter *iter, void *state);
+extern void *sepol_iter_get_state(const struct sepol_iter *iter);
+extern void sepol_iter_set_next(struct sepol_iter *iter,
+ int (*next)(struct sepol_handle *, struct sepol_iter *));
+extern void sepol_iter_set_prev(struct sepol_iter *iter,
+ int (*prev)(struct sepol_handle *, struct sepol_iter *));
+extern void sepol_iter_set_get_data(struct sepol_iter *iter,
+ void *(*get)(struct sepol_handle *, struct sepol_iter *));
+extern void sepol_iter_set_free(struct sepol_iter *iter, int (*state_free)(struct sepol_handle *, void *data));
+extern void sepol_iter_set_clone(struct sepol_iter *iter,
+ int (*clone)(struct sepol_handle *, const struct sepol_iter *old, struct sepol_iter *new_iter));
+
+#endif
diff --git a/libsepol/include/sepol/list.h b/libsepol/include/sepol/list.h
new file mode 100644
index 0000000..c9dd229
--- /dev/null
+++ b/libsepol/include/sepol/list.h
@@ -0,0 +1,234 @@
+/* Author : Karl MacMillan <kmacmillan@mentalrootkit.com> */
+
+
+#ifndef __sepol_list_h__
+#define __sepol_list_h__
+
+#include <sepol/iter.h>
+
+/**
+ * \defgroup libsepol_list sepol_list: doubly-linked lists
+ * Doubly-linked list data type.
+ *
+ * The sepol_list data type represents a doubly-linked list.
+ * It supports:
+ * - forward and backward iteration using sepol_iter.
+ * - prepending and appending in constant time.
+ * - getting the length in constant time.
+ * - insertion and deletion.
+ * - stack / queue like usage (via sepol_list_pop_front and
+ * sepol_list_pop_back).
+ *
+ * This list implementation is designed to be generic by storing
+ * void pointers as the objects. These pointers are not interpreted
+ * or manipulated in any way. This means that the memory for the
+ * objects is *not* managed with the rest of the list (e.g.,
+ * sepol_list_free only destroys the memory for the list not the
+ * items stored in the list). This also means that the list is not
+ * ideal for storing simple types (like ints) because they need to
+ * be allocated.
+ *
+ * @see sepol_iter
+ */
+
+/**
+ * \ingroup libsepol_list
+ * \struct sepol_list
+ * Doubly-linked list struct type.
+ *
+ * @see libsepol_list
+ */
+struct sepol_list;
+
+/**
+ * \ingroup libsepol_list
+ * Create an sepol_list. On success, SEPOL_OK is returned
+ * and the list pointer passed in is set to an allocated
+ * sepol_list struct that has been initialized.
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list pointer to a list pointer for returning the
+ * newly created list.
+ *
+ * \retval SEPOL_OK list successfully created
+ * \retval SEPOL_ENOMEM out of memory
+ */
+extern int sepol_list_create(struct sepol_handle *h, struct sepol_list **list);
+
+/**
+ * \ingroup libsepol_list
+ * Destroy an sepol_list. This will _not_ free the memory
+ * for the list items, only for the internal list structures.
+ * The list items memory should be freed by the caller.
+ *
+ * @param list list to destroy
+ */
+extern void sepol_list_free(struct sepol_list *list);
+
+/**
+ * \ingroup libsepol_list
+ * Return the lenght of the list. This is a constant time
+ * operation.
+ *
+ * @param list list object
+ *
+ * \returns length of the list
+ */
+extern unsigned int sepol_list_length(struct sepol_list *list);
+
+/**
+ * \ingroup libsepol_list
+ * Append an item to the list. If successful, the item will
+ * become the last item in the list.
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list to which to append
+ * @param item to append
+ *
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ENOMEM out of memory
+ */
+extern int sepol_list_append(struct sepol_handle *h, struct sepol_list *list,
+ void *item);
+
+/**
+ * \ingroup libsepol_list
+ * Prepend an item to the list. If successful, the item will
+ * become the first item in the list.
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list to which to prepend
+ * @param item to prepend
+ *
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ENOMEM out of memory
+ */
+extern int sepol_list_prepend(struct sepol_handle *h, struct sepol_list *list,
+ void *item);
+
+/**
+ * \ingroup libsepol_list
+ * Insert an item before the iterator position. The existing item is
+ * shifted to the next position in the list. The iterator continues to
+ * point at the same item, though the position of that item will have
+ * moved forward by one.
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list to which to insert
+ * @param iter iter representing the insertion position
+ * @param item item to insert
+ *
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ENOMEM out of memory
+ */
+extern int sepol_list_insert(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter, void *item);
+
+/**
+ * \ingroup libsepol_list
+ * Insert into the list all of the items returned by the iter. This method
+ * is useful for inserting all of the items from another data structure
+ * into the list (because a standard iterator is used any data structure that
+ * supports iteratoration can be used).
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list to extend
+ * @param iter iterator for data to extend
+ *
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ENOMEM out of memory
+ */
+extern int sepol_list_extend(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter);
+
+/**
+ * \ingroup libsepol_list
+ * Convenience function to extend a list with another list. Internally, simply
+ * creates a an iter pointing to the beginning of the list and calls
+ * sepol_list_extend.
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list to extend
+ * @param other source list
+ *
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ENOMEM out of memory
+ */
+extern int sepol_list_extend_list(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_list *other);
+
+/**
+ * \ingroup libsepol_list
+ * Remove and return the first item in the list. Item will be set
+ * to the item if the operation was successful.
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list from which to pop item
+ * @param item pointer that will be set to the popped item
+ *
+ * \retval SEPOL_OK succss
+ * \retval SEPOL_ERANGE empty list
+ */
+extern int sepol_list_pop_front(struct sepol_handle *h, struct sepol_list *list,
+ void **item);
+
+/**
+ * \ingroup libsepol_list
+ * Remove and return the last item in the list. Item will be set
+ * to the item if the operation was successful.
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list from which to pop item
+ * @param item that will be set to the popped item
+ *
+ * \retval SEPOL_OK succss
+ * \retval SEPOL_ERANGE: empty list
+ */
+extern int sepol_list_pop_back(struct sepol_handle *h, struct sepol_list *list,
+ void **item);
+
+/**
+ * \ingroup libsepol_list
+ * Delete an item at the iterator position. The iterator is no longer
+ * valid after deletion (if continued iteration is needed, the iterator
+ * should be copied and the copy advanced prior to deletion).
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list from which to delete item
+ * @param iter representing the position of the item to delete
+ *
+ * \retval SEPOL_OK success
+ */
+extern int sepol_list_del(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter);
+
+/**
+ * \ingroup libsepol_list
+ * Position the iterator at the beginning of the list. If the list
+ * is empty SEPOL_ITERSTOP will be returned and the iterator will not
+ * be valid.
+ *
+ * @param h sepol handle (may be NULL)
+ * @param list list to iterate over
+ * @param iter iterator to set to list beginning
+ *
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ITERSTOP empty list
+ */
+extern int sepol_list_begin(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter);
+
+/**
+ * \ingroup libsepol_list
+ * Position the iterator at the end of the list. If the list
+ * is empty SEPOL_ITERSTOP will be returned and the iterator will not
+ * be valid.
+ *
+ * @param h sepol handle (may be NULL)
+ * \retval SEPOL_OK success
+ * \retval SEPOL_ITERSTOP empty list
+ */
+extern int sepol_list_end(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter);
+
+#endif
diff --git a/libsepol/src/iter.c b/libsepol/src/iter.c
new file mode 100644
index 0000000..4762bdb
--- /dev/null
+++ b/libsepol/src/iter.c
@@ -0,0 +1,186 @@
+/*
+ * Author : Karl MacMillan <kmacmillan@mentalrootkit.com>
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <sepol/iter.h>
+#include <sepol/errcodes.h>
+
+#include "debug.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+struct sepol_iter
+{
+ void *state;
+ int (*next)(struct sepol_handle *, struct sepol_iter *);
+ int (*prev)(struct sepol_handle *, struct sepol_iter *);
+ void *(*get)(struct sepol_handle *, struct sepol_iter *);
+ int (*clone)(struct sepol_handle *, const struct sepol_iter *, struct sepol_iter *);
+ int (*free_fn)(struct sepol_handle *, void *);
+};
+
+int sepol_iter_create(struct sepol_handle *h, struct sepol_iter **iter)
+{
+ *iter = (struct sepol_iter*)calloc(1, sizeof(struct sepol_iter));
+ if (*iter == NULL) {
+ ERR(h, "out of memory");
+ return SEPOL_ENOMEM;
+ }
+
+ return SEPOL_OK;
+}
+
+int sepol_iter_free(struct sepol_handle *h, struct sepol_iter *iter)
+{
+ int ret;
+ if (iter->free_fn != NULL) {
+ ret = iter->free_fn(h, iter->state);
+ }
+ free(iter);
+
+ return ret;
+}
+
+int sepol_iter_clone(struct sepol_handle *h, const struct sepol_iter *iter,
+ struct sepol_iter **new_iter)
+{
+ int ret;
+
+ if (iter->clone == NULL) {
+ ERR(h, "iterator copying not supported");
+ return SEPOL_ENOTSUP;
+ }
+
+ ret = sepol_iter_create(h, new_iter);
+ if (ret < 0)
+ return ret;
+
+ return iter->clone(h, iter, *new_iter);
+}
+
+void *sepol_iter_get_data(struct sepol_handle *h, struct sepol_iter *iter)
+{
+ assert(iter);
+ assert(iter->get);
+
+ return iter->get(h, iter);
+}
+
+int sepol_iter_next(struct sepol_handle *h, struct sepol_iter *iter)
+{
+ assert(iter);
+ assert(iter->next);
+
+ return iter->next(h, iter);
+}
+
+int sepol_iter_prev(struct sepol_handle *h, struct sepol_iter *iter)
+{
+ assert(iter);
+
+ if (iter->prev == NULL) {
+ ERR(h, "iterator previous not supported");
+ return SEPOL_ENOTSUP;
+ }
+
+ return iter->prev(h, iter);
+}
+
+/* At some point forward and backward should be overridable by
+ * the data structures. Depending on the data structure there
+ * could be significant performance improvements by directly
+ * implementing forward and backward.
+ */
+int sepol_iter_forward(struct sepol_handle *h, struct sepol_iter *iter,
+ unsigned int distance)
+{
+ unsigned int i = 0;
+ int ret = SEPOL_OK;
+
+ while (i < distance && ret == SEPOL_OK) {
+ ret = sepol_iter_next(h, iter);
+ i++;
+ }
+
+ return ret;
+}
+
+int sepol_iter_backward(struct sepol_handle *h, struct sepol_iter *iter,
+ unsigned int distance)
+{
+ unsigned int i = 0;
+ int ret = SEPOL_OK;
+
+ while (i < distance && ret == SEPOL_OK) {
+ ret = sepol_iter_prev(h, iter);
+ i++;
+ }
+
+ return ret;
+}
+
+void sepol_iter_set_state(struct sepol_iter *iter, void *state)
+{
+ assert(iter);
+ if (iter->state && iter->free_fn)
+ iter->free_fn(NULL, iter->state);
+ iter->state = state;
+}
+
+void *sepol_iter_get_state(const struct sepol_iter *iter)
+{
+ assert(iter);
+ return iter->state;
+}
+
+void sepol_iter_set_next(struct sepol_iter *iter,
+ int (*next)(struct sepol_handle *, struct sepol_iter *))
+{
+ assert(iter);
+ iter->next = next;
+}
+
+void sepol_iter_set_prev(struct sepol_iter *iter,
+ int (*prev)(struct sepol_handle *, struct sepol_iter *))
+{
+ assert(iter);
+ iter->prev = prev;
+}
+
+void sepol_iter_set_get_data(struct sepol_iter *iter,
+ void *(*get)(struct sepol_handle *, struct sepol_iter *))
+{
+ assert(iter);
+ iter->get = get;
+}
+
+void sepol_iter_set_free(struct sepol_iter *iter, int (*state_free)(struct sepol_handle *, void *))
+{
+ assert(iter);
+ iter->free_fn = state_free;
+}
+
+void sepol_iter_set_clone(struct sepol_iter *iter,
+ int (*clone)(struct sepol_handle *, const struct sepol_iter *old, struct sepol_iter *new_iter))
+{
+ assert(iter);
+ iter->clone = clone;
+}
diff --git a/libsepol/src/list.c b/libsepol/src/list.c
new file mode 100644
index 0000000..a2d8a6c
--- /dev/null
+++ b/libsepol/src/list.c
@@ -0,0 +1,419 @@
+/*
+ * Author : Karl MacMillan <kmacmillan@mentalrootkit.com>
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <sepol/errcodes.h>
+
+#include <sepol/list.h>
+#include <sepol/iter.h>
+
+#include "debug.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct sepol_list_item
+{
+ struct sepol_list_item *next;
+ struct sepol_list_item *prev;
+ void *item;
+};
+
+struct sepol_list
+{
+ struct sepol_list_item *head;
+ struct sepol_list_item *tail;
+ unsigned int len;
+};
+
+int sepol_list_create(struct sepol_handle *h, struct sepol_list **list)
+{
+ assert(list);
+
+ *list = (struct sepol_list *)calloc(1, sizeof(struct sepol_list));
+ if (*list == NULL) {
+ ERR(h, "out of memory");
+ return SEPOL_ENOMEM;
+ }
+
+ return SEPOL_OK;
+}
+
+void sepol_list_free(struct sepol_list *list)
+{
+ struct sepol_list_item *cur, *next;
+
+ if (list == NULL)
+ return;
+
+ cur = list->head;
+ while (cur != NULL) {
+ next = cur->next;
+ free(cur);
+ cur = next;
+ }
+
+ free(list);
+}
+
+unsigned int sepol_list_length(struct sepol_list *list)
+{
+ assert(list);
+ return list->len;
+}
+
+static int sepol_list_item_create(struct sepol_handle *h,
+ struct sepol_list_item **x)
+{
+ *x = calloc(1, sizeof(struct sepol_list_item));
+ if (*x == NULL) {
+ ERR(h, "out of memory");
+ return SEPOL_ENOMEM;
+ } else {
+ return SEPOL_OK;
+ }
+}
+
+int sepol_list_append(struct sepol_handle *h, struct sepol_list *list, void *item)
+{
+ int ret;
+ struct sepol_list_item *x;
+
+ assert(list);
+
+ ret = sepol_list_item_create(h, &x);
+ if (ret < 0)
+ return ret;
+ x->item = item;
+
+ /* empty list */
+ if (list->tail == NULL) {
+ list->tail = x;
+ list->head = x;
+ x->prev = NULL;
+ x->next = NULL;
+ } else {
+ /* non-empty list */
+ list->tail->next = x;
+ x->prev = list->tail;
+ x->next = NULL;
+ list->tail = x;
+ }
+
+ list->len++;
+ return SEPOL_OK;
+}
+
+int sepol_list_prepend(struct sepol_handle *h, struct sepol_list *list, void *item)
+{
+ int ret;
+ struct sepol_list_item *x;
+
+ assert(list);
+
+ ret = sepol_list_item_create(h, &x);
+ if (ret < 0)
+ return ret;
+ x->item = item;
+
+ /* empty list */
+ if (list->tail == NULL) {
+ list->tail = x;
+ list->head = x;
+ x->prev = NULL;
+ x->next = NULL;
+ } else {
+ x->next = list->head;
+ list->head->prev = x;
+ x->prev = NULL;
+ list->head = x;
+ }
+
+ list->len++;
+ return SEPOL_OK;
+}
+
+int sepol_list_insert(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter, void *item)
+{
+ int ret;
+ struct sepol_list_item *x, *cur;
+
+ assert(list);
+
+ cur = (struct sepol_list_item*)sepol_iter_get_state(iter);
+ assert(cur);
+
+ /* Short circuit for prepend and append. */
+ if (list->head == cur) {
+ return sepol_list_prepend(h, list, item);
+ } else if (list->tail == cur) {
+ return sepol_list_append(h, list, item);
+ }
+
+ ret = sepol_list_item_create(h, &x);
+ if (ret < 0)
+ return ret;
+ x->item = item;
+
+ x->prev = cur->prev;
+ x->prev->next = x;
+ x->next = cur;
+ cur->prev = x;
+
+ list->len++;
+ return SEPOL_OK;
+}
+
+int sepol_list_extend(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter)
+{
+ int ret = SEPOL_OK;
+ void *data;
+
+ while (ret == SEPOL_OK) {
+ data = sepol_iter_get_data(h, iter);
+ if (!data)
+ return SEPOL_ERR;
+ ret = sepol_list_append(h, list, data);
+ if (ret < 0)
+ return ret;
+
+ ret = sepol_iter_next(h, iter);
+ }
+ if (ret != SEPOL_ITERSTOP)
+ return ret;
+ else
+ return SEPOL_OK;
+}
+
+int sepol_list_extend_list(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_list *other)
+{
+ int ret;
+ struct sepol_iter *iter;
+
+ if (!other->len)
+ return SEPOL_OK;
+
+ ret = sepol_iter_create(h, &iter);
+ if (ret < 0)
+ return ret;
+
+ ret = sepol_list_begin(h, other, iter);
+ if (ret < 0)
+ goto out;
+ ret = sepol_list_extend(h, list, iter);
+
+out:
+ sepol_iter_free(h, iter);
+ return ret;
+}
+
+
+int sepol_list_pop_front(struct sepol_handle *h, struct sepol_list *list,
+ void **item)
+{
+ struct sepol_list_item *cur;
+
+ if (list->head == NULL)
+ return SEPOL_ERANGE;
+
+ cur = list->head;
+ if (list->head == list->tail) {
+ list->head = NULL;
+ list->tail = NULL;
+ } else {
+ list->head = list->head->next;
+ if (list->head)
+ list->head->prev = NULL;
+ }
+
+ *item = cur->item;
+ free(cur);
+
+ return SEPOL_OK;
+}
+
+int sepol_list_pop_back(struct sepol_handle *h, struct sepol_list *list,
+ void **item)
+{
+ struct sepol_list_item *cur;
+
+ if (list->tail == NULL)
+ return SEPOL_ERANGE;
+
+ cur = list->tail;
+
+ if (list->head == list->tail) {
+ list->head = NULL;
+ list->tail = NULL;
+ } else {
+ list->tail = list->tail->prev;
+ if (list->tail)
+ list->tail->next = NULL;
+ }
+
+ *item = cur->item;
+ free(cur);
+
+ return SEPOL_OK;
+}
+
+
+int sepol_list_del(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter)
+{
+ struct sepol_list_item *cur;
+
+ cur = sepol_iter_get_state(iter);
+ assert(cur);
+
+ if (list->head == cur && list->tail == cur) {
+ list->head = NULL;
+ list->tail = NULL;
+ goto out;
+ }
+
+ if (cur->prev)
+ cur->prev->next = cur->next;
+ else
+ list->head = cur->next;
+
+ if (cur->next)
+ cur->next->prev = cur->prev;
+ else
+ list->tail = cur->prev;
+
+out:
+ free(cur);
+ list->len--;
+ sepol_iter_set_state(iter, NULL);
+ return SEPOL_OK;
+}
+
+static int sepol_list_next(struct sepol_handle *h, struct sepol_iter *iter)
+{
+ struct sepol_list_item *cur;
+
+ assert(iter);
+
+ cur = (struct sepol_list_item*)sepol_iter_get_state(iter);
+ assert(cur);
+
+ if (cur->next == NULL) {
+ /* set the state to NULL to catch using this iterator
+ * after ITERSTOP is returned (which is a bug). */
+ sepol_iter_set_state(iter, NULL);
+ return SEPOL_ITERSTOP;
+ } else {
+ sepol_iter_set_state(iter, cur->next);
+ return SEPOL_OK;
+ }
+}
+
+static int sepol_list_prev(struct sepol_handle *h, struct sepol_iter *iter)
+{
+ struct sepol_list_item *cur;
+
+ assert(iter);
+
+ cur = (struct sepol_list_item*)sepol_iter_get_state(iter);
+ assert(cur);
+
+ if (cur->prev == NULL) {
+ /* set the state to NULL to catch using this iterator
+ * after ITERSTOP is returned (which is a bug). */
+ sepol_iter_set_state(iter, NULL);
+ return SEPOL_ITERSTOP;
+ } else {
+ sepol_iter_set_state(iter, cur->prev);
+ return SEPOL_OK;
+ }
+}
+
+static void *sepol_list_iter_get_data(struct sepol_handle *h, struct sepol_iter *iter)
+{
+ struct sepol_list_item *cur;
+
+ assert(iter);
+
+ cur = (struct sepol_list_item*)sepol_iter_get_state(iter);
+ if (!cur) {
+ return NULL;
+ }
+
+ return cur->item;
+}
+
+
+static int sepol_list_iter_clone(struct sepol_handle *h, const struct sepol_iter *o,
+ struct sepol_iter *n);
+
+#define ITERSETUP(iter) { sepol_iter_set_next(iter, sepol_list_next); \
+ sepol_iter_set_prev(iter, sepol_list_prev); \
+ sepol_iter_set_clone(iter, sepol_list_iter_clone); \
+ sepol_iter_set_get_data(iter, sepol_list_iter_get_data); }
+
+static int sepol_list_iter_clone(struct sepol_handle *h, const struct sepol_iter *o,
+ struct sepol_iter *n)
+{
+ void *state = sepol_iter_get_state(o);
+ sepol_iter_set_state(n, state);
+
+ ITERSETUP(n);
+
+ return SEPOL_OK;
+}
+
+
+int sepol_list_begin(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter)
+{
+ assert(list);
+ assert(iter);
+
+ if (list->head == NULL)
+ return SEPOL_ITERSTOP;
+
+ sepol_iter_set_state(iter, list->head);
+
+ ITERSETUP(iter);
+
+ return SEPOL_OK;
+}
+
+int sepol_list_end(struct sepol_handle *h, struct sepol_list *list,
+ struct sepol_iter *iter)
+{
+ assert(list);
+ assert(iter);
+
+ if (list->tail == NULL)
+ return SEPOL_ITERSTOP;
+
+ sepol_iter_set_state(iter, list->tail);
+
+ ITERSETUP(iter);
+
+ return SEPOL_OK;
+}
+
+
diff --git a/libsepol/tests/libsepol-tests.c b/libsepol/tests/libsepol-tests.c
index dced1c3..c548cdd 100644
--- a/libsepol/tests/libsepol-tests.c
+++ b/libsepol/tests/libsepol-tests.c
@@ -22,6 +22,7 @@
#include "test-linker.h"
#include "test-expander.h"
#include "test-deps.h"
+#include "test-list.h"
#include <CUnit/Basic.h>
#include <CUnit/Console.h>
@@ -61,6 +62,7 @@ static int do_tests(int interactive, int verbose)
DECLARE_SUITE(linker);
DECLARE_SUITE(expander);
DECLARE_SUITE(deps);
+ DECLARE_SUITE(list);
if (verbose)
CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsepol/tests/test-list.c b/libsepol/tests/test-list.c
new file mode 100644
index 0000000..d19a292
--- /dev/null
+++ b/libsepol/tests/test-list.c
@@ -0,0 +1,373 @@
+/*
+ * Author : Karl MacMillan <kmacmillan@mentalrootkit.com>
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "test-list.h"
+
+#include <sepol/list.h>
+#include <sepol/iter.h>
+#include <sepol/errcodes.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int list_test_init(void)
+{
+ return 0;
+}
+
+int list_test_cleanup(void)
+{
+ return 0;
+}
+
+static void test_list_create(void)
+{
+ struct sepol_list *list;
+ int ret;
+
+ ret = sepol_list_create(NULL, &list);
+ CU_ASSERT(ret == 0);
+
+ sepol_list_free(list);
+}
+
+static void test_list(void)
+{
+ struct sepol_list *list;
+ struct sepol_iter *iter, *iter2;
+ struct sepol_handle *h;
+ int ret;
+ int i, *num, nums[6];
+
+ for (i = 0; i < 6; i++)
+ nums[i] = i;
+
+ h = sepol_handle_create();
+ CU_ASSERT(h != NULL);
+
+ ret = sepol_iter_create(h, &iter);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_create(h, &list);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_append(h, list, &nums[4]);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_append(h, list, &nums[5]);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_prepend(h, list, &nums[1]);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_begin(h, list, iter);
+ CU_ASSERT(ret == 0);
+ ret = sepol_iter_forward(h, iter, 1);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_insert(h, list, iter, &nums[2]);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_begin(h, list, iter);
+ CU_ASSERT(ret == 0);
+ ret = sepol_list_insert(h, list, iter, &nums[0]);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_begin(h, list, iter);
+ CU_ASSERT(ret == 0);
+ ret = sepol_iter_forward(h, iter, 3);
+ CU_ASSERT(ret == 0);
+
+ ret = sepol_list_insert(h, list, iter, &nums[3]);
+ CU_ASSERT(ret == 0);
+
+ CU_ASSERT(sepol_list_length(list) == 6);
+
+ ret = sepol_list_begin(h, list, iter);
+ CU_ASSERT(ret == 0);
+ i = 0;
+
+ sepol_foreach(h, ret, num, iter) {
+ CU_ASSERT(*num == i);
+ i++;
+ }
+
+ CU_ASSERT(i == 6);
+ CU_ASSERT(ret == SEPOL_ITERSTOP);
+
+ ret = sepol_list_end(h, list, iter);
+ CU_ASSERT(ret == 0);
+ i = 5;
+ while (ret == SEPOL_OK) {
+ num = (int *)sepol_iter_get_data(h, iter);
+ CU_ASSERT(num != NULL);
+ CU_ASSERT(*num == i);
+ i--;
+ ret = sepol_iter_prev(h, iter);
+ }
+ CU_ASSERT(i == -1);
+ CU_ASSERT(ret == SEPOL_ITERSTOP);
+
+ ret = sepol_list_end(h, list, iter);
+ CU_ASSERT(ret == 0);
+ ret = sepol_iter_prev(h, iter);
+ CU_ASSERT(ret == 0);
+ num = (int *)sepol_iter_get_data(h, iter);
+ CU_ASSERT(num != NULL);
+ CU_ASSERT(*num == 4);
+
+
+ ret = sepol_list_begin(h, list, iter);
+ CU_ASSERT(ret == 0);
+ i = 0;
+ while (ret == SEPOL_OK) {
+ if (i == 2) {
+ ret = sepol_iter_clone(h, iter, &iter2);
+ CU_ASSERT(ret == SEPOL_OK);
+ ret = sepol_iter_next(h, iter);
+ CU_ASSERT(ret == SEPOL_OK);
+ ret = sepol_list_del(h, list, iter2);
+ CU_ASSERT(ret == SEPOL_OK);
+ i++;
+ continue;
+ }
+ i++;
+ ret = sepol_iter_next(h, iter);
+ }
+ CU_ASSERT(ret == SEPOL_ITERSTOP);
+ CU_ASSERT(i == 6);
+ CU_ASSERT(sepol_list_length(list) == 5);
+
+ sepol_iter_free(h, iter);
+ sepol_iter_free(h, iter2);
+ sepol_list_free(list);
+ sepol_handle_destroy(h);
+}
+
+static void test_list_pop(void)
+{
+ int ret;
+ struct sepol_list *list;
+ struct sepol_handle *h;
+ void *item;
+
+ h = sepol_handle_create();
+ CU_ASSERT(h != NULL);
+
+ ret = sepol_list_create(h, &list);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, list, "webern");
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, list, "berg");
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, list, "schoenberg");
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, list, "sessions");
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_pop_back(h, list, &item);
+ CU_ASSERT(ret == SEPOL_OK);
+ CU_ASSERT(strcmp((char*)item, "sessions") == 0);
+
+ ret = sepol_list_pop_back(h, list, &item);
+ CU_ASSERT(ret == SEPOL_OK);
+ CU_ASSERT(strcmp((char*)item, "schoenberg") == 0);
+
+ ret = sepol_list_pop_front(h, list, &item);
+ CU_ASSERT(ret == SEPOL_OK);
+ CU_ASSERT(strcmp((char*)item, "webern") == 0);
+
+ ret = sepol_list_pop_back(h, list, &item);
+ CU_ASSERT(ret == SEPOL_OK);
+ CU_ASSERT(strcmp((char*)item, "berg") == 0);
+
+
+ ret = sepol_list_pop_back(h, list, &item);
+ CU_ASSERT(ret == SEPOL_ERANGE);
+
+ sepol_list_free(list);
+ sepol_handle_destroy(h);
+}
+
+static void test_list_extend(void)
+{
+ int ret, i;
+ struct sepol_list *serialism, *minimalism;
+ struct sepol_iter *iter;
+ struct sepol_handle *h;
+ char *composers[] = {"webern", "berg",
+ "schoenberg", "sessions",
+ "adams", "glass", "reich" };
+ char *composer;
+
+ h = sepol_handle_create();
+ CU_ASSERT(h != NULL);
+
+ ret = sepol_list_create(h, &serialism);
+ CU_ASSERT(ret == SEPOL_OK);
+
+
+ ret = sepol_list_create(h, &minimalism);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, serialism, composers[0]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, serialism, composers[1]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, serialism, composers[2]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, serialism, composers[3]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, minimalism, composers[4]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, minimalism, composers[5]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, minimalism, composers[6]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_iter_create(h, &iter);
+ CU_ASSERT(ret == SEPOL_OK);
+ ret = sepol_list_begin(h, minimalism, iter);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_extend(h, serialism, iter);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_begin(h, serialism, iter);
+ CU_ASSERT(ret == SEPOL_OK);
+ i = 0;
+ while (ret == SEPOL_OK) {
+ composer = (char *)sepol_iter_get_data(h, iter);
+ CU_ASSERT(composer != NULL);
+ CU_ASSERT(strcmp(composers[i], composer) == 0);
+ ret = sepol_iter_next(h, iter);
+ i++;
+ }
+ CU_ASSERT(ret == SEPOL_ITERSTOP);
+
+ sepol_iter_free(h, iter);
+ sepol_list_free(serialism);
+ sepol_list_free(minimalism);
+ sepol_handle_destroy(h);
+}
+
+static void test_list_extend_list(void)
+{
+ int ret, i;
+ struct sepol_list *serialism, *minimalism;
+ struct sepol_iter *iter;
+ struct sepol_handle *h;
+ char *composers[] = {"webern", "berg",
+ "schoenberg", "sessions",
+ "adams", "glass", "reich" };
+ char *composer;
+
+
+ h = sepol_handle_create();
+ CU_ASSERT(h != NULL);
+
+ ret = sepol_list_create(h, &serialism);
+ CU_ASSERT(ret == SEPOL_OK);
+
+
+ ret = sepol_list_create(h, &minimalism);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, serialism, composers[0]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, serialism, composers[1]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, serialism, composers[2]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, serialism, composers[3]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, minimalism, composers[4]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, minimalism, composers[5]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_append(h, minimalism, composers[6]);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_list_extend_list(h, serialism, minimalism);
+ CU_ASSERT(ret == SEPOL_OK);
+
+ ret = sepol_iter_create(h, &iter);
+ CU_ASSERT(ret == SEPOL_OK);
+
+
+ ret = sepol_list_begin(h, serialism, iter);
+ CU_ASSERT(ret == SEPOL_OK);
+ i = 0;
+ while (ret == SEPOL_OK) {
+ composer = (char *)sepol_iter_get_data(h, iter);
+ CU_ASSERT(composer != NULL);
+ CU_ASSERT(strcmp(composers[i], composer) == 0);
+ ret = sepol_iter_next(h, iter);
+ i++;
+ }
+ CU_ASSERT(ret == SEPOL_ITERSTOP);
+
+ sepol_iter_free(h, iter);
+ sepol_list_free(serialism);
+ sepol_list_free(minimalism);
+ sepol_handle_destroy(h);
+}
+
+int list_add_tests(CU_pSuite suite)
+{
+ if (NULL == CU_add_test(suite, "test_list_create", test_list_create)) {
+ return -1;
+ }
+
+ if (NULL == CU_add_test(suite, "test_list",
+ test_list)) {
+ return -1;
+ }
+
+ if (NULL == CU_add_test(suite, "test_list_pop", test_list_pop)) {
+ return -1;
+ }
+
+ if (NULL == CU_add_test(suite, "test_list_extend", test_list_extend)) {
+ return -1;
+ }
+
+ if (NULL == CU_add_test(suite, "test_list_extend_list", test_list_extend_list)) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/libsepol/tests/test-list.h b/libsepol/tests/test-list.h
new file mode 100644
index 0000000..6a51bcb
--- /dev/null
+++ b/libsepol/tests/test-list.h
@@ -0,0 +1,12 @@
+/* Author : Karl MacMillan <kmacmillan@mentalrootkit.com> */
+
+#ifndef __test_list_h__
+#define __test_list_h__
+
+#include <CUnit/Basic.h>
+
+int list_test_init(void);
+int list_test_cleanup(void);
+int list_add_tests(CU_pSuite suite);
+
+#endif
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-20 13:34 [POLICYREP PATCH] Add generic iterators and a list data type to libsepol Karl MacMillan
@ 2007-04-20 19:55 ` Eamon Walsh
2007-04-23 15:48 ` Karl MacMillan
2007-04-24 16:42 ` Stephen Smalley
1 sibling, 1 reply; 17+ messages in thread
From: Eamon Walsh @ 2007-04-20 19:55 UTC (permalink / raw)
To: Karl MacMillan; +Cc: selinux
Karl MacMillan wrote:
> Add a generic iterator data structure and a linked-list implementation
> based that uses the iterators to libsepol. Includes test cases for the
> linked-list implementation.
>
> This version is updated to remove improper use of void** based on comments
> from James Antill.
>
> Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
>
Is there no standard utility library out there that could provide these
things? Glib? APR?
--
Eamon Walsh <ewalsh@tycho.nsa.gov>
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-20 19:55 ` Eamon Walsh
@ 2007-04-23 15:48 ` Karl MacMillan
2007-04-23 16:28 ` James Antill
0 siblings, 1 reply; 17+ messages in thread
From: Karl MacMillan @ 2007-04-23 15:48 UTC (permalink / raw)
To: Eamon Walsh; +Cc: selinux
On Fri, 2007-04-20 at 15:55 -0400, Eamon Walsh wrote:
> Karl MacMillan wrote:
> > Add a generic iterator data structure and a linked-list implementation
> > based that uses the iterators to libsepol. Includes test cases for the
> > linked-list implementation.
> >
> > This version is updated to remove improper use of void** based on comments
> > from James Antill.
> >
> > Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
> >
>
> Is there no standard utility library out there that could provide these
> things? Glib? APR?
>
In the past, we had decided to not use external libraries because it
would pull in a fairly large library (like glib) close to the root of
the library dependency tree. If we maintain a complete split between
libsepol / libselinux then much of that concern seems to go away. It
also means that the extra dependency is only present on managed systems,
which doesn't make things worse for embedded.
APR seems aimed at a slightly different problem set (less data
structures, more system abstraction).
Glib, on the other hand, would provide everything that we need. In fact,
gobject is a perfect fit for the policy object abstraction that I
created with many advantages (including support for exporting the
objects to other languages like python).
The Pros of using glib:
* All the data structures that we need.
* Better tested foundation.
* Safe string functions.
* Familiar environment for many developers.
* Complete object-oriented layer for the policy rep.
* Easy export to Python and other languages.
* Our code gets much smaller (libsemanage in particular could shrink if
we used glib).
The Cons:
* Large dependency.
* Potential security issues in glib (not certain this is a real issue,
but glib is fairly big).
* Glib tends to be slightly verbose and boilerplate heavy.
So, if you ask me, I think we should start using glib in libsepol (and
eventually libsemanage). I can work up some code to see what the
policyrep stuff would look like based on glib if others think this is
worth exploring.
Karl
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-23 15:48 ` Karl MacMillan
@ 2007-04-23 16:28 ` James Antill
2007-04-23 17:52 ` Stephen Smalley
0 siblings, 1 reply; 17+ messages in thread
From: James Antill @ 2007-04-23 16:28 UTC (permalink / raw)
To: Karl MacMillan; +Cc: Eamon Walsh, selinux
[-- Attachment #1: Type: text/plain, Size: 1560 bytes --]
On Mon, 2007-04-23 at 11:48 -0400, Karl MacMillan wrote:
> Glib, on the other hand, would provide everything that we need. In fact,
> gobject is a perfect fit for the policy object abstraction that I
> created with many advantages (including support for exporting the
> objects to other languages like python).
>
> The Pros of using glib:
> * All the data structures that we need.
> * Better tested foundation.
> * Safe string functions.
> * Familiar environment for many developers.
> * Complete object-oriented layer for the policy rep.
> * Easy export to Python and other languages.
> * Our code gets much smaller (libsemanage in particular could shrink if
> we used glib).
>
> The Cons:
> * Large dependency.
> * Potential security issues in glib (not certain this is a real issue,
> but glib is fairly big).
> * Glib tends to be slightly verbose and boilerplate heavy.
I'm pretty sure glib is used in a few security relevant places, so I
doubt that's a problem. The "dependency" argument just seems like normal
C programmer twitchyness ... glib is at least as portable as what we'd
use it in and is included in pretty much every distro.
The only real problem I've ever had with glib is that calling g_new()
calls abort() on failure (and by extension so does everything that
allocates in glib).
This also tends to mean that glib code allocates much more freely than
normal C code. But if you can swallow the allocation death pill, it's
hard to argue against glib ... IMO.
--
James Antill <jantill@redhat.com>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-23 16:28 ` James Antill
@ 2007-04-23 17:52 ` Stephen Smalley
2007-04-23 21:35 ` Karl MacMillan
0 siblings, 1 reply; 17+ messages in thread
From: Stephen Smalley @ 2007-04-23 17:52 UTC (permalink / raw)
To: James Antill; +Cc: Karl MacMillan, Eamon Walsh, selinux
On Mon, 2007-04-23 at 12:28 -0400, James Antill wrote:
> On Mon, 2007-04-23 at 11:48 -0400, Karl MacMillan wrote:
>
> > Glib, on the other hand, would provide everything that we need. In fact,
> > gobject is a perfect fit for the policy object abstraction that I
> > created with many advantages (including support for exporting the
> > objects to other languages like python).
> >
> > The Pros of using glib:
> > * All the data structures that we need.
> > * Better tested foundation.
> > * Safe string functions.
> > * Familiar environment for many developers.
> > * Complete object-oriented layer for the policy rep.
> > * Easy export to Python and other languages.
> > * Our code gets much smaller (libsemanage in particular could shrink if
> > we used glib).
> >
> > The Cons:
> > * Large dependency.
> > * Potential security issues in glib (not certain this is a real issue,
> > but glib is fairly big).
> > * Glib tends to be slightly verbose and boilerplate heavy.
>
> I'm pretty sure glib is used in a few security relevant places, so I
> doubt that's a problem. The "dependency" argument just seems like normal
> C programmer twitchyness ... glib is at least as portable as what we'd
> use it in and is included in pretty much every distro.
>
> The only real problem I've ever had with glib is that calling g_new()
> calls abort() on failure (and by extension so does everything that
> allocates in glib).
> This also tends to mean that glib code allocates much more freely than
> normal C code. But if you can swallow the allocation death pill, it's
> hard to argue against glib ... IMO.
I can't swallow the allocation death pill - how does one perform sane
cleanup with such behavior? However, looking around, I see you can
replace the allocator virtual table with your own functions and there
are g_try_* functions that return NULL rather than calling abort. But
not clear that helps with its own internal usage of g_new.
David Wheeler's Secure Programming howto notes this behavior as a
problem for use of glib in most secure programs.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-23 17:52 ` Stephen Smalley
@ 2007-04-23 21:35 ` Karl MacMillan
2007-04-23 23:33 ` James Antill
2007-04-24 12:26 ` Stephen Smalley
0 siblings, 2 replies; 17+ messages in thread
From: Karl MacMillan @ 2007-04-23 21:35 UTC (permalink / raw)
To: Stephen Smalley; +Cc: James Antill, Eamon Walsh, selinux
On Mon, 2007-04-23 at 13:52 -0400, Stephen Smalley wrote:
> On Mon, 2007-04-23 at 12:28 -0400, James Antill wrote:
> > On Mon, 2007-04-23 at 11:48 -0400, Karl MacMillan wrote:
> >
> > > Glib, on the other hand, would provide everything that we need. In fact,
> > > gobject is a perfect fit for the policy object abstraction that I
> > > created with many advantages (including support for exporting the
> > > objects to other languages like python).
> > >
> > > The Pros of using glib:
> > > * All the data structures that we need.
> > > * Better tested foundation.
> > > * Safe string functions.
> > > * Familiar environment for many developers.
> > > * Complete object-oriented layer for the policy rep.
> > > * Easy export to Python and other languages.
> > > * Our code gets much smaller (libsemanage in particular could shrink if
> > > we used glib).
> > >
> > > The Cons:
> > > * Large dependency.
> > > * Potential security issues in glib (not certain this is a real issue,
> > > but glib is fairly big).
> > > * Glib tends to be slightly verbose and boilerplate heavy.
> >
> > I'm pretty sure glib is used in a few security relevant places, so I
> > doubt that's a problem. The "dependency" argument just seems like normal
> > C programmer twitchyness ... glib is at least as portable as what we'd
> > use it in and is included in pretty much every distro.
> >
> > The only real problem I've ever had with glib is that calling g_new()
> > calls abort() on failure (and by extension so does everything that
> > allocates in glib).
> > This also tends to mean that glib code allocates much more freely than
> > normal C code. But if you can swallow the allocation death pill, it's
> > hard to argue against glib ... IMO.
>
> I can't swallow the allocation death pill - how does one perform sane
> cleanup with such behavior?
To be fair, in libsepol we currently just exist on allocation error.
Yes, it's better than abort, but we don't really have a need to perform
cleanup.
libsemanage is obviously different and I don't think the libsemanage
dependency on libsepol is ever going to be removed.
> However, looking around, I see you can
> replace the allocator virtual table with your own functions and there
> are g_try_* functions that return NULL rather than calling abort. But
> not clear that helps with its own internal usage of g_new.
>
This does help internal usage of g_new (verified by code inspection and
experimentation). However, glib includes several custom allocators and
replacing the allocator vtable did not seem to help there. It might be
possible to track down all of the allocators and convince them not to
abort, but there may be problems in the future. We could also try
catching sigabort but there would be no good way to figure out why the
abort was delivered. This is really frustrating and is causing people to
not use glib (the X hackers rejected it over this reason).
Any other options (there don't seem to be any obvious ones)? Personally,
I vote for the C++ STL but that requires a small change to which some
might object. In summary - C sucks and I'm tired of this 1980s
programming environment.
Karl
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-23 21:35 ` Karl MacMillan
@ 2007-04-23 23:33 ` James Antill
2007-04-24 12:26 ` Stephen Smalley
1 sibling, 0 replies; 17+ messages in thread
From: James Antill @ 2007-04-23 23:33 UTC (permalink / raw)
To: Karl MacMillan; +Cc: Stephen Smalley, Eamon Walsh, selinux
[-- Attachment #1: Type: text/plain, Size: 2840 bytes --]
On Mon, 2007-04-23 at 17:35 -0400, Karl MacMillan wrote:
> On Mon, 2007-04-23 at 13:52 -0400, Stephen Smalley wrote:
> > However, looking around, I see you can
> > replace the allocator virtual table with your own functions and there
> > are g_try_* functions that return NULL rather than calling abort. But
> > not clear that helps with its own internal usage of g_new.
> >
>
> This does help internal usage of g_new (verified by code inspection and
> experimentation).
Errm, What do you mean here? The vtable calls return NULL on failure
_now_ (they just call libc malloc/realloc/free), they only exist so you
can replace them with debugging versions as in g_mem_profile().
g_new() calls g_malloc() which is defined as calling abort(), via.
g_error(), on allocation failure. Pretty much everything in glib will
break if that changes, for instance g_list_append() calls g_slice_new()
as you add something to the linked list, which calls g_malloc() ... and
g_list_append() has no error path because it knows it can't fail. Dito.
g_hash_table_new_full() on both counts.
> However, glib includes several custom allocators and
> replacing the allocator vtable did not seem to help there. It might be
> possible to track down all of the allocators and convince them not to
> abort, but there may be problems in the future. We could also try
> catching sigabort but there would be no good way to figure out why the
> abort was delivered. This is really frustrating and is causing people to
> not use glib (the X hackers rejected it over this reason).
Dealing with the abort() is the simple problem, it's how you then get
out from the call to g_queue_push_fail() when it happens four functions
calls further down the stack ... without dereferencing NULL a few times.
> Any other options (there don't seem to be any obvious ones)? Personally,
> I vote for the C++ STL but that requires a small change to which some
> might object. In summary - C sucks and I'm tired of this 1980s
> programming environment.
I completely agree, although personally I think C++ sucks more. The
options are pretty sparse, as everyone generally hacks up mediocre
versions of exactly what they need (as everyone is loath to have
externals deps).
The only other one that comes to mind is NSPR, which is again mostly a
matter of portability with a few other useful things thrown in for good
measure. But I'd be loath to recommend it for libsepol (or much else,
for that matter).
Of course there are a few million on the internets, of varying quality,
but nothing that's in Fedora that I know of.
--
James Antill - <james.antill@redhat.com>
setsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, ...);
setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, ...);
setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, ...);
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-23 21:35 ` Karl MacMillan
2007-04-23 23:33 ` James Antill
@ 2007-04-24 12:26 ` Stephen Smalley
1 sibling, 0 replies; 17+ messages in thread
From: Stephen Smalley @ 2007-04-24 12:26 UTC (permalink / raw)
To: Karl MacMillan; +Cc: James Antill, Eamon Walsh, selinux
On Mon, 2007-04-23 at 17:35 -0400, Karl MacMillan wrote:
> On Mon, 2007-04-23 at 13:52 -0400, Stephen Smalley wrote:
> > On Mon, 2007-04-23 at 12:28 -0400, James Antill wrote:
> > > On Mon, 2007-04-23 at 11:48 -0400, Karl MacMillan wrote:
> > >
> > > > Glib, on the other hand, would provide everything that we need. In fact,
> > > > gobject is a perfect fit for the policy object abstraction that I
> > > > created with many advantages (including support for exporting the
> > > > objects to other languages like python).
> > > >
> > > > The Pros of using glib:
> > > > * All the data structures that we need.
> > > > * Better tested foundation.
> > > > * Safe string functions.
> > > > * Familiar environment for many developers.
> > > > * Complete object-oriented layer for the policy rep.
> > > > * Easy export to Python and other languages.
> > > > * Our code gets much smaller (libsemanage in particular could shrink if
> > > > we used glib).
> > > >
> > > > The Cons:
> > > > * Large dependency.
> > > > * Potential security issues in glib (not certain this is a real issue,
> > > > but glib is fairly big).
> > > > * Glib tends to be slightly verbose and boilerplate heavy.
> > >
> > > I'm pretty sure glib is used in a few security relevant places, so I
> > > doubt that's a problem. The "dependency" argument just seems like normal
> > > C programmer twitchyness ... glib is at least as portable as what we'd
> > > use it in and is included in pretty much every distro.
> > >
> > > The only real problem I've ever had with glib is that calling g_new()
> > > calls abort() on failure (and by extension so does everything that
> > > allocates in glib).
> > > This also tends to mean that glib code allocates much more freely than
> > > normal C code. But if you can swallow the allocation death pill, it's
> > > hard to argue against glib ... IMO.
> >
> > I can't swallow the allocation death pill - how does one perform sane
> > cleanup with such behavior?
>
> To be fair, in libsepol we currently just exist on allocation error.
> Yes, it's better than abort, but we don't really have a need to perform
> cleanup.
>
> libsemanage is obviously different and I don't think the libsemanage
> dependency on libsepol is ever going to be removed.
>
> > However, looking around, I see you can
> > replace the allocator virtual table with your own functions and there
> > are g_try_* functions that return NULL rather than calling abort. But
> > not clear that helps with its own internal usage of g_new.
> >
>
> This does help internal usage of g_new (verified by code inspection and
> experimentation). However, glib includes several custom allocators and
> replacing the allocator vtable did not seem to help there. It might be
> possible to track down all of the allocators and convince them not to
> abort, but there may be problems in the future. We could also try
> catching sigabort but there would be no good way to figure out why the
> abort was delivered. This is really frustrating and is causing people to
> not use glib (the X hackers rejected it over this reason).
>
> Any other options (there don't seem to be any obvious ones)? Personally,
> I vote for the C++ STL but that requires a small change to which some
> might object. In summary - C sucks and I'm tired of this 1980s
> programming environment.
I think rolling our own (in C) is the only real option here.
Also, keep in mind that we will continue to have a /sbin/init ->
libsepol dependency for the purpose of downgrading policy versions, so
external dependencies do matter.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-20 13:34 [POLICYREP PATCH] Add generic iterators and a list data type to libsepol Karl MacMillan
2007-04-20 19:55 ` Eamon Walsh
@ 2007-04-24 16:42 ` Stephen Smalley
2007-04-25 19:49 ` Karl MacMillan
1 sibling, 1 reply; 17+ messages in thread
From: Stephen Smalley @ 2007-04-24 16:42 UTC (permalink / raw)
To: Karl MacMillan; +Cc: selinux
On Fri, 2007-04-20 at 09:34 -0400, Karl MacMillan wrote:
> Add a generic iterator data structure and a linked-list implementation
> based that uses the iterators to libsepol. Includes test cases for the
> linked-list implementation.
>
> This version is updated to remove improper use of void** based on comments
> from James Antill.
>
> Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
For the entire policyrep patch series so far,
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Merge at will.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-24 16:42 ` Stephen Smalley
@ 2007-04-25 19:49 ` Karl MacMillan
2007-04-25 20:48 ` Joshua Brindle
0 siblings, 1 reply; 17+ messages in thread
From: Karl MacMillan @ 2007-04-25 19:49 UTC (permalink / raw)
To: Stephen Smalley; +Cc: selinux
On Tue, 2007-04-24 at 12:42 -0400, Stephen Smalley wrote:
> On Fri, 2007-04-20 at 09:34 -0400, Karl MacMillan wrote:
> > Add a generic iterator data structure and a linked-list implementation
> > based that uses the iterators to libsepol. Includes test cases for the
> > linked-list implementation.
> >
> > This version is updated to remove improper use of void** based on comments
> > from James Antill.
> >
> > Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
>
> For the entire policyrep patch series so far,
>
> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
>
> Merge at will.
>
Merged as libsepol 2.0.4.
Karl
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-25 19:49 ` Karl MacMillan
@ 2007-04-25 20:48 ` Joshua Brindle
2007-04-25 21:09 ` Karl MacMillan
2007-04-26 11:49 ` Stephen Smalley
0 siblings, 2 replies; 17+ messages in thread
From: Joshua Brindle @ 2007-04-25 20:48 UTC (permalink / raw)
To: Karl MacMillan; +Cc: Stephen Smalley, selinux
Karl MacMillan wrote:
> On Tue, 2007-04-24 at 12:42 -0400, Stephen Smalley wrote:
>
>> On Fri, 2007-04-20 at 09:34 -0400, Karl MacMillan wrote:
>>
>>> Add a generic iterator data structure and a linked-list implementation
>>> based that uses the iterators to libsepol. Includes test cases for the
>>> linked-list implementation.
>>>
>>> This version is updated to remove improper use of void** based on comments
>>> from James Antill.
>>>
>>> Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
>>>
>> For the entire policyrep patch series so far,
>>
>> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
>>
>> Merge at will.
>>
>>
>
> Merged as libsepol 2.0.4.
>
shouldn't this be 2.1.4 or similar since 2.0.4 will be the next revision
of trunk?
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-25 20:48 ` Joshua Brindle
@ 2007-04-25 21:09 ` Karl MacMillan
2007-04-25 21:13 ` Joshua Brindle
2007-04-26 11:49 ` Stephen Smalley
1 sibling, 1 reply; 17+ messages in thread
From: Karl MacMillan @ 2007-04-25 21:09 UTC (permalink / raw)
To: Joshua Brindle; +Cc: Stephen Smalley, selinux
On Wed, 2007-04-25 at 16:48 -0400, Joshua Brindle wrote:
> Karl MacMillan wrote:
> > On Tue, 2007-04-24 at 12:42 -0400, Stephen Smalley wrote:
> >
> >> On Fri, 2007-04-20 at 09:34 -0400, Karl MacMillan wrote:
> >>
> >>> Add a generic iterator data structure and a linked-list implementation
> >>> based that uses the iterators to libsepol. Includes test cases for the
> >>> linked-list implementation.
> >>>
> >>> This version is updated to remove improper use of void** based on comments
> >>> from James Antill.
> >>>
> >>> Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
> >>>
> >> For the entire policyrep patch series so far,
> >>
> >> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
> >>
> >> Merge at will.
> >>
> >>
> >
> > Merged as libsepol 2.0.4.
> >
> shouldn't this be 2.1.4 or similar since 2.0.4 will be the next revision
> of trunk?
>
Yeah - I bumped it to 2.1.0. That sound OK or do we want to leave space
for another release of trunk before the merge?
Karl
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-25 21:09 ` Karl MacMillan
@ 2007-04-25 21:13 ` Joshua Brindle
0 siblings, 0 replies; 17+ messages in thread
From: Joshua Brindle @ 2007-04-25 21:13 UTC (permalink / raw)
To: Karl MacMillan; +Cc: Stephen Smalley, selinux
Karl MacMillan wrote:
> On Wed, 2007-04-25 at 16:48 -0400, Joshua Brindle wrote:
>
>> Karl MacMillan wrote:
>>
>>> On Tue, 2007-04-24 at 12:42 -0400, Stephen Smalley wrote:
>>>
>>>
>>>> On Fri, 2007-04-20 at 09:34 -0400, Karl MacMillan wrote:
>>>>
>>>>
>>>>> Add a generic iterator data structure and a linked-list implementation
>>>>> based that uses the iterators to libsepol. Includes test cases for the
>>>>> linked-list implementation.
>>>>>
>>>>> This version is updated to remove improper use of void** based on comments
>>>>> from James Antill.
>>>>>
>>>>> Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
>>>>>
>>>>>
>>>> For the entire policyrep patch series so far,
>>>>
>>>> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
>>>>
>>>> Merge at will.
>>>>
>>>>
>>>>
>>> Merged as libsepol 2.0.4.
>>>
>>>
>> shouldn't this be 2.1.4 or similar since 2.0.4 will be the next revision
>> of trunk?
>>
>>
>
> Yeah - I bumped it to 2.1.0. That sound OK or do we want to leave space
> for another release of trunk before the merge?
>
>
I think thats fine, hopefully this will be the next release, if not we
can adjust when the time comes.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-25 20:48 ` Joshua Brindle
2007-04-25 21:09 ` Karl MacMillan
@ 2007-04-26 11:49 ` Stephen Smalley
2007-04-26 13:43 ` Joshua Brindle
1 sibling, 1 reply; 17+ messages in thread
From: Stephen Smalley @ 2007-04-26 11:49 UTC (permalink / raw)
To: Joshua Brindle; +Cc: Karl MacMillan, selinux
On Wed, 2007-04-25 at 16:48 -0400, Joshua Brindle wrote:
> Karl MacMillan wrote:
> > On Tue, 2007-04-24 at 12:42 -0400, Stephen Smalley wrote:
> >
> >> On Fri, 2007-04-20 at 09:34 -0400, Karl MacMillan wrote:
> >>
> >>> Add a generic iterator data structure and a linked-list implementation
> >>> based that uses the iterators to libsepol. Includes test cases for the
> >>> linked-list implementation.
> >>>
> >>> This version is updated to remove improper use of void** based on comments
> >>> from James Antill.
> >>>
> >>> Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
> >>>
> >> For the entire policyrep patch series so far,
> >>
> >> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
> >>
> >> Merge at will.
> >>
> >>
> >
> > Merged as libsepol 2.0.4.
> >
> shouldn't this be 2.1.4 or similar since 2.0.4 will be the next revision
> of trunk?
It doesn't actually matter, as we can update the version just before
merging to trunk.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-26 11:49 ` Stephen Smalley
@ 2007-04-26 13:43 ` Joshua Brindle
2007-04-26 13:49 ` Stephen Smalley
0 siblings, 1 reply; 17+ messages in thread
From: Joshua Brindle @ 2007-04-26 13:43 UTC (permalink / raw)
To: Stephen Smalley; +Cc: Karl MacMillan, selinux
Stephen Smalley wrote:
> On Wed, 2007-04-25 at 16:48 -0400, Joshua Brindle wrote:
>
>> Karl MacMillan wrote:
>>
>>> On Tue, 2007-04-24 at 12:42 -0400, Stephen Smalley wrote:
>>>
>>>
>>>> On Fri, 2007-04-20 at 09:34 -0400, Karl MacMillan wrote:
>>>>
>>>>
>>>>> Add a generic iterator data structure and a linked-list implementation
>>>>> based that uses the iterators to libsepol. Includes test cases for the
>>>>> linked-list implementation.
>>>>>
>>>>> This version is updated to remove improper use of void** based on comments
>>>>> from James Antill.
>>>>>
>>>>> Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
>>>>>
>>>>>
>>>> For the entire policyrep patch series so far,
>>>>
>>>> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
>>>>
>>>> Merge at will.
>>>>
>>>>
>>>>
>>> Merged as libsepol 2.0.4.
>>>
>>>
>> shouldn't this be 2.1.4 or similar since 2.0.4 will be the next revision
>> of trunk?
>>
>
> It doesn't actually matter, as we can update the version just before
> merging to trunk.
>
>
but if we ever roll up rpm's for testing this branch it will be
undesirable to have overlapping versions.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-26 13:43 ` Joshua Brindle
@ 2007-04-26 13:49 ` Stephen Smalley
2007-04-26 19:24 ` Karl MacMillan
0 siblings, 1 reply; 17+ messages in thread
From: Stephen Smalley @ 2007-04-26 13:49 UTC (permalink / raw)
To: Joshua Brindle; +Cc: Karl MacMillan, selinux
On Thu, 2007-04-26 at 09:43 -0400, Joshua Brindle wrote:
> Stephen Smalley wrote:
> > On Wed, 2007-04-25 at 16:48 -0400, Joshua Brindle wrote:
> >
> >> Karl MacMillan wrote:
> >>
> >>> On Tue, 2007-04-24 at 12:42 -0400, Stephen Smalley wrote:
> >>>
> >>>
> >>>> On Fri, 2007-04-20 at 09:34 -0400, Karl MacMillan wrote:
> >>>>
> >>>>
> >>>>> Add a generic iterator data structure and a linked-list implementation
> >>>>> based that uses the iterators to libsepol. Includes test cases for the
> >>>>> linked-list implementation.
> >>>>>
> >>>>> This version is updated to remove improper use of void** based on comments
> >>>>> from James Antill.
> >>>>>
> >>>>> Signed-off-by: Karl MacMillan <kmacmillan@mentalrootkit.com>
> >>>>>
> >>>>>
> >>>> For the entire policyrep patch series so far,
> >>>>
> >>>> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
> >>>>
> >>>> Merge at will.
> >>>>
> >>>>
> >>>>
> >>> Merged as libsepol 2.0.4.
> >>>
> >>>
> >> shouldn't this be 2.1.4 or similar since 2.0.4 will be the next revision
> >> of trunk?
> >>
> >
> > It doesn't actually matter, as we can update the version just before
> > merging to trunk.
> >
> >
> but if we ever roll up rpm's for testing this branch it will be
> undesirable to have overlapping versions.
I'm not sure why one would ever do that (roll up rpms, vs. just make
install install-pywrap relabel).
Changing the {VERSION, ChangeLog} on the branch will also prevent clean
merges from the trunk.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [POLICYREP PATCH] Add generic iterators and a list data type to libsepol
2007-04-26 13:49 ` Stephen Smalley
@ 2007-04-26 19:24 ` Karl MacMillan
0 siblings, 0 replies; 17+ messages in thread
From: Karl MacMillan @ 2007-04-26 19:24 UTC (permalink / raw)
To: Stephen Smalley; +Cc: Joshua Brindle, selinux
On Thu, 2007-04-26 at 09:49 -0400, Stephen Smalley wrote:
> On Thu, 2007-04-26 at 09:43 -0400, Joshua Brindle wrote:
<snip>
> > >>> Merged as libsepol 2.0.4.
> > >>>
> > >>>
> > >> shouldn't this be 2.1.4 or similar since 2.0.4 will be the next revision
> > >> of trunk?
> > >>
> > >
> > > It doesn't actually matter, as we can update the version just before
> > > merging to trunk.
> > >
> > >
> > but if we ever roll up rpm's for testing this branch it will be
> > undesirable to have overlapping versions.
>
> I'm not sure why one would ever do that (roll up rpms, vs. just make
> install install-pywrap relabel).
>
> Changing the {VERSION, ChangeLog} on the branch will also prevent clean
> merges from the trunk.
>
This part was compelling to me (the merging) so I removed the version
change completely and the changelog entries.
Karl
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2007-04-26 19:24 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-20 13:34 [POLICYREP PATCH] Add generic iterators and a list data type to libsepol Karl MacMillan
2007-04-20 19:55 ` Eamon Walsh
2007-04-23 15:48 ` Karl MacMillan
2007-04-23 16:28 ` James Antill
2007-04-23 17:52 ` Stephen Smalley
2007-04-23 21:35 ` Karl MacMillan
2007-04-23 23:33 ` James Antill
2007-04-24 12:26 ` Stephen Smalley
2007-04-24 16:42 ` Stephen Smalley
2007-04-25 19:49 ` Karl MacMillan
2007-04-25 20:48 ` Joshua Brindle
2007-04-25 21:09 ` Karl MacMillan
2007-04-25 21:13 ` Joshua Brindle
2007-04-26 11:49 ` Stephen Smalley
2007-04-26 13:43 ` Joshua Brindle
2007-04-26 13:49 ` Stephen Smalley
2007-04-26 19:24 ` Karl MacMillan
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.