Add list and iter data types to libsepol
RFC 1/1 Add list and iter data types to libsepol
As part of some work to improve the parser in checkpolicy and module data structures in libsepol, I have implemented doubly-linked list and iterator data types. The attached patch adds these to libsepol.
I would appreciate feedback on these before I submit larger patches that make use of them. In particular:
* Is the iterator concept acceptable (I plan to add iterator support to other data types including hashtabs)?
* We've discussed dropping the use of typedefs on structs (which I do in this patch). Is this what we want to do, or should I add typedefs?
Karl
libsepol/include/sepol/errcodes.h +3 -0
@@ -22,4 +22,7 @@#define SEPOL_EEXIST -EEXIST#define SEPOL_ENOENT -ENOENT +/* Custom error codes */ +#define SEPOL_ITERSTOP -500 +#endif
libsepol/include/sepol/policydb/iter.h +118 -0
118 lines not on this page · raw message
libsepol/include/sepol/policydb/list.h +79 -0
79 lines not on this page · raw message
libsepol/src/iter.c +141 -0
141 lines not on this page · raw message
libsepol/src/list.c +253 -0
253 lines not on this page · raw message
libsepol/tests/libsepol-tests.c +2 -0
@@ -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, intDECLARE_SUITE (linker);DECLARE_SUITE (expander);DECLARE_SUITE (deps); +DECLARE_SUITE (list);if (verbose)CU_basic_set_mode (CU_BRM_VERBOSE );
libsepol/tests/test-list.c +145 -0
145 lines not on this page · raw message
libsepol/tests/test-list.h +12 -0
@@ -0,0 +1,12 @@ +/* Author : Karl MacMillan <[email protected]> */ + +#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
Quoted 6 lines · Karl MacMillan
As part of some work to improve the parser in checkpolicy and module data structures in libsepol, I have implemented doubly-linked list and iterator data types. The attached patch adds these to libsepol.
I would appreciate feedback on these before I submit larger patches that make use of them. In particular:
* Is the iterator concept acceptable (I plan to add iterator support to other data types including hashtabs)?
Attached is a patch that implements iterators for hash tables (it also includes some unrelated cleanups).
Karl
libsepol/include/sepol/policydb/hashtab.h +19 -6
@@ -15,6 +15,7 @@#define _SEPOL_POLICYDB_HASHTAB_H_#include <sepol/errcodes.h> +#include <sepol/policydb/iter.h> #include <stdint.h> #include <stdio.h>
@@ -40,19 +41,18 @@ typedef struct hashtab_val {typedef hashtab_val_t *hashtab_t ; +typedef unsigned int (*hash_value_fnc_t )(hashtab_t h,const hashtab_key_t key); +typedef int (*keycmp_fnc_t )(hashtab_t h,const hashtab_key_t key1, +const hashtab_key_t key2);/* Creates a new hash table with the specified characteristics. Returns NULL if insufficent space is available or the new hash table otherwise. */ -extern hashtab_t hashtab_create (unsigned int (*hash_value) (hashtab_t h, -const hashtab_key_t - key), -int (*keycmp) (hashtab_t h, -const hashtab_key_t key1, -const hashtab_key_t key2), +extern hashtab_t hashtab_create (hash_value_fnc_t hash,keycmp_fnc_t keycmp,unsigned int size); +/* Inserts the specified (key, datum) pair into the specified hash table.
@@ -61,6 +61,9 @@ extern hashtab_t hashtab_create(unsignedSEPOL_OK otherwise. */ extern int hashtab_insert (hashtab_t h,hashtab_key_t k,hashtab_datum_t d); +extern int hashtab_insert2 (hashtab_t h,hashtab_key_t key,hashtab_datum_t datum, +hashtab_ptr_t *current); +/* Removes the entry with the specified key from the hash table.
@@ -103,6 +106,16 @@ extern void hashtab_destroy(hashtab_t h)extern void hashtab_destroy (hashtab_t h);/* +Initializes an iterator for the hash table (see +sepol/policydb/iter.h). sepol_iter_get_data will return a +hashtab_ptr_t. + +Returns NULL if the iterator cannot be created or the iterator +otherwise. +*/ +extern int hashtab_iter (hashtab_t h,struct sepol_iter *iter); + +/* Applies the specified apply function to (key,datum,args) for each entry in the specified hash table.
libsepol/src/hashtab.c +92 -3
128 lines not on this page · raw message
libsepol/tests/libsepol-tests.c +2 -0
@@ -23,6 +23,7 @@#include "test-expander.h" #include "test-deps.h" #include "test-list.h" +#include "test-hashtab.h" #include <CUnit/Basic.h> #include <CUnit/Console.h>
@@ -63,6 +64,7 @@ static int do_tests(int interactive, intDECLARE_SUITE (expander);DECLARE_SUITE (deps);DECLARE_SUITE (list); +DECLARE_SUITE (hashtab);if (verbose)CU_basic_set_mode (CU_BRM_VERBOSE );
libsepol/tests/test-hashtab.c +99 -0
99 lines not on this page · raw message
libsepol/tests/test-hashtab.h +12 -0
@@ -0,0 +1,12 @@ +/* Author: Karl MacMillan <[email protected]> */ + +#ifndef __test_hashtab_h__ +#define __test_hashtab_h__ + +#include <CUnit/Basic.h> + +int hashtab_test_init (void ); +int hashtab_test_cleanup (void ); +int hashtab_add_tests (CU_pSuite suite); + +#endif
Quoted 9 lines · Karl MacMillan
As part of some work to improve the parser in checkpolicy and module data structures in libsepol, I have implemented doubly-linked list and iterator data types. The attached patch adds these to libsepol.
I would appreciate feedback on these before I submit larger patches that make use of them. In particular:
* Is the iterator concept acceptable (I plan to add iterator support to other data types including hashtabs)?
How does this compare with Kevin Carr's previous iterator proposal? How does it compare with the existing _iterate functions in libsepol?
Quoted 2 lines
* We've discussed dropping the use of typedefs on structs (which I do in this patch). Is this what we want to do, or should I add typedefs?
Omitting typedefs is preferred I think.
Signature · 8 lines
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 [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 8 lines · Stephen Smalley
Quoted 5 lines · Karl MacMillan
As part of some work to improve the parser in checkpolicy and module data structures in libsepol, I have implemented doubly-linked list and iterator data types. The attached patch adds these to libsepol.
I would appreciate feedback on these before I submit larger patches that make use of them. In particular:
* Is the iterator concept acceptable (I plan to add iterator support to other data types including hashtabs)?
How does this compare with Kevin Carr's previous iterator proposal?
Different implementations and - as far as I remember - different design. Same basic idea, though.
Quoted 3 lines
How
does it compare with the existing_iteratefunctions in libsepol?
The iterate functions (which are basically the same as the hashtab callbacks) have the same basic goal of allowing external callers to iterate over the elements of a data structure without exposing the implementation of the data structure. To me, the _iterate functions and callbacks have a few problems solved by the iterators:
* Defining callbacks is cumbersome and ofter requires defining data structures for passing complex state (see link.c).
* Iterating through nested data structures using callbacks is even more painful (see semodule_deps.c for an example of where callbacks would have been almost unusable).
* Iterating through multiple, related data structures with the callbacks is also difficult or impossible. Think of what the equivalent callbacks for the example below would be like (simplified):
int reta, retb;
struct sepol_iter *itera, *iterb;
struct sepol_list *a, *b;
reta = sepol_list_begin(a, itera);
retb = sepol_list_begin(b, iterb);
while (reta == SEPOL_OK && retb == SEPOL_OK) {
// do something with the data
sepol_iter_next(itera);
sepol_iter_next(iterb);
}* Controlling the traversal (e.g., only visiting every other element or stopping traversal) is cumbersome.
* Inserting or removing elements into data structures via callbacks is also problematic. At best the performance will be worse. The iterators I am proposing can hold whatever state is needed for fast insertion / deletion while with the callbacks it is hard to connect the callback driver function state (e.g., hashtab_map) with the insertion / deletion functions. The hashtab_map_remove_on_error function does work around this, but mixing insertion and deletions would be very difficult. See test-list.c for an example of how the iterators help with this.
The summary, I think, is that these are a better model overall which is why it is a popular approach (at least in non-C languages). Granted, the situation is that the callbacks are working for our current needs. So I'm not asking for this to be merged without code actually using it (which is coming) - just if there are any fundamental objections.
Quoted 4 lines
Quoted 1 line
* We've discussed dropping the use of typedefs on structs (which I do in this patch). Is this what we want to do, or should I add typedefs?
Omitting typedefs is preferred I think.
Ok.
Karl
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 63 lines · Karl MacMillan
Quoted 5 lines · Stephen Smalley
Quoted 4 lines · Karl MacMillan
As part of some work to improve the parser in checkpolicy and module data structures in libsepol, I have implemented doubly-linked list and iterator data types. The attached patch adds these to libsepol.
Quoted 7 lines
Quoted 5 lines
I would appreciate feedback on these before I submit larger patches that make use of them. In particular:
* Is the iterator concept acceptable (I plan to add iterator support to other data types including hashtabs)?
How does this compare with Kevin Carr's previous iterator proposal?
Different implementations and - as far as I remember - different design. Same basic idea, though.
Quoted 3 lines
How
does it compare with the existing_iteratefunctions in libsepol?The iterate functions (which are basically the same as the hashtab callbacks) have the same basic goal of allowing external callers to iterate over the elements of a data structure without exposing the implementation of the data structure. To me, the
_iteratefunctions and callbacks have a few problems solved by the iterators:* Defining callbacks is cumbersome and ofter requires defining data structures for passing complex state (see
link.c).* Iterating through nested data structures using callbacks is even more painful (see
semodule_deps.cfor an example of where callbacks would have been almost unusable).* Iterating through multiple, related data structures with the callbacks is also difficult or impossible. Think of what the equivalent callbacks for the example below would be like (simplified):
int reta, retb;
structsepol_iter*itera, *iterb;
structsepol_list*a, *b;reta =
sepol_list_begin(a, itera);
retb =sepol_list_begin(b, iterb);while (reta == SEPOL_OK && retb == SEPOL_OK) { // do something with the data sepol_iter_next(itera); sepol_iter_next(iterb); }* Controlling the traversal (e.g., only visiting every other element or stopping traversal) is cumbersome.
* Inserting or removing elements into data structures via callbacks is also problematic. At best the performance will be worse. The iterators I am proposing can hold whatever state is needed for fast insertion / deletion while with the callbacks it is hard to connect the callback driver function state (e.g.,
hashtab_map) with the insertion / deletion functions. Thehashtab_map_remove_on_errorfunction does work around this, but mixing insertion and deletions would be very difficult. Seetest-list.cfor an example of how the iterators help with this.
Quoted 5 lines
The summary, I think, is that these are a better model overall which is why it is a popular approach (at least in non-C languages). Granted, the situation is that the callbacks are working for our current needs. So I'm not asking for this to be merged without code actually using it (which is coming) - just if there are any fundamental objections.
No fundamental objection from me. Just proves that Kevin is always right ;)
Signature · 8 lines
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 [email protected] with the words "unsubscribe selinux" without quotes as the message.