2 * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
22 #include "capability.h"
23 #include "rb_dictionary.h"
26 static rb_dlink_list capability_indexes
= { NULL
, NULL
, 0 };
28 struct CapabilityEntry
*
29 capability_find(struct CapabilityIndex
*idx
, const char *cap
)
31 s_assert(idx
!= NULL
);
35 return rb_dictionary_retrieve(idx
->cap_dict
, cap
);
39 capability_get(struct CapabilityIndex
*idx
, const char *cap
, void **ownerdata
)
41 struct CapabilityEntry
*entry
;
43 s_assert(idx
!= NULL
);
47 entry
= rb_dictionary_retrieve(idx
->cap_dict
, cap
);
48 if (entry
!= NULL
&& !(entry
->flags
& CAP_ORPHANED
))
50 if (ownerdata
!= NULL
)
51 *ownerdata
= entry
->ownerdata
;
52 return (1 << entry
->value
);
59 capability_put(struct CapabilityIndex
*idx
, const char *cap
, void *ownerdata
)
61 struct CapabilityEntry
*entry
;
63 s_assert(idx
!= NULL
);
64 if (!idx
->highest_bit
)
67 if ((entry
= rb_dictionary_retrieve(idx
->cap_dict
, cap
)) != NULL
)
69 entry
->flags
&= ~CAP_ORPHANED
;
70 if (ownerdata
!= NULL
)
72 s_assert(entry
->ownerdata
== NULL
);
73 entry
->ownerdata
= ownerdata
;
75 return (1 << entry
->value
);
78 entry
= rb_malloc(sizeof(struct CapabilityEntry
));
79 entry
->cap
= rb_strdup(cap
);
81 entry
->value
= idx
->highest_bit
;
82 entry
->ownerdata
= ownerdata
;
84 rb_dictionary_add(idx
->cap_dict
, entry
->cap
, entry
);
87 if (idx
->highest_bit
% (sizeof(unsigned int) * 8) == 0)
90 return (1 << entry
->value
);
94 capability_put_anonymous(struct CapabilityIndex
*idx
)
98 s_assert(idx
!= NULL
);
99 if (!idx
->highest_bit
)
101 value
= 1 << idx
->highest_bit
;
103 if (idx
->highest_bit
% (sizeof(unsigned int) * 8) == 0)
104 idx
->highest_bit
= 0;
109 capability_orphan(struct CapabilityIndex
*idx
, const char *cap
)
111 struct CapabilityEntry
*entry
;
113 s_assert(idx
!= NULL
);
115 entry
= rb_dictionary_retrieve(idx
->cap_dict
, cap
);
118 entry
->flags
&= ~CAP_REQUIRED
;
119 entry
->flags
|= CAP_ORPHANED
;
120 entry
->ownerdata
= NULL
;
125 capability_require(struct CapabilityIndex
*idx
, const char *cap
)
127 struct CapabilityEntry
*entry
;
129 s_assert(idx
!= NULL
);
131 entry
= rb_dictionary_retrieve(idx
->cap_dict
, cap
);
133 entry
->flags
|= CAP_REQUIRED
;
137 capability_destroy(rb_dictionary_element
*delem
, void *privdata
)
139 s_assert(delem
!= NULL
);
141 struct CapabilityEntry
*entry
= delem
->data
;
142 rb_free((char *)entry
->cap
);
146 struct CapabilityIndex
*
147 capability_index_create(const char *name
)
149 struct CapabilityIndex
*idx
;
151 idx
= rb_malloc(sizeof(struct CapabilityIndex
));
153 idx
->cap_dict
= rb_dictionary_create(name
, rb_strcasecmp
);
154 idx
->highest_bit
= 1;
156 rb_dlinkAdd(idx
, &idx
->node
, &capability_indexes
);
162 capability_index_destroy(struct CapabilityIndex
*idx
)
164 s_assert(idx
!= NULL
);
166 rb_dlinkDelete(&idx
->node
, &capability_indexes
);
168 rb_dictionary_destroy(idx
->cap_dict
, capability_destroy
, NULL
);
173 capability_index_list(struct CapabilityIndex
*idx
, unsigned int cap_mask
)
175 rb_dictionary_iter iter
;
176 struct CapabilityEntry
*entry
;
177 static char buf
[BUFSIZE
];
181 s_assert(idx
!= NULL
);
185 RB_DICTIONARY_FOREACH(entry
, &iter
, idx
->cap_dict
)
187 if ((1 << entry
->value
) & cap_mask
)
189 tl
= sprintf(t
, "%s ", entry
->cap
);
201 capability_index_mask(struct CapabilityIndex
*idx
)
203 rb_dictionary_iter iter
;
204 struct CapabilityEntry
*entry
;
205 unsigned int mask
= 0;
207 s_assert(idx
!= NULL
);
209 RB_DICTIONARY_FOREACH(entry
, &iter
, idx
->cap_dict
)
211 if (!(entry
->flags
& CAP_ORPHANED
))
212 mask
|= (1 << entry
->value
);
219 capability_index_get_required(struct CapabilityIndex
*idx
)
221 rb_dictionary_iter iter
;
222 struct CapabilityEntry
*entry
;
223 unsigned int mask
= 0;
225 s_assert(idx
!= NULL
);
227 RB_DICTIONARY_FOREACH(entry
, &iter
, idx
->cap_dict
)
229 if (!(entry
->flags
& CAP_ORPHANED
) && (entry
->flags
& CAP_REQUIRED
))
230 mask
|= (1 << entry
->value
);
237 capability_index_stats(void (*cb
)(const char *line
, void *privdata
), void *privdata
)
242 RB_DLINK_FOREACH(node
, capability_indexes
.head
)
244 struct CapabilityIndex
*idx
= node
->data
;
245 rb_dictionary_iter iter
;
246 struct CapabilityEntry
*entry
;
248 snprintf(buf
, sizeof buf
, "'%s': allocated bits - %d", idx
->name
, (idx
->highest_bit
- 1));
251 RB_DICTIONARY_FOREACH(entry
, &iter
, idx
->cap_dict
)
253 snprintf(buf
, sizeof buf
, "bit %d: '%s'", entry
->value
, entry
->cap
);
257 snprintf(buf
, sizeof buf
, "'%s': remaining bits - %u", idx
->name
,
258 (unsigned int)((sizeof(unsigned int) * 8) - (idx
->highest_bit
- 1)));
262 snprintf(buf
, sizeof buf
, "%ld capability indexes", rb_dlink_list_length(&capability_indexes
));