1*2d543d20SAndroid Build Coastguard Worker
2*2d543d20SAndroid Build Coastguard Worker /* Author : Stephen Smalley, <[email protected]> */
3*2d543d20SAndroid Build Coastguard Worker
4*2d543d20SAndroid Build Coastguard Worker /* FLASK */
5*2d543d20SAndroid Build Coastguard Worker
6*2d543d20SAndroid Build Coastguard Worker /*
7*2d543d20SAndroid Build Coastguard Worker * Implementation of the hash table type.
8*2d543d20SAndroid Build Coastguard Worker */
9*2d543d20SAndroid Build Coastguard Worker
10*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
11*2d543d20SAndroid Build Coastguard Worker #include <string.h>
12*2d543d20SAndroid Build Coastguard Worker #include "hashtab.h"
13*2d543d20SAndroid Build Coastguard Worker
selinux_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)14*2d543d20SAndroid Build Coastguard Worker hashtab_t selinux_hashtab_create(unsigned int (*hash_value) (hashtab_t h,
15*2d543d20SAndroid Build Coastguard Worker const_hashtab_key_t key),
16*2d543d20SAndroid Build Coastguard Worker int (*keycmp) (hashtab_t h,
17*2d543d20SAndroid Build Coastguard Worker const_hashtab_key_t key1,
18*2d543d20SAndroid Build Coastguard Worker const_hashtab_key_t key2),
19*2d543d20SAndroid Build Coastguard Worker unsigned int size)
20*2d543d20SAndroid Build Coastguard Worker {
21*2d543d20SAndroid Build Coastguard Worker
22*2d543d20SAndroid Build Coastguard Worker hashtab_t p;
23*2d543d20SAndroid Build Coastguard Worker unsigned int i;
24*2d543d20SAndroid Build Coastguard Worker
25*2d543d20SAndroid Build Coastguard Worker p = (hashtab_t) malloc(sizeof(hashtab_val_t));
26*2d543d20SAndroid Build Coastguard Worker if (p == NULL)
27*2d543d20SAndroid Build Coastguard Worker return p;
28*2d543d20SAndroid Build Coastguard Worker
29*2d543d20SAndroid Build Coastguard Worker memset(p, 0, sizeof(hashtab_val_t));
30*2d543d20SAndroid Build Coastguard Worker p->size = size;
31*2d543d20SAndroid Build Coastguard Worker p->nel = 0;
32*2d543d20SAndroid Build Coastguard Worker p->hash_value = hash_value;
33*2d543d20SAndroid Build Coastguard Worker p->keycmp = keycmp;
34*2d543d20SAndroid Build Coastguard Worker p->htable = (hashtab_ptr_t *) malloc(sizeof(hashtab_ptr_t) * size);
35*2d543d20SAndroid Build Coastguard Worker if (p->htable == NULL) {
36*2d543d20SAndroid Build Coastguard Worker free(p);
37*2d543d20SAndroid Build Coastguard Worker return NULL;
38*2d543d20SAndroid Build Coastguard Worker }
39*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < size; i++)
40*2d543d20SAndroid Build Coastguard Worker p->htable[i] = (hashtab_ptr_t) NULL;
41*2d543d20SAndroid Build Coastguard Worker
42*2d543d20SAndroid Build Coastguard Worker return p;
43*2d543d20SAndroid Build Coastguard Worker }
44*2d543d20SAndroid Build Coastguard Worker
selinux_hashtab_insert(hashtab_t h,hashtab_key_t key,hashtab_datum_t datum)45*2d543d20SAndroid Build Coastguard Worker int selinux_hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
46*2d543d20SAndroid Build Coastguard Worker {
47*2d543d20SAndroid Build Coastguard Worker unsigned int hvalue;
48*2d543d20SAndroid Build Coastguard Worker hashtab_ptr_t prev, cur, newnode;
49*2d543d20SAndroid Build Coastguard Worker
50*2d543d20SAndroid Build Coastguard Worker if (!h)
51*2d543d20SAndroid Build Coastguard Worker return HASHTAB_OVERFLOW;
52*2d543d20SAndroid Build Coastguard Worker
53*2d543d20SAndroid Build Coastguard Worker hvalue = h->hash_value(h, key);
54*2d543d20SAndroid Build Coastguard Worker prev = NULL;
55*2d543d20SAndroid Build Coastguard Worker cur = h->htable[hvalue];
56*2d543d20SAndroid Build Coastguard Worker while (cur && h->keycmp(h, key, cur->key) > 0) {
57*2d543d20SAndroid Build Coastguard Worker prev = cur;
58*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
59*2d543d20SAndroid Build Coastguard Worker }
60*2d543d20SAndroid Build Coastguard Worker
61*2d543d20SAndroid Build Coastguard Worker if (cur && (h->keycmp(h, key, cur->key) == 0))
62*2d543d20SAndroid Build Coastguard Worker return HASHTAB_PRESENT;
63*2d543d20SAndroid Build Coastguard Worker
64*2d543d20SAndroid Build Coastguard Worker newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
65*2d543d20SAndroid Build Coastguard Worker if (newnode == NULL)
66*2d543d20SAndroid Build Coastguard Worker return HASHTAB_OVERFLOW;
67*2d543d20SAndroid Build Coastguard Worker memset(newnode, 0, sizeof(struct hashtab_node));
68*2d543d20SAndroid Build Coastguard Worker newnode->key = key;
69*2d543d20SAndroid Build Coastguard Worker newnode->datum = datum;
70*2d543d20SAndroid Build Coastguard Worker if (prev) {
71*2d543d20SAndroid Build Coastguard Worker newnode->next = prev->next;
72*2d543d20SAndroid Build Coastguard Worker prev->next = newnode;
73*2d543d20SAndroid Build Coastguard Worker } else {
74*2d543d20SAndroid Build Coastguard Worker newnode->next = h->htable[hvalue];
75*2d543d20SAndroid Build Coastguard Worker h->htable[hvalue] = newnode;
76*2d543d20SAndroid Build Coastguard Worker }
77*2d543d20SAndroid Build Coastguard Worker
78*2d543d20SAndroid Build Coastguard Worker h->nel++;
79*2d543d20SAndroid Build Coastguard Worker return HASHTAB_SUCCESS;
80*2d543d20SAndroid Build Coastguard Worker }
81*2d543d20SAndroid Build Coastguard Worker
selinux_hashtab_remove(hashtab_t h,hashtab_key_t key,void (* destroy)(hashtab_key_t k,hashtab_datum_t d,void * args),void * args)82*2d543d20SAndroid Build Coastguard Worker int selinux_hashtab_remove(hashtab_t h, hashtab_key_t key,
83*2d543d20SAndroid Build Coastguard Worker void (*destroy) (hashtab_key_t k,
84*2d543d20SAndroid Build Coastguard Worker hashtab_datum_t d, void *args), void *args)
85*2d543d20SAndroid Build Coastguard Worker {
86*2d543d20SAndroid Build Coastguard Worker unsigned int hvalue;
87*2d543d20SAndroid Build Coastguard Worker hashtab_ptr_t cur, last;
88*2d543d20SAndroid Build Coastguard Worker
89*2d543d20SAndroid Build Coastguard Worker if (!h)
90*2d543d20SAndroid Build Coastguard Worker return HASHTAB_MISSING;
91*2d543d20SAndroid Build Coastguard Worker
92*2d543d20SAndroid Build Coastguard Worker hvalue = h->hash_value(h, key);
93*2d543d20SAndroid Build Coastguard Worker last = NULL;
94*2d543d20SAndroid Build Coastguard Worker cur = h->htable[hvalue];
95*2d543d20SAndroid Build Coastguard Worker while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
96*2d543d20SAndroid Build Coastguard Worker last = cur;
97*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
98*2d543d20SAndroid Build Coastguard Worker }
99*2d543d20SAndroid Build Coastguard Worker
100*2d543d20SAndroid Build Coastguard Worker if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
101*2d543d20SAndroid Build Coastguard Worker return HASHTAB_MISSING;
102*2d543d20SAndroid Build Coastguard Worker
103*2d543d20SAndroid Build Coastguard Worker if (last == NULL)
104*2d543d20SAndroid Build Coastguard Worker h->htable[hvalue] = cur->next;
105*2d543d20SAndroid Build Coastguard Worker else
106*2d543d20SAndroid Build Coastguard Worker last->next = cur->next;
107*2d543d20SAndroid Build Coastguard Worker
108*2d543d20SAndroid Build Coastguard Worker if (destroy)
109*2d543d20SAndroid Build Coastguard Worker destroy(cur->key, cur->datum, args);
110*2d543d20SAndroid Build Coastguard Worker free(cur);
111*2d543d20SAndroid Build Coastguard Worker h->nel--;
112*2d543d20SAndroid Build Coastguard Worker return HASHTAB_SUCCESS;
113*2d543d20SAndroid Build Coastguard Worker }
114*2d543d20SAndroid Build Coastguard Worker
selinux_hashtab_search(hashtab_t h,const_hashtab_key_t key)115*2d543d20SAndroid Build Coastguard Worker hashtab_datum_t selinux_hashtab_search(hashtab_t h, const_hashtab_key_t key)
116*2d543d20SAndroid Build Coastguard Worker {
117*2d543d20SAndroid Build Coastguard Worker
118*2d543d20SAndroid Build Coastguard Worker unsigned int hvalue;
119*2d543d20SAndroid Build Coastguard Worker hashtab_ptr_t cur;
120*2d543d20SAndroid Build Coastguard Worker
121*2d543d20SAndroid Build Coastguard Worker if (!h)
122*2d543d20SAndroid Build Coastguard Worker return NULL;
123*2d543d20SAndroid Build Coastguard Worker
124*2d543d20SAndroid Build Coastguard Worker hvalue = h->hash_value(h, key);
125*2d543d20SAndroid Build Coastguard Worker cur = h->htable[hvalue];
126*2d543d20SAndroid Build Coastguard Worker while (cur != NULL && h->keycmp(h, key, cur->key) > 0)
127*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
128*2d543d20SAndroid Build Coastguard Worker
129*2d543d20SAndroid Build Coastguard Worker if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
130*2d543d20SAndroid Build Coastguard Worker return NULL;
131*2d543d20SAndroid Build Coastguard Worker
132*2d543d20SAndroid Build Coastguard Worker return cur->datum;
133*2d543d20SAndroid Build Coastguard Worker }
134*2d543d20SAndroid Build Coastguard Worker
selinux_hashtab_destroy(hashtab_t h)135*2d543d20SAndroid Build Coastguard Worker void selinux_hashtab_destroy(hashtab_t h)
136*2d543d20SAndroid Build Coastguard Worker {
137*2d543d20SAndroid Build Coastguard Worker unsigned int i;
138*2d543d20SAndroid Build Coastguard Worker hashtab_ptr_t cur, temp;
139*2d543d20SAndroid Build Coastguard Worker
140*2d543d20SAndroid Build Coastguard Worker if (!h)
141*2d543d20SAndroid Build Coastguard Worker return;
142*2d543d20SAndroid Build Coastguard Worker
143*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < h->size; i++) {
144*2d543d20SAndroid Build Coastguard Worker cur = h->htable[i];
145*2d543d20SAndroid Build Coastguard Worker while (cur != NULL) {
146*2d543d20SAndroid Build Coastguard Worker temp = cur;
147*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
148*2d543d20SAndroid Build Coastguard Worker free(temp);
149*2d543d20SAndroid Build Coastguard Worker }
150*2d543d20SAndroid Build Coastguard Worker h->htable[i] = NULL;
151*2d543d20SAndroid Build Coastguard Worker }
152*2d543d20SAndroid Build Coastguard Worker
153*2d543d20SAndroid Build Coastguard Worker free(h->htable);
154*2d543d20SAndroid Build Coastguard Worker h->htable = NULL;
155*2d543d20SAndroid Build Coastguard Worker
156*2d543d20SAndroid Build Coastguard Worker free(h);
157*2d543d20SAndroid Build Coastguard Worker }
158*2d543d20SAndroid Build Coastguard Worker
selinux_hashtab_destroy_key(hashtab_t h,int (* destroy_key)(hashtab_key_t k))159*2d543d20SAndroid Build Coastguard Worker void selinux_hashtab_destroy_key(hashtab_t h,
160*2d543d20SAndroid Build Coastguard Worker int (*destroy_key) (hashtab_key_t k))
161*2d543d20SAndroid Build Coastguard Worker {
162*2d543d20SAndroid Build Coastguard Worker unsigned int i;
163*2d543d20SAndroid Build Coastguard Worker hashtab_ptr_t cur, temp;
164*2d543d20SAndroid Build Coastguard Worker
165*2d543d20SAndroid Build Coastguard Worker if (!h)
166*2d543d20SAndroid Build Coastguard Worker return;
167*2d543d20SAndroid Build Coastguard Worker
168*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < h->size; i++) {
169*2d543d20SAndroid Build Coastguard Worker cur = h->htable[i];
170*2d543d20SAndroid Build Coastguard Worker while (cur != NULL) {
171*2d543d20SAndroid Build Coastguard Worker temp = cur;
172*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
173*2d543d20SAndroid Build Coastguard Worker destroy_key(temp->key);
174*2d543d20SAndroid Build Coastguard Worker free(temp);
175*2d543d20SAndroid Build Coastguard Worker }
176*2d543d20SAndroid Build Coastguard Worker h->htable[i] = NULL;
177*2d543d20SAndroid Build Coastguard Worker }
178*2d543d20SAndroid Build Coastguard Worker
179*2d543d20SAndroid Build Coastguard Worker free(h->htable);
180*2d543d20SAndroid Build Coastguard Worker h->htable = NULL;
181*2d543d20SAndroid Build Coastguard Worker
182*2d543d20SAndroid Build Coastguard Worker free(h);
183*2d543d20SAndroid Build Coastguard Worker }
184*2d543d20SAndroid Build Coastguard Worker
selinux_hashtab_map(hashtab_t h,int (* apply)(hashtab_key_t k,hashtab_datum_t d,void * args),void * args)185*2d543d20SAndroid Build Coastguard Worker int selinux_hashtab_map(hashtab_t h,
186*2d543d20SAndroid Build Coastguard Worker int (*apply) (hashtab_key_t k,
187*2d543d20SAndroid Build Coastguard Worker hashtab_datum_t d, void *args), void *args)
188*2d543d20SAndroid Build Coastguard Worker {
189*2d543d20SAndroid Build Coastguard Worker unsigned int i;
190*2d543d20SAndroid Build Coastguard Worker hashtab_ptr_t cur;
191*2d543d20SAndroid Build Coastguard Worker int ret;
192*2d543d20SAndroid Build Coastguard Worker
193*2d543d20SAndroid Build Coastguard Worker if (!h)
194*2d543d20SAndroid Build Coastguard Worker return HASHTAB_SUCCESS;
195*2d543d20SAndroid Build Coastguard Worker
196*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < h->size; i++) {
197*2d543d20SAndroid Build Coastguard Worker cur = h->htable[i];
198*2d543d20SAndroid Build Coastguard Worker while (cur != NULL) {
199*2d543d20SAndroid Build Coastguard Worker ret = apply(cur->key, cur->datum, args);
200*2d543d20SAndroid Build Coastguard Worker if (ret)
201*2d543d20SAndroid Build Coastguard Worker return ret;
202*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
203*2d543d20SAndroid Build Coastguard Worker }
204*2d543d20SAndroid Build Coastguard Worker }
205*2d543d20SAndroid Build Coastguard Worker return HASHTAB_SUCCESS;
206*2d543d20SAndroid Build Coastguard Worker }
207*2d543d20SAndroid Build Coastguard Worker
selinux_hashtab_hash_eval(hashtab_t h,char * tag)208*2d543d20SAndroid Build Coastguard Worker void selinux_hashtab_hash_eval(hashtab_t h, char *tag)
209*2d543d20SAndroid Build Coastguard Worker {
210*2d543d20SAndroid Build Coastguard Worker unsigned int i;
211*2d543d20SAndroid Build Coastguard Worker int chain_len, slots_used, max_chain_len;
212*2d543d20SAndroid Build Coastguard Worker hashtab_ptr_t cur;
213*2d543d20SAndroid Build Coastguard Worker
214*2d543d20SAndroid Build Coastguard Worker slots_used = 0;
215*2d543d20SAndroid Build Coastguard Worker max_chain_len = 0;
216*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < h->size; i++) {
217*2d543d20SAndroid Build Coastguard Worker cur = h->htable[i];
218*2d543d20SAndroid Build Coastguard Worker if (cur) {
219*2d543d20SAndroid Build Coastguard Worker slots_used++;
220*2d543d20SAndroid Build Coastguard Worker chain_len = 0;
221*2d543d20SAndroid Build Coastguard Worker while (cur) {
222*2d543d20SAndroid Build Coastguard Worker chain_len++;
223*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
224*2d543d20SAndroid Build Coastguard Worker }
225*2d543d20SAndroid Build Coastguard Worker
226*2d543d20SAndroid Build Coastguard Worker if (chain_len > max_chain_len)
227*2d543d20SAndroid Build Coastguard Worker max_chain_len = chain_len;
228*2d543d20SAndroid Build Coastguard Worker }
229*2d543d20SAndroid Build Coastguard Worker }
230*2d543d20SAndroid Build Coastguard Worker
231*2d543d20SAndroid Build Coastguard Worker printf
232*2d543d20SAndroid Build Coastguard Worker ("%s: %d entries and %d/%d buckets used, longest chain length %d\n",
233*2d543d20SAndroid Build Coastguard Worker tag, h->nel, slots_used, h->size, max_chain_len);
234*2d543d20SAndroid Build Coastguard Worker }
235