• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdarg.h>
32 
33 #include "cil_internal.h"
34 #include "cil_flavor.h"
35 #include "cil_log.h"
36 #include "cil_mem.h"
37 
cil_list_error(const char * msg,...)38 __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) static void cil_list_error(const char* msg, ...)
39 {
40 	va_list ap;
41 	va_start(ap, msg);
42 	cil_vlog(CIL_ERR, msg, ap);
43 	va_end(ap);
44 	exit(1);
45 }
46 
cil_list_init(struct cil_list ** list,enum cil_flavor flavor)47 void cil_list_init(struct cil_list **list, enum cil_flavor flavor)
48 {
49 	struct cil_list *new_list = cil_malloc(sizeof(*new_list));
50 	new_list->head = NULL;
51 	new_list->tail = NULL;
52 	new_list->flavor = flavor;
53 	*list = new_list;
54 }
55 
cil_list_destroy(struct cil_list ** list,unsigned destroy_data)56 void cil_list_destroy(struct cil_list **list, unsigned destroy_data)
57 {
58 	struct cil_list_item *item;
59 
60 	if (*list == NULL) {
61 		return;
62 	}
63 
64 	item = (*list)->head;
65 	while (item != NULL)
66 	{
67 		struct cil_list_item *next = item->next;
68 		if (item->flavor == CIL_LIST) {
69 			cil_list_destroy((struct cil_list**)&(item->data), destroy_data);
70 			free(item);
71 		} else {
72 			cil_list_item_destroy(&item, destroy_data);
73 		}
74 		item = next;
75 	}
76 	free(*list);
77 	*list = NULL;
78 }
79 
cil_list_item_init(struct cil_list_item ** item)80 void cil_list_item_init(struct cil_list_item **item)
81 {
82 	struct cil_list_item *new_item = cil_malloc(sizeof(*new_item));
83 	new_item->next = NULL;
84 	new_item->flavor = CIL_NONE;
85 	new_item->data = NULL;
86 
87 	*item = new_item;
88 }
89 
cil_list_item_destroy(struct cil_list_item ** item,unsigned destroy_data)90 void cil_list_item_destroy(struct cil_list_item **item, unsigned destroy_data)
91 {
92 	if (destroy_data) {
93 		cil_destroy_data(&(*item)->data, (*item)->flavor);
94 	}
95 	free(*item);
96 	*item = NULL;
97 }
98 
cil_list_append(struct cil_list * list,enum cil_flavor flavor,void * data)99 void cil_list_append(struct cil_list *list, enum cil_flavor flavor, void *data)
100 {
101 	struct cil_list_item *item;
102 
103 	if (list == NULL) {
104 		cil_list_error("Attempt to append data to a NULL list");
105 	}
106 
107 	cil_list_item_init(&item);
108 	item->flavor = flavor;
109 	item->data = data;
110 
111 	if (list->tail == NULL) {
112 		list->head = item;
113 		list->tail = item;
114 		return;
115 	}
116 
117 	list->tail->next = item;
118 	list->tail = item;
119 }
120 
cil_list_prepend(struct cil_list * list,enum cil_flavor flavor,void * data)121 void cil_list_prepend(struct cil_list *list, enum cil_flavor flavor, void *data)
122 {
123 	struct cil_list_item *item;
124 
125 	if (list == NULL) {
126 		cil_list_error("Attempt to prepend data to a NULL list");
127 	}
128 
129 	cil_list_item_init(&item);
130 	item->flavor = flavor;
131 	item->data = data;
132 
133 	if (list->tail == NULL) {
134 		list->head = item;
135 		list->tail = item;
136 		return;
137 	}
138 
139 	item->next = list->head;
140 	list->head = item;
141 }
142 
cil_list_insert(struct cil_list * list,struct cil_list_item * curr,enum cil_flavor flavor,void * data)143 struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data)
144 {
145 	struct cil_list_item *item;
146 
147 	if (list == NULL) {
148 		cil_list_error("Attempt to append data to a NULL list");
149 	}
150 
151 	if (curr == NULL) {
152 		/* Insert at the front of the list */
153 		cil_list_prepend(list, flavor, data);
154 		return list->head;
155 	}
156 
157 	if (curr == list->tail) {
158 		cil_list_append(list, flavor, data);
159 		return list->tail;
160 	}
161 
162 	cil_list_item_init(&item);
163 	item->flavor = flavor;
164 	item->data = data;
165 	item->next = curr->next;
166 
167 	curr->next = item;
168 
169 	return item;
170 }
171 
cil_list_append_item(struct cil_list * list,struct cil_list_item * item)172 void cil_list_append_item(struct cil_list *list, struct cil_list_item *item)
173 {
174 	struct cil_list_item *last = item;
175 
176 	if (list == NULL) {
177 		cil_list_error("Attempt to append an item to a NULL list");
178 	}
179 
180 	if (item == NULL) {
181 		cil_list_error("Attempt to append a NULL item to a list");
182 	}
183 
184 	while (last->next != NULL) {
185 		last = last->next;
186 	}
187 
188 	if (list->tail == NULL) {
189 		list->head = item;
190 		list->tail = last;
191 		return;
192 	}
193 
194 	list->tail->next = item;
195 	list->tail = last;
196 
197 }
198 
cil_list_prepend_item(struct cil_list * list,struct cil_list_item * item)199 void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item)
200 {
201 	struct cil_list_item *last = item;
202 
203 	if (list == NULL) {
204 		cil_list_error("Attempt to prepend an item to a NULL list");
205 	}
206 
207 	if (item == NULL) {
208 		cil_list_error("Attempt to prepend a NULL item to a list");
209 	}
210 
211 	while (last->next != NULL) {
212 		last = last->next;
213 	}
214 
215 	if (list->tail == NULL) {
216 		list->head = item;
217 		list->tail = last;
218 		return;
219 	}
220 
221 	last->next = list->head;
222 	list->head = item;
223 }
224 
cil_list_remove(struct cil_list * list,enum cil_flavor flavor,void * data,unsigned destroy_data)225 void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data, unsigned destroy_data)
226 {
227 	struct cil_list_item *item;
228 	struct cil_list_item *previous = NULL;
229 
230 	if (list == NULL) {
231 		cil_list_error("Attempt to remove data from a NULL list");
232 	}
233 
234 	cil_list_for_each(item, list) {
235 		if (item->data == data && item->flavor == flavor) {
236 			if (previous == NULL) {
237 				list->head = item->next;
238 			} else {
239 				previous->next = item->next;
240 			}
241 			if (item->next == NULL) {
242 				list->tail = previous;
243 			}
244 			cil_list_item_destroy(&item, destroy_data);
245 			break;
246 		}
247 		previous = item;
248 	}
249 }
250 
cil_list_contains(struct cil_list * list,void * data)251 int cil_list_contains(struct cil_list *list, void *data)
252 {
253 	struct cil_list_item *curr = NULL;
254 
255 	cil_list_for_each(curr, list) {
256 		if (curr->data == data) {
257 			return CIL_TRUE;
258 		}
259 	}
260 
261 	return CIL_FALSE;
262 }
263 
cil_list_match_any(struct cil_list * l1,struct cil_list * l2)264 int cil_list_match_any(struct cil_list *l1, struct cil_list *l2)
265 {
266 	struct cil_list_item *i1;
267 	struct cil_list_item *i2;
268 
269 	cil_list_for_each(i1, l1) {
270 		cil_list_for_each(i2, l2) {
271 			if (i1->data == i2->data && i1->flavor == i2->flavor) {
272 				return CIL_TRUE;
273 			}
274 		}
275 	}
276 
277 	return CIL_FALSE;
278 }
279