xref: /aosp_15_r20/external/selinux/libsepol/src/ebitmap.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
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 extensible bitmap type.
8*2d543d20SAndroid Build Coastguard Worker  */
9*2d543d20SAndroid Build Coastguard Worker 
10*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
11*2d543d20SAndroid Build Coastguard Worker 
12*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/ebitmap.h>
13*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
14*2d543d20SAndroid Build Coastguard Worker 
15*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
16*2d543d20SAndroid Build Coastguard Worker #include "private.h"
17*2d543d20SAndroid Build Coastguard Worker 
ebitmap_or(ebitmap_t * dst,const ebitmap_t * e1,const ebitmap_t * e2)18*2d543d20SAndroid Build Coastguard Worker int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2)
19*2d543d20SAndroid Build Coastguard Worker {
20*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n1, *n2;
21*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *new = NULL, **prev;
22*2d543d20SAndroid Build Coastguard Worker 
23*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(dst);
24*2d543d20SAndroid Build Coastguard Worker 
25*2d543d20SAndroid Build Coastguard Worker 	prev = &dst->node;
26*2d543d20SAndroid Build Coastguard Worker 	n1 = e1->node;
27*2d543d20SAndroid Build Coastguard Worker 	n2 = e2->node;
28*2d543d20SAndroid Build Coastguard Worker 	while (n1 || n2) {
29*2d543d20SAndroid Build Coastguard Worker 		new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
30*2d543d20SAndroid Build Coastguard Worker 		if (!new) {
31*2d543d20SAndroid Build Coastguard Worker 			ebitmap_destroy(dst);
32*2d543d20SAndroid Build Coastguard Worker 			return -ENOMEM;
33*2d543d20SAndroid Build Coastguard Worker 		}
34*2d543d20SAndroid Build Coastguard Worker 		if (n1 && n2 && n1->startbit == n2->startbit) {
35*2d543d20SAndroid Build Coastguard Worker 			new->startbit = n1->startbit;
36*2d543d20SAndroid Build Coastguard Worker 			new->map = n1->map | n2->map;
37*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
38*2d543d20SAndroid Build Coastguard Worker 			n2 = n2->next;
39*2d543d20SAndroid Build Coastguard Worker 		} else if (!n2 || (n1 && n1->startbit < n2->startbit)) {
40*2d543d20SAndroid Build Coastguard Worker 			new->startbit = n1->startbit;
41*2d543d20SAndroid Build Coastguard Worker 			new->map = n1->map;
42*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
43*2d543d20SAndroid Build Coastguard Worker 		} else {
44*2d543d20SAndroid Build Coastguard Worker 			new->startbit = n2->startbit;
45*2d543d20SAndroid Build Coastguard Worker 			new->map = n2->map;
46*2d543d20SAndroid Build Coastguard Worker 			n2 = n2->next;
47*2d543d20SAndroid Build Coastguard Worker 		}
48*2d543d20SAndroid Build Coastguard Worker 
49*2d543d20SAndroid Build Coastguard Worker 		new->next = NULL;
50*2d543d20SAndroid Build Coastguard Worker 
51*2d543d20SAndroid Build Coastguard Worker 		*prev = new;
52*2d543d20SAndroid Build Coastguard Worker 		prev = &new->next;
53*2d543d20SAndroid Build Coastguard Worker 	}
54*2d543d20SAndroid Build Coastguard Worker 
55*2d543d20SAndroid Build Coastguard Worker 	dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit;
56*2d543d20SAndroid Build Coastguard Worker 	return 0;
57*2d543d20SAndroid Build Coastguard Worker }
58*2d543d20SAndroid Build Coastguard Worker 
ebitmap_union(ebitmap_t * dst,const ebitmap_t * e1)59*2d543d20SAndroid Build Coastguard Worker int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1)
60*2d543d20SAndroid Build Coastguard Worker {
61*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t tmp;
62*2d543d20SAndroid Build Coastguard Worker 
63*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_or(&tmp, dst, e1))
64*2d543d20SAndroid Build Coastguard Worker 		return -1;
65*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(dst);
66*2d543d20SAndroid Build Coastguard Worker 	dst->node = tmp.node;
67*2d543d20SAndroid Build Coastguard Worker 	dst->highbit = tmp.highbit;
68*2d543d20SAndroid Build Coastguard Worker 
69*2d543d20SAndroid Build Coastguard Worker 	return 0;
70*2d543d20SAndroid Build Coastguard Worker }
71*2d543d20SAndroid Build Coastguard Worker 
ebitmap_and(ebitmap_t * dst,const ebitmap_t * e1,const ebitmap_t * e2)72*2d543d20SAndroid Build Coastguard Worker int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2)
73*2d543d20SAndroid Build Coastguard Worker {
74*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n1, *n2;
75*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *new = NULL, **prev;
76*2d543d20SAndroid Build Coastguard Worker 
77*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(dst);
78*2d543d20SAndroid Build Coastguard Worker 
79*2d543d20SAndroid Build Coastguard Worker 	prev = &dst->node;
80*2d543d20SAndroid Build Coastguard Worker 	n1 = e1->node;
81*2d543d20SAndroid Build Coastguard Worker 	n2 = e2->node;
82*2d543d20SAndroid Build Coastguard Worker 	while (n1 && n2) {
83*2d543d20SAndroid Build Coastguard Worker 		if (n1->startbit == n2->startbit) {
84*2d543d20SAndroid Build Coastguard Worker 			if (n1->map & n2->map) {
85*2d543d20SAndroid Build Coastguard Worker 				new = malloc(sizeof(ebitmap_node_t));
86*2d543d20SAndroid Build Coastguard Worker 				if (!new) {
87*2d543d20SAndroid Build Coastguard Worker 					ebitmap_destroy(dst);
88*2d543d20SAndroid Build Coastguard Worker 					return -ENOMEM;
89*2d543d20SAndroid Build Coastguard Worker 				}
90*2d543d20SAndroid Build Coastguard Worker 				new->startbit = n1->startbit;
91*2d543d20SAndroid Build Coastguard Worker 				new->map = n1->map & n2->map;
92*2d543d20SAndroid Build Coastguard Worker 				new->next = NULL;
93*2d543d20SAndroid Build Coastguard Worker 
94*2d543d20SAndroid Build Coastguard Worker 				*prev = new;
95*2d543d20SAndroid Build Coastguard Worker 				prev = &new->next;
96*2d543d20SAndroid Build Coastguard Worker 			}
97*2d543d20SAndroid Build Coastguard Worker 
98*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
99*2d543d20SAndroid Build Coastguard Worker 			n2 = n2->next;
100*2d543d20SAndroid Build Coastguard Worker 		} else if (n1->startbit > n2->startbit) {
101*2d543d20SAndroid Build Coastguard Worker 			n2 = n2->next;
102*2d543d20SAndroid Build Coastguard Worker 		} else {
103*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
104*2d543d20SAndroid Build Coastguard Worker 		}
105*2d543d20SAndroid Build Coastguard Worker 	}
106*2d543d20SAndroid Build Coastguard Worker 
107*2d543d20SAndroid Build Coastguard Worker 	if (new)
108*2d543d20SAndroid Build Coastguard Worker 		dst->highbit = new->startbit + MAPSIZE;
109*2d543d20SAndroid Build Coastguard Worker 
110*2d543d20SAndroid Build Coastguard Worker 	return 0;
111*2d543d20SAndroid Build Coastguard Worker }
112*2d543d20SAndroid Build Coastguard Worker 
ebitmap_xor(ebitmap_t * dst,const ebitmap_t * e1,const ebitmap_t * e2)113*2d543d20SAndroid Build Coastguard Worker int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2)
114*2d543d20SAndroid Build Coastguard Worker {
115*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n1, *n2;
116*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *new = NULL, **prev;
117*2d543d20SAndroid Build Coastguard Worker 	uint32_t startbit;
118*2d543d20SAndroid Build Coastguard Worker 	MAPTYPE map;
119*2d543d20SAndroid Build Coastguard Worker 
120*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(dst);
121*2d543d20SAndroid Build Coastguard Worker 
122*2d543d20SAndroid Build Coastguard Worker 	prev = &dst->node;
123*2d543d20SAndroid Build Coastguard Worker 	n1 = e1->node;
124*2d543d20SAndroid Build Coastguard Worker 	n2 = e2->node;
125*2d543d20SAndroid Build Coastguard Worker 	while (n1 || n2) {
126*2d543d20SAndroid Build Coastguard Worker 		if (n1 && n2 && n1->startbit == n2->startbit) {
127*2d543d20SAndroid Build Coastguard Worker 			startbit = n1->startbit;
128*2d543d20SAndroid Build Coastguard Worker 			map = n1->map ^ n2->map;
129*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
130*2d543d20SAndroid Build Coastguard Worker 			n2 = n2->next;
131*2d543d20SAndroid Build Coastguard Worker 		} else if (!n2 || (n1 && n1->startbit < n2->startbit)) {
132*2d543d20SAndroid Build Coastguard Worker 			startbit = n1->startbit;
133*2d543d20SAndroid Build Coastguard Worker 			map = n1->map;
134*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
135*2d543d20SAndroid Build Coastguard Worker 		} else {
136*2d543d20SAndroid Build Coastguard Worker 			startbit = n2->startbit;
137*2d543d20SAndroid Build Coastguard Worker 			map = n2->map;
138*2d543d20SAndroid Build Coastguard Worker 			n2 = n2->next;
139*2d543d20SAndroid Build Coastguard Worker 		}
140*2d543d20SAndroid Build Coastguard Worker 
141*2d543d20SAndroid Build Coastguard Worker 		if (map != 0) {
142*2d543d20SAndroid Build Coastguard Worker 			new = malloc(sizeof(ebitmap_node_t));
143*2d543d20SAndroid Build Coastguard Worker 			if (!new) {
144*2d543d20SAndroid Build Coastguard Worker 				ebitmap_destroy(dst);
145*2d543d20SAndroid Build Coastguard Worker 				return -ENOMEM;
146*2d543d20SAndroid Build Coastguard Worker 			}
147*2d543d20SAndroid Build Coastguard Worker 			new->startbit = startbit;
148*2d543d20SAndroid Build Coastguard Worker 			new->map = map;
149*2d543d20SAndroid Build Coastguard Worker 			new->next = NULL;
150*2d543d20SAndroid Build Coastguard Worker 
151*2d543d20SAndroid Build Coastguard Worker 			*prev = new;
152*2d543d20SAndroid Build Coastguard Worker 			prev = &new->next;
153*2d543d20SAndroid Build Coastguard Worker 		}
154*2d543d20SAndroid Build Coastguard Worker 	}
155*2d543d20SAndroid Build Coastguard Worker 
156*2d543d20SAndroid Build Coastguard Worker 	if (new)
157*2d543d20SAndroid Build Coastguard Worker 		dst->highbit = new->startbit + MAPSIZE;
158*2d543d20SAndroid Build Coastguard Worker 
159*2d543d20SAndroid Build Coastguard Worker 	return 0;
160*2d543d20SAndroid Build Coastguard Worker }
161*2d543d20SAndroid Build Coastguard Worker 
ebitmap_not(ebitmap_t * dst,const ebitmap_t * e1,unsigned int maxbit)162*2d543d20SAndroid Build Coastguard Worker int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit)
163*2d543d20SAndroid Build Coastguard Worker {
164*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n;
165*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *new = NULL, **prev;
166*2d543d20SAndroid Build Coastguard Worker 	uint32_t startbit, cur_startbit;
167*2d543d20SAndroid Build Coastguard Worker 	MAPTYPE map;
168*2d543d20SAndroid Build Coastguard Worker 
169*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(dst);
170*2d543d20SAndroid Build Coastguard Worker 
171*2d543d20SAndroid Build Coastguard Worker 	prev = &dst->node;
172*2d543d20SAndroid Build Coastguard Worker 	n = e1->node;
173*2d543d20SAndroid Build Coastguard Worker 	for (cur_startbit = 0; cur_startbit < maxbit; cur_startbit += MAPSIZE) {
174*2d543d20SAndroid Build Coastguard Worker 		if (n && n->startbit == cur_startbit) {
175*2d543d20SAndroid Build Coastguard Worker 			startbit = n->startbit;
176*2d543d20SAndroid Build Coastguard Worker 			map = ~n->map;
177*2d543d20SAndroid Build Coastguard Worker 
178*2d543d20SAndroid Build Coastguard Worker 			n = n->next;
179*2d543d20SAndroid Build Coastguard Worker 		} else {
180*2d543d20SAndroid Build Coastguard Worker 			startbit = cur_startbit;
181*2d543d20SAndroid Build Coastguard Worker 			map = ~((MAPTYPE) 0);
182*2d543d20SAndroid Build Coastguard Worker 		}
183*2d543d20SAndroid Build Coastguard Worker 
184*2d543d20SAndroid Build Coastguard Worker 		if (maxbit - cur_startbit < MAPSIZE)
185*2d543d20SAndroid Build Coastguard Worker 			map &= (((MAPTYPE)1) << (maxbit - cur_startbit)) - 1;
186*2d543d20SAndroid Build Coastguard Worker 
187*2d543d20SAndroid Build Coastguard Worker 		if (map != 0) {
188*2d543d20SAndroid Build Coastguard Worker 			new = malloc(sizeof(ebitmap_node_t));
189*2d543d20SAndroid Build Coastguard Worker 			if (!new) {
190*2d543d20SAndroid Build Coastguard Worker 				ebitmap_destroy(dst);
191*2d543d20SAndroid Build Coastguard Worker 				return -ENOMEM;
192*2d543d20SAndroid Build Coastguard Worker 			}
193*2d543d20SAndroid Build Coastguard Worker 
194*2d543d20SAndroid Build Coastguard Worker 			new->startbit = startbit;
195*2d543d20SAndroid Build Coastguard Worker 			new->map = map;
196*2d543d20SAndroid Build Coastguard Worker 			new->next = NULL;
197*2d543d20SAndroid Build Coastguard Worker 
198*2d543d20SAndroid Build Coastguard Worker 			*prev = new;
199*2d543d20SAndroid Build Coastguard Worker 			prev = &new->next;
200*2d543d20SAndroid Build Coastguard Worker 		}
201*2d543d20SAndroid Build Coastguard Worker 	}
202*2d543d20SAndroid Build Coastguard Worker 
203*2d543d20SAndroid Build Coastguard Worker 	if (new)
204*2d543d20SAndroid Build Coastguard Worker 		dst->highbit = new->startbit + MAPSIZE;
205*2d543d20SAndroid Build Coastguard Worker 
206*2d543d20SAndroid Build Coastguard Worker 	return 0;
207*2d543d20SAndroid Build Coastguard Worker }
208*2d543d20SAndroid Build Coastguard Worker 
ebitmap_andnot(ebitmap_t * dst,const ebitmap_t * e1,const ebitmap_t * e2,unsigned int maxbit)209*2d543d20SAndroid Build Coastguard Worker int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit)
210*2d543d20SAndroid Build Coastguard Worker {
211*2d543d20SAndroid Build Coastguard Worker 	int rc;
212*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t e3;
213*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(dst);
214*2d543d20SAndroid Build Coastguard Worker 	rc = ebitmap_not(&e3, e2, maxbit);
215*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
216*2d543d20SAndroid Build Coastguard Worker 		return rc;
217*2d543d20SAndroid Build Coastguard Worker 	rc = ebitmap_and(dst, e1, &e3);
218*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e3);
219*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
220*2d543d20SAndroid Build Coastguard Worker 		return rc;
221*2d543d20SAndroid Build Coastguard Worker 	return 0;
222*2d543d20SAndroid Build Coastguard Worker }
223*2d543d20SAndroid Build Coastguard Worker 
ebitmap_cardinality(const ebitmap_t * e1)224*2d543d20SAndroid Build Coastguard Worker unsigned int ebitmap_cardinality(const ebitmap_t *e1)
225*2d543d20SAndroid Build Coastguard Worker {
226*2d543d20SAndroid Build Coastguard Worker 	unsigned int count = 0;
227*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n;
228*2d543d20SAndroid Build Coastguard Worker 
229*2d543d20SAndroid Build Coastguard Worker 	for (n = e1->node; n; n = n->next) {
230*2d543d20SAndroid Build Coastguard Worker 		count += __builtin_popcountll(n->map);
231*2d543d20SAndroid Build Coastguard Worker 	}
232*2d543d20SAndroid Build Coastguard Worker 	return count;
233*2d543d20SAndroid Build Coastguard Worker }
234*2d543d20SAndroid Build Coastguard Worker 
ebitmap_hamming_distance(const ebitmap_t * e1,const ebitmap_t * e2)235*2d543d20SAndroid Build Coastguard Worker int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2)
236*2d543d20SAndroid Build Coastguard Worker {
237*2d543d20SAndroid Build Coastguard Worker 	int rc;
238*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t tmp;
239*2d543d20SAndroid Build Coastguard Worker 	int distance;
240*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_cmp(e1, e2))
241*2d543d20SAndroid Build Coastguard Worker 		return 0;
242*2d543d20SAndroid Build Coastguard Worker 	rc = ebitmap_xor(&tmp, e1, e2);
243*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
244*2d543d20SAndroid Build Coastguard Worker 		return -1;
245*2d543d20SAndroid Build Coastguard Worker 	distance = ebitmap_cardinality(&tmp);
246*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&tmp);
247*2d543d20SAndroid Build Coastguard Worker 	return distance;
248*2d543d20SAndroid Build Coastguard Worker }
249*2d543d20SAndroid Build Coastguard Worker 
ebitmap_cmp(const ebitmap_t * e1,const ebitmap_t * e2)250*2d543d20SAndroid Build Coastguard Worker int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2)
251*2d543d20SAndroid Build Coastguard Worker {
252*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n1, *n2;
253*2d543d20SAndroid Build Coastguard Worker 
254*2d543d20SAndroid Build Coastguard Worker 	if (e1->highbit != e2->highbit)
255*2d543d20SAndroid Build Coastguard Worker 		return 0;
256*2d543d20SAndroid Build Coastguard Worker 
257*2d543d20SAndroid Build Coastguard Worker 	n1 = e1->node;
258*2d543d20SAndroid Build Coastguard Worker 	n2 = e2->node;
259*2d543d20SAndroid Build Coastguard Worker 	while (n1 && n2 &&
260*2d543d20SAndroid Build Coastguard Worker 	       (n1->startbit == n2->startbit) && (n1->map == n2->map)) {
261*2d543d20SAndroid Build Coastguard Worker 		n1 = n1->next;
262*2d543d20SAndroid Build Coastguard Worker 		n2 = n2->next;
263*2d543d20SAndroid Build Coastguard Worker 	}
264*2d543d20SAndroid Build Coastguard Worker 
265*2d543d20SAndroid Build Coastguard Worker 	if (n1 || n2)
266*2d543d20SAndroid Build Coastguard Worker 		return 0;
267*2d543d20SAndroid Build Coastguard Worker 
268*2d543d20SAndroid Build Coastguard Worker 	return 1;
269*2d543d20SAndroid Build Coastguard Worker }
270*2d543d20SAndroid Build Coastguard Worker 
ebitmap_cpy(ebitmap_t * dst,const ebitmap_t * src)271*2d543d20SAndroid Build Coastguard Worker int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src)
272*2d543d20SAndroid Build Coastguard Worker {
273*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n;
274*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *new = NULL, **prev;
275*2d543d20SAndroid Build Coastguard Worker 
276*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(dst);
277*2d543d20SAndroid Build Coastguard Worker 	n = src->node;
278*2d543d20SAndroid Build Coastguard Worker 	prev = &dst->node;
279*2d543d20SAndroid Build Coastguard Worker 	while (n) {
280*2d543d20SAndroid Build Coastguard Worker 		new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
281*2d543d20SAndroid Build Coastguard Worker 		if (!new) {
282*2d543d20SAndroid Build Coastguard Worker 			ebitmap_destroy(dst);
283*2d543d20SAndroid Build Coastguard Worker 			return -ENOMEM;
284*2d543d20SAndroid Build Coastguard Worker 		}
285*2d543d20SAndroid Build Coastguard Worker 		new->startbit = n->startbit;
286*2d543d20SAndroid Build Coastguard Worker 		new->map = n->map;
287*2d543d20SAndroid Build Coastguard Worker 		new->next = NULL;
288*2d543d20SAndroid Build Coastguard Worker 
289*2d543d20SAndroid Build Coastguard Worker 		*prev = new;
290*2d543d20SAndroid Build Coastguard Worker 		prev = &new->next;
291*2d543d20SAndroid Build Coastguard Worker 
292*2d543d20SAndroid Build Coastguard Worker 		n = n->next;
293*2d543d20SAndroid Build Coastguard Worker 	}
294*2d543d20SAndroid Build Coastguard Worker 
295*2d543d20SAndroid Build Coastguard Worker 	dst->highbit = src->highbit;
296*2d543d20SAndroid Build Coastguard Worker 	return 0;
297*2d543d20SAndroid Build Coastguard Worker }
298*2d543d20SAndroid Build Coastguard Worker 
ebitmap_contains(const ebitmap_t * e1,const ebitmap_t * e2)299*2d543d20SAndroid Build Coastguard Worker int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2)
300*2d543d20SAndroid Build Coastguard Worker {
301*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n1, *n2;
302*2d543d20SAndroid Build Coastguard Worker 
303*2d543d20SAndroid Build Coastguard Worker 	if (e1->highbit < e2->highbit)
304*2d543d20SAndroid Build Coastguard Worker 		return 0;
305*2d543d20SAndroid Build Coastguard Worker 
306*2d543d20SAndroid Build Coastguard Worker 	n1 = e1->node;
307*2d543d20SAndroid Build Coastguard Worker 	n2 = e2->node;
308*2d543d20SAndroid Build Coastguard Worker 	while (n1 && n2 && (n1->startbit <= n2->startbit)) {
309*2d543d20SAndroid Build Coastguard Worker 		if (n1->startbit < n2->startbit) {
310*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
311*2d543d20SAndroid Build Coastguard Worker 			continue;
312*2d543d20SAndroid Build Coastguard Worker 		}
313*2d543d20SAndroid Build Coastguard Worker 		if ((n1->map & n2->map) != n2->map)
314*2d543d20SAndroid Build Coastguard Worker 			return 0;
315*2d543d20SAndroid Build Coastguard Worker 
316*2d543d20SAndroid Build Coastguard Worker 		n1 = n1->next;
317*2d543d20SAndroid Build Coastguard Worker 		n2 = n2->next;
318*2d543d20SAndroid Build Coastguard Worker 	}
319*2d543d20SAndroid Build Coastguard Worker 
320*2d543d20SAndroid Build Coastguard Worker 	if (n2)
321*2d543d20SAndroid Build Coastguard Worker 		return 0;
322*2d543d20SAndroid Build Coastguard Worker 
323*2d543d20SAndroid Build Coastguard Worker 	return 1;
324*2d543d20SAndroid Build Coastguard Worker }
325*2d543d20SAndroid Build Coastguard Worker 
ebitmap_match_any(const ebitmap_t * e1,const ebitmap_t * e2)326*2d543d20SAndroid Build Coastguard Worker int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2)
327*2d543d20SAndroid Build Coastguard Worker {
328*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n1 = e1->node;
329*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n2 = e2->node;
330*2d543d20SAndroid Build Coastguard Worker 
331*2d543d20SAndroid Build Coastguard Worker 	while (n1 && n2) {
332*2d543d20SAndroid Build Coastguard Worker 		if (n1->startbit < n2->startbit) {
333*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
334*2d543d20SAndroid Build Coastguard Worker 		} else if (n2->startbit < n1->startbit) {
335*2d543d20SAndroid Build Coastguard Worker 			n2 = n2->next;
336*2d543d20SAndroid Build Coastguard Worker 		} else {
337*2d543d20SAndroid Build Coastguard Worker 			if (n1->map & n2->map) {
338*2d543d20SAndroid Build Coastguard Worker 				return 1;
339*2d543d20SAndroid Build Coastguard Worker 			}
340*2d543d20SAndroid Build Coastguard Worker 			n1 = n1->next;
341*2d543d20SAndroid Build Coastguard Worker 			n2 = n2->next;
342*2d543d20SAndroid Build Coastguard Worker 		}
343*2d543d20SAndroid Build Coastguard Worker 	}
344*2d543d20SAndroid Build Coastguard Worker 
345*2d543d20SAndroid Build Coastguard Worker 	return 0;
346*2d543d20SAndroid Build Coastguard Worker }
347*2d543d20SAndroid Build Coastguard Worker 
ebitmap_get_bit(const ebitmap_t * e,unsigned int bit)348*2d543d20SAndroid Build Coastguard Worker int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit)
349*2d543d20SAndroid Build Coastguard Worker {
350*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n;
351*2d543d20SAndroid Build Coastguard Worker 
352*2d543d20SAndroid Build Coastguard Worker 	if (e->highbit < bit)
353*2d543d20SAndroid Build Coastguard Worker 		return 0;
354*2d543d20SAndroid Build Coastguard Worker 
355*2d543d20SAndroid Build Coastguard Worker 	n = e->node;
356*2d543d20SAndroid Build Coastguard Worker 	while (n && (n->startbit <= bit)) {
357*2d543d20SAndroid Build Coastguard Worker 		if ((n->startbit + MAPSIZE) > bit) {
358*2d543d20SAndroid Build Coastguard Worker 			if (n->map & (MAPBIT << (bit - n->startbit)))
359*2d543d20SAndroid Build Coastguard Worker 				return 1;
360*2d543d20SAndroid Build Coastguard Worker 			else
361*2d543d20SAndroid Build Coastguard Worker 				return 0;
362*2d543d20SAndroid Build Coastguard Worker 		}
363*2d543d20SAndroid Build Coastguard Worker 		n = n->next;
364*2d543d20SAndroid Build Coastguard Worker 	}
365*2d543d20SAndroid Build Coastguard Worker 
366*2d543d20SAndroid Build Coastguard Worker 	return 0;
367*2d543d20SAndroid Build Coastguard Worker }
368*2d543d20SAndroid Build Coastguard Worker 
ebitmap_set_bit(ebitmap_t * e,unsigned int bit,int value)369*2d543d20SAndroid Build Coastguard Worker int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value)
370*2d543d20SAndroid Build Coastguard Worker {
371*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *n, *prev, *new;
372*2d543d20SAndroid Build Coastguard Worker 	uint32_t startbit = bit & ~(MAPSIZE - 1);
373*2d543d20SAndroid Build Coastguard Worker 	uint32_t highbit = startbit + MAPSIZE;
374*2d543d20SAndroid Build Coastguard Worker 
375*2d543d20SAndroid Build Coastguard Worker 	if (highbit == 0) {
376*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "bitmap overflow, bit 0x%x", bit);
377*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
378*2d543d20SAndroid Build Coastguard Worker 	}
379*2d543d20SAndroid Build Coastguard Worker 
380*2d543d20SAndroid Build Coastguard Worker 	prev = 0;
381*2d543d20SAndroid Build Coastguard Worker 	n = e->node;
382*2d543d20SAndroid Build Coastguard Worker 	while (n && n->startbit <= bit) {
383*2d543d20SAndroid Build Coastguard Worker 		if ((n->startbit + MAPSIZE) > bit) {
384*2d543d20SAndroid Build Coastguard Worker 			if (value) {
385*2d543d20SAndroid Build Coastguard Worker 				n->map |= (MAPBIT << (bit - n->startbit));
386*2d543d20SAndroid Build Coastguard Worker 			} else {
387*2d543d20SAndroid Build Coastguard Worker 				n->map &= ~(MAPBIT << (bit - n->startbit));
388*2d543d20SAndroid Build Coastguard Worker 				if (!n->map) {
389*2d543d20SAndroid Build Coastguard Worker 					/* drop this node from the bitmap */
390*2d543d20SAndroid Build Coastguard Worker 
391*2d543d20SAndroid Build Coastguard Worker 					if (!n->next) {
392*2d543d20SAndroid Build Coastguard Worker 						/*
393*2d543d20SAndroid Build Coastguard Worker 						 * this was the highest map
394*2d543d20SAndroid Build Coastguard Worker 						 * within the bitmap
395*2d543d20SAndroid Build Coastguard Worker 						 */
396*2d543d20SAndroid Build Coastguard Worker 						if (prev)
397*2d543d20SAndroid Build Coastguard Worker 							e->highbit =
398*2d543d20SAndroid Build Coastguard Worker 							    prev->startbit +
399*2d543d20SAndroid Build Coastguard Worker 							    MAPSIZE;
400*2d543d20SAndroid Build Coastguard Worker 						else
401*2d543d20SAndroid Build Coastguard Worker 							e->highbit = 0;
402*2d543d20SAndroid Build Coastguard Worker 					}
403*2d543d20SAndroid Build Coastguard Worker 					if (prev)
404*2d543d20SAndroid Build Coastguard Worker 						prev->next = n->next;
405*2d543d20SAndroid Build Coastguard Worker 					else
406*2d543d20SAndroid Build Coastguard Worker 						e->node = n->next;
407*2d543d20SAndroid Build Coastguard Worker 
408*2d543d20SAndroid Build Coastguard Worker 					free(n);
409*2d543d20SAndroid Build Coastguard Worker 				}
410*2d543d20SAndroid Build Coastguard Worker 			}
411*2d543d20SAndroid Build Coastguard Worker 			return 0;
412*2d543d20SAndroid Build Coastguard Worker 		}
413*2d543d20SAndroid Build Coastguard Worker 		prev = n;
414*2d543d20SAndroid Build Coastguard Worker 		n = n->next;
415*2d543d20SAndroid Build Coastguard Worker 	}
416*2d543d20SAndroid Build Coastguard Worker 
417*2d543d20SAndroid Build Coastguard Worker 	if (!value)
418*2d543d20SAndroid Build Coastguard Worker 		return 0;
419*2d543d20SAndroid Build Coastguard Worker 
420*2d543d20SAndroid Build Coastguard Worker 	new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
421*2d543d20SAndroid Build Coastguard Worker 	if (!new)
422*2d543d20SAndroid Build Coastguard Worker 		return -ENOMEM;
423*2d543d20SAndroid Build Coastguard Worker 
424*2d543d20SAndroid Build Coastguard Worker 	new->startbit = startbit;
425*2d543d20SAndroid Build Coastguard Worker 	new->map = (MAPBIT << (bit - new->startbit));
426*2d543d20SAndroid Build Coastguard Worker 
427*2d543d20SAndroid Build Coastguard Worker 	if (!n) {
428*2d543d20SAndroid Build Coastguard Worker 		/* this node will be the highest map within the bitmap */
429*2d543d20SAndroid Build Coastguard Worker 		e->highbit = highbit;
430*2d543d20SAndroid Build Coastguard Worker 	}
431*2d543d20SAndroid Build Coastguard Worker 
432*2d543d20SAndroid Build Coastguard Worker 	if (prev) {
433*2d543d20SAndroid Build Coastguard Worker 		new->next = prev->next;
434*2d543d20SAndroid Build Coastguard Worker 		prev->next = new;
435*2d543d20SAndroid Build Coastguard Worker 	} else {
436*2d543d20SAndroid Build Coastguard Worker 		new->next = e->node;
437*2d543d20SAndroid Build Coastguard Worker 		e->node = new;
438*2d543d20SAndroid Build Coastguard Worker 	}
439*2d543d20SAndroid Build Coastguard Worker 
440*2d543d20SAndroid Build Coastguard Worker 	return 0;
441*2d543d20SAndroid Build Coastguard Worker }
442*2d543d20SAndroid Build Coastguard Worker 
ebitmap_init_range(ebitmap_t * e,unsigned int minbit,unsigned int maxbit)443*2d543d20SAndroid Build Coastguard Worker int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit)
444*2d543d20SAndroid Build Coastguard Worker {
445*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *new = NULL, **prev;
446*2d543d20SAndroid Build Coastguard Worker 	uint32_t minstartbit = minbit & ~(MAPSIZE - 1);
447*2d543d20SAndroid Build Coastguard Worker 	uint32_t maxstartbit = maxbit & ~(MAPSIZE - 1);
448*2d543d20SAndroid Build Coastguard Worker 	uint32_t minhighbit = minstartbit + MAPSIZE;
449*2d543d20SAndroid Build Coastguard Worker 	uint32_t maxhighbit = maxstartbit + MAPSIZE;
450*2d543d20SAndroid Build Coastguard Worker 	uint32_t startbit;
451*2d543d20SAndroid Build Coastguard Worker 	MAPTYPE mask;
452*2d543d20SAndroid Build Coastguard Worker 
453*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(e);
454*2d543d20SAndroid Build Coastguard Worker 
455*2d543d20SAndroid Build Coastguard Worker 	if (minbit > maxbit)
456*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
457*2d543d20SAndroid Build Coastguard Worker 
458*2d543d20SAndroid Build Coastguard Worker 	if (minhighbit == 0 || maxhighbit == 0)
459*2d543d20SAndroid Build Coastguard Worker 		return -EOVERFLOW;
460*2d543d20SAndroid Build Coastguard Worker 
461*2d543d20SAndroid Build Coastguard Worker 	prev = &e->node;
462*2d543d20SAndroid Build Coastguard Worker 
463*2d543d20SAndroid Build Coastguard Worker 	for (startbit = minstartbit; startbit <= maxstartbit; startbit += MAPSIZE) {
464*2d543d20SAndroid Build Coastguard Worker 		new = malloc(sizeof(ebitmap_node_t));
465*2d543d20SAndroid Build Coastguard Worker 		if (!new)
466*2d543d20SAndroid Build Coastguard Worker 			return -ENOMEM;
467*2d543d20SAndroid Build Coastguard Worker 
468*2d543d20SAndroid Build Coastguard Worker 		new->next = NULL;
469*2d543d20SAndroid Build Coastguard Worker 		new->startbit = startbit;
470*2d543d20SAndroid Build Coastguard Worker 
471*2d543d20SAndroid Build Coastguard Worker 		if (startbit != minstartbit && startbit != maxstartbit) {
472*2d543d20SAndroid Build Coastguard Worker 			new->map = ~((MAPTYPE)0);
473*2d543d20SAndroid Build Coastguard Worker 		} else if (startbit != maxstartbit) {
474*2d543d20SAndroid Build Coastguard Worker 			new->map = ~((MAPTYPE)0) << (minbit - startbit);
475*2d543d20SAndroid Build Coastguard Worker 		} else if (startbit != minstartbit) {
476*2d543d20SAndroid Build Coastguard Worker 			new->map = ~((MAPTYPE)0) >> (MAPSIZE - (maxbit - startbit + 1));
477*2d543d20SAndroid Build Coastguard Worker 		} else {
478*2d543d20SAndroid Build Coastguard Worker 			mask = ~((MAPTYPE)0) >> (MAPSIZE - (maxbit - minbit + 1));
479*2d543d20SAndroid Build Coastguard Worker 			new->map = (mask << (minbit - startbit));
480*2d543d20SAndroid Build Coastguard Worker 		}
481*2d543d20SAndroid Build Coastguard Worker 
482*2d543d20SAndroid Build Coastguard Worker 		*prev = new;
483*2d543d20SAndroid Build Coastguard Worker 		prev = &new->next;
484*2d543d20SAndroid Build Coastguard Worker 	}
485*2d543d20SAndroid Build Coastguard Worker 
486*2d543d20SAndroid Build Coastguard Worker 	e->highbit = maxhighbit;
487*2d543d20SAndroid Build Coastguard Worker 
488*2d543d20SAndroid Build Coastguard Worker 	return 0;
489*2d543d20SAndroid Build Coastguard Worker }
490*2d543d20SAndroid Build Coastguard Worker 
ebitmap_highest_set_bit(const ebitmap_t * e)491*2d543d20SAndroid Build Coastguard Worker unsigned int ebitmap_highest_set_bit(const ebitmap_t * e)
492*2d543d20SAndroid Build Coastguard Worker {
493*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_node_t *n;
494*2d543d20SAndroid Build Coastguard Worker 	MAPTYPE map;
495*2d543d20SAndroid Build Coastguard Worker 	unsigned int pos = 0;
496*2d543d20SAndroid Build Coastguard Worker 
497*2d543d20SAndroid Build Coastguard Worker 	n = e->node;
498*2d543d20SAndroid Build Coastguard Worker 	if (!n)
499*2d543d20SAndroid Build Coastguard Worker 		return 0;
500*2d543d20SAndroid Build Coastguard Worker 
501*2d543d20SAndroid Build Coastguard Worker 	while (n->next)
502*2d543d20SAndroid Build Coastguard Worker 		n = n->next;
503*2d543d20SAndroid Build Coastguard Worker 
504*2d543d20SAndroid Build Coastguard Worker 	map = n->map;
505*2d543d20SAndroid Build Coastguard Worker 	while (map >>= 1)
506*2d543d20SAndroid Build Coastguard Worker 		pos++;
507*2d543d20SAndroid Build Coastguard Worker 
508*2d543d20SAndroid Build Coastguard Worker 	return n->startbit + pos;
509*2d543d20SAndroid Build Coastguard Worker }
510*2d543d20SAndroid Build Coastguard Worker 
ebitmap_destroy(ebitmap_t * e)511*2d543d20SAndroid Build Coastguard Worker void ebitmap_destroy(ebitmap_t * e)
512*2d543d20SAndroid Build Coastguard Worker {
513*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *n, *temp;
514*2d543d20SAndroid Build Coastguard Worker 
515*2d543d20SAndroid Build Coastguard Worker 	if (!e)
516*2d543d20SAndroid Build Coastguard Worker 		return;
517*2d543d20SAndroid Build Coastguard Worker 
518*2d543d20SAndroid Build Coastguard Worker 	n = e->node;
519*2d543d20SAndroid Build Coastguard Worker 	while (n) {
520*2d543d20SAndroid Build Coastguard Worker 		temp = n;
521*2d543d20SAndroid Build Coastguard Worker 		n = n->next;
522*2d543d20SAndroid Build Coastguard Worker 		free(temp);
523*2d543d20SAndroid Build Coastguard Worker 	}
524*2d543d20SAndroid Build Coastguard Worker 
525*2d543d20SAndroid Build Coastguard Worker 	e->highbit = 0;
526*2d543d20SAndroid Build Coastguard Worker 	e->node = 0;
527*2d543d20SAndroid Build Coastguard Worker 	return;
528*2d543d20SAndroid Build Coastguard Worker }
529*2d543d20SAndroid Build Coastguard Worker 
ebitmap_read(ebitmap_t * e,void * fp)530*2d543d20SAndroid Build Coastguard Worker int ebitmap_read(ebitmap_t * e, void *fp)
531*2d543d20SAndroid Build Coastguard Worker {
532*2d543d20SAndroid Build Coastguard Worker 	int rc;
533*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *n, *l;
534*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[3], mapsize, count, i;
535*2d543d20SAndroid Build Coastguard Worker 	uint64_t map;
536*2d543d20SAndroid Build Coastguard Worker 
537*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(e);
538*2d543d20SAndroid Build Coastguard Worker 
539*2d543d20SAndroid Build Coastguard Worker 	rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
540*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
541*2d543d20SAndroid Build Coastguard Worker 		goto bad;
542*2d543d20SAndroid Build Coastguard Worker 
543*2d543d20SAndroid Build Coastguard Worker 	mapsize = le32_to_cpu(buf[0]);
544*2d543d20SAndroid Build Coastguard Worker 	e->highbit = le32_to_cpu(buf[1]);
545*2d543d20SAndroid Build Coastguard Worker 	count = le32_to_cpu(buf[2]);
546*2d543d20SAndroid Build Coastguard Worker 
547*2d543d20SAndroid Build Coastguard Worker 	if (mapsize != MAPSIZE) {
548*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "security: ebitmap: map size %d does not match my size %zu (high bit was %d)",
549*2d543d20SAndroid Build Coastguard Worker 		     mapsize, MAPSIZE, e->highbit);
550*2d543d20SAndroid Build Coastguard Worker 		goto bad;
551*2d543d20SAndroid Build Coastguard Worker 	}
552*2d543d20SAndroid Build Coastguard Worker 	if (!e->highbit) {
553*2d543d20SAndroid Build Coastguard Worker 		e->node = NULL;
554*2d543d20SAndroid Build Coastguard Worker 		goto ok;
555*2d543d20SAndroid Build Coastguard Worker 	}
556*2d543d20SAndroid Build Coastguard Worker 	if (e->highbit & (MAPSIZE - 1)) {
557*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "security: ebitmap: high bit (%d) is not a multiple of the map size (%zu)",
558*2d543d20SAndroid Build Coastguard Worker 		     e->highbit, MAPSIZE);
559*2d543d20SAndroid Build Coastguard Worker 		goto bad;
560*2d543d20SAndroid Build Coastguard Worker 	}
561*2d543d20SAndroid Build Coastguard Worker 
562*2d543d20SAndroid Build Coastguard Worker 	if (e->highbit && !count)
563*2d543d20SAndroid Build Coastguard Worker 		goto bad;
564*2d543d20SAndroid Build Coastguard Worker 
565*2d543d20SAndroid Build Coastguard Worker 	l = NULL;
566*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
567*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(buf, fp, sizeof(uint32_t));
568*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
569*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL, "security: ebitmap: truncated map");
570*2d543d20SAndroid Build Coastguard Worker 			goto bad;
571*2d543d20SAndroid Build Coastguard Worker 		}
572*2d543d20SAndroid Build Coastguard Worker 		n = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
573*2d543d20SAndroid Build Coastguard Worker 		if (!n) {
574*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL, "security: ebitmap: out of memory");
575*2d543d20SAndroid Build Coastguard Worker 			rc = -ENOMEM;
576*2d543d20SAndroid Build Coastguard Worker 			goto bad;
577*2d543d20SAndroid Build Coastguard Worker 		}
578*2d543d20SAndroid Build Coastguard Worker 		memset(n, 0, sizeof(ebitmap_node_t));
579*2d543d20SAndroid Build Coastguard Worker 
580*2d543d20SAndroid Build Coastguard Worker 		n->startbit = le32_to_cpu(buf[0]);
581*2d543d20SAndroid Build Coastguard Worker 
582*2d543d20SAndroid Build Coastguard Worker 		if (n->startbit & (MAPSIZE - 1)) {
583*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL, "security: ebitmap start bit (%d) is not a multiple of the map size (%zu)",
584*2d543d20SAndroid Build Coastguard Worker 			     n->startbit, MAPSIZE);
585*2d543d20SAndroid Build Coastguard Worker 			goto bad_free;
586*2d543d20SAndroid Build Coastguard Worker 		}
587*2d543d20SAndroid Build Coastguard Worker 		if (n->startbit > (e->highbit - MAPSIZE)) {
588*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL, "security: ebitmap start bit (%d) is beyond the end of the bitmap (%zu)",
589*2d543d20SAndroid Build Coastguard Worker 			     n->startbit, (e->highbit - MAPSIZE));
590*2d543d20SAndroid Build Coastguard Worker 			goto bad_free;
591*2d543d20SAndroid Build Coastguard Worker 		}
592*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(&map, fp, sizeof(uint64_t));
593*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
594*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL, "security: ebitmap: truncated map");
595*2d543d20SAndroid Build Coastguard Worker 			goto bad_free;
596*2d543d20SAndroid Build Coastguard Worker 		}
597*2d543d20SAndroid Build Coastguard Worker 		n->map = le64_to_cpu(map);
598*2d543d20SAndroid Build Coastguard Worker 
599*2d543d20SAndroid Build Coastguard Worker 		if (!n->map) {
600*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL, "security: ebitmap: null map in ebitmap (startbit %d)",
601*2d543d20SAndroid Build Coastguard Worker 			     n->startbit);
602*2d543d20SAndroid Build Coastguard Worker 			goto bad_free;
603*2d543d20SAndroid Build Coastguard Worker 		}
604*2d543d20SAndroid Build Coastguard Worker 		if (l) {
605*2d543d20SAndroid Build Coastguard Worker 			if (n->startbit <= l->startbit) {
606*2d543d20SAndroid Build Coastguard Worker 				ERR(NULL, "security: ebitmap: start bit %d comes after start bit %d",
607*2d543d20SAndroid Build Coastguard Worker 				     n->startbit, l->startbit);
608*2d543d20SAndroid Build Coastguard Worker 				goto bad_free;
609*2d543d20SAndroid Build Coastguard Worker 			}
610*2d543d20SAndroid Build Coastguard Worker 			l->next = n;
611*2d543d20SAndroid Build Coastguard Worker 		} else
612*2d543d20SAndroid Build Coastguard Worker 			e->node = n;
613*2d543d20SAndroid Build Coastguard Worker 
614*2d543d20SAndroid Build Coastguard Worker 		l = n;
615*2d543d20SAndroid Build Coastguard Worker 	}
616*2d543d20SAndroid Build Coastguard Worker 	if (count && l->startbit + MAPSIZE != e->highbit) {
617*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "security: ebitmap: high bit %u has not the expected value %zu",
618*2d543d20SAndroid Build Coastguard Worker 		     e->highbit, l->startbit + MAPSIZE);
619*2d543d20SAndroid Build Coastguard Worker 		goto bad;
620*2d543d20SAndroid Build Coastguard Worker 	}
621*2d543d20SAndroid Build Coastguard Worker 
622*2d543d20SAndroid Build Coastguard Worker       ok:
623*2d543d20SAndroid Build Coastguard Worker 	rc = 0;
624*2d543d20SAndroid Build Coastguard Worker       out:
625*2d543d20SAndroid Build Coastguard Worker 	return rc;
626*2d543d20SAndroid Build Coastguard Worker       bad_free:
627*2d543d20SAndroid Build Coastguard Worker 	free(n);
628*2d543d20SAndroid Build Coastguard Worker       bad:
629*2d543d20SAndroid Build Coastguard Worker 	if (!rc)
630*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
631*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(e);
632*2d543d20SAndroid Build Coastguard Worker 	goto out;
633*2d543d20SAndroid Build Coastguard Worker }
634*2d543d20SAndroid Build Coastguard Worker 
635*2d543d20SAndroid Build Coastguard Worker /* FLASK */
636