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