• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* Author : Stephen Smalley, <sds@tycho.nsa.gov> */
3 
4 /*
5  * Updated : Karl MacMillan <kmacmillan@mentalrootkit.com>
6  *
7  * Copyright (C) 2007 Red Hat, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 
25 /* FLASK */
26 
27 /*
28  * Implementation of the hash table type.
29  */
30 
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sepol/policydb/hashtab.h>
34 
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),unsigned int size)35 hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
36 						     const_hashtab_key_t key),
37 			 int (*keycmp) (hashtab_t h,
38 					const_hashtab_key_t key1,
39 					const_hashtab_key_t key2),
40 			 unsigned int size)
41 {
42 
43 	hashtab_t p;
44 	unsigned int i;
45 
46 	p = (hashtab_t) malloc(sizeof(hashtab_val_t));
47 	if (p == NULL)
48 		return p;
49 
50 	memset(p, 0, sizeof(hashtab_val_t));
51 	p->size = size;
52 	p->nel = 0;
53 	p->hash_value = hash_value;
54 	p->keycmp = keycmp;
55 	p->htable = (hashtab_ptr_t *) malloc(sizeof(hashtab_ptr_t) * size);
56 	if (p->htable == NULL) {
57 		free(p);
58 		return NULL;
59 	}
60 	for (i = 0; i < size; i++)
61 		p->htable[i] = (hashtab_ptr_t) NULL;
62 
63 	return p;
64 }
65 
hashtab_check_resize(hashtab_t h)66 static void hashtab_check_resize(hashtab_t h)
67 {
68 	unsigned int hvalue, i, old_size, new_size = h->size;
69 	hashtab_ptr_t *new_htable, *dst, cur, next;
70 
71 	while (new_size <= h->nel && new_size * 2 != 0)
72 		new_size *= 2;
73 
74 	if (h->size == new_size)
75 		return;
76 
77 	new_htable = calloc(new_size, sizeof(*new_htable));
78 	if (!new_htable)
79 		return;
80 
81 	old_size = h->size;
82 	h->size = new_size;
83 
84 	/* Move all elements to the new htable */
85 	for (i = 0; i < old_size; i++) {
86 		cur = h->htable[i];
87 		while (cur != NULL) {
88 			hvalue = h->hash_value(h, cur->key);
89 			dst = &new_htable[hvalue];
90 			while (*dst && h->keycmp(h, cur->key, (*dst)->key) > 0)
91 				dst = &(*dst)->next;
92 
93 			next = cur->next;
94 
95 			cur->next = *dst;
96 			*dst = cur;
97 
98 			cur = next;
99 		}
100 	}
101 	free(h->htable);
102 	h->htable = new_htable;
103 }
104 
hashtab_insert(hashtab_t h,hashtab_key_t key,hashtab_datum_t datum)105 int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
106 {
107 	int hvalue;
108 	hashtab_ptr_t prev, cur, newnode;
109 
110 	if (!h)
111 		return SEPOL_ENOMEM;
112 
113 	hashtab_check_resize(h);
114 
115 	hvalue = h->hash_value(h, key);
116 	prev = NULL;
117 	cur = h->htable[hvalue];
118 	while (cur && h->keycmp(h, key, cur->key) > 0) {
119 		prev = cur;
120 		cur = cur->next;
121 	}
122 
123 	if (cur && (h->keycmp(h, key, cur->key) == 0))
124 		return SEPOL_EEXIST;
125 
126 	newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
127 	if (newnode == NULL)
128 		return SEPOL_ENOMEM;
129 	memset(newnode, 0, sizeof(struct hashtab_node));
130 	newnode->key = key;
131 	newnode->datum = datum;
132 	if (prev) {
133 		newnode->next = prev->next;
134 		prev->next = newnode;
135 	} else {
136 		newnode->next = h->htable[hvalue];
137 		h->htable[hvalue] = newnode;
138 	}
139 
140 	h->nel++;
141 	return SEPOL_OK;
142 }
143 
hashtab_remove(hashtab_t h,hashtab_key_t key,void (* destroy)(hashtab_key_t k,hashtab_datum_t d,void * args),void * args)144 int hashtab_remove(hashtab_t h, hashtab_key_t key,
145 		   void (*destroy) (hashtab_key_t k,
146 				    hashtab_datum_t d, void *args), void *args)
147 {
148 	int hvalue;
149 	hashtab_ptr_t cur, last;
150 
151 	if (!h)
152 		return SEPOL_ENOENT;
153 
154 	hvalue = h->hash_value(h, key);
155 	last = NULL;
156 	cur = h->htable[hvalue];
157 	while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
158 		last = cur;
159 		cur = cur->next;
160 	}
161 
162 	if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
163 		return SEPOL_ENOENT;
164 
165 	if (last == NULL)
166 		h->htable[hvalue] = cur->next;
167 	else
168 		last->next = cur->next;
169 
170 	if (destroy)
171 		destroy(cur->key, cur->datum, args);
172 	free(cur);
173 	h->nel--;
174 	return SEPOL_OK;
175 }
176 
hashtab_search(hashtab_t h,const_hashtab_key_t key)177 hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key)
178 {
179 
180 	int hvalue;
181 	hashtab_ptr_t cur;
182 
183 	if (!h)
184 		return NULL;
185 
186 	hvalue = h->hash_value(h, key);
187 	cur = h->htable[hvalue];
188 	while (cur != NULL && h->keycmp(h, key, cur->key) > 0)
189 		cur = cur->next;
190 
191 	if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
192 		return NULL;
193 
194 	return cur->datum;
195 }
196 
hashtab_destroy(hashtab_t h)197 void hashtab_destroy(hashtab_t h)
198 {
199 	unsigned int i;
200 	hashtab_ptr_t cur, temp;
201 
202 	if (!h)
203 		return;
204 
205 	for (i = 0; i < h->size; i++) {
206 		cur = h->htable[i];
207 		while (cur != NULL) {
208 			temp = cur;
209 			cur = cur->next;
210 			free(temp);
211 		}
212 		h->htable[i] = NULL;
213 	}
214 
215 	free(h->htable);
216 	h->htable = NULL;
217 
218 	free(h);
219 }
220 
hashtab_map(hashtab_t h,int (* apply)(hashtab_key_t k,hashtab_datum_t d,void * args),void * args)221 int hashtab_map(hashtab_t h,
222 		int (*apply) (hashtab_key_t k,
223 			      hashtab_datum_t d, void *args), void *args)
224 {
225 	unsigned int i, ret;
226 	hashtab_ptr_t cur;
227 
228 	if (!h)
229 		return SEPOL_OK;
230 
231 	for (i = 0; i < h->size; i++) {
232 		cur = h->htable[i];
233 		while (cur != NULL) {
234 			ret = apply(cur->key, cur->datum, args);
235 			if (ret)
236 				return ret;
237 			cur = cur->next;
238 		}
239 	}
240 	return SEPOL_OK;
241 }
242 
hashtab_hash_eval(hashtab_t h,char * tag)243 void hashtab_hash_eval(hashtab_t h, char *tag)
244 {
245 	unsigned int i;
246 	int chain_len, slots_used, max_chain_len;
247 	hashtab_ptr_t cur;
248 
249 	slots_used = 0;
250 	max_chain_len = 0;
251 	for (i = 0; i < h->size; i++) {
252 		cur = h->htable[i];
253 		if (cur) {
254 			slots_used++;
255 			chain_len = 0;
256 			while (cur) {
257 				chain_len++;
258 				cur = cur->next;
259 			}
260 
261 			if (chain_len > max_chain_len)
262 				max_chain_len = chain_len;
263 		}
264 	}
265 
266 	printf
267 	    ("%s:  %d entries and %d/%d buckets used, longest chain length %d\n",
268 	     tag, h->nel, slots_used, h->size, max_chain_len);
269 }
270