]> jfr.im git - solanum.git/blob - ircd/capability.c
Mailmap and copyright update for Ariadne
[solanum.git] / ircd / capability.c
1 /*
2 * Copyright (c) 2012 Ariadne Conill <ariadne@dereferenced.org>.
3 *
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.
7 *
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.
19 */
20
21 #include "stdinc.h"
22 #include "capability.h"
23 #include "rb_dictionary.h"
24 #include "s_assert.h"
25
26 static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
27
28 struct CapabilityEntry *
29 capability_find(struct CapabilityIndex *idx, const char *cap)
30 {
31 s_assert(idx != NULL);
32 if (cap == NULL)
33 return NULL;
34
35 return rb_dictionary_retrieve(idx->cap_dict, cap);
36 }
37
38 unsigned int
39 capability_get(struct CapabilityIndex *idx, const char *cap, void **ownerdata)
40 {
41 struct CapabilityEntry *entry;
42
43 s_assert(idx != NULL);
44 if (cap == NULL)
45 return 0;
46
47 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
48 if (entry != NULL && !(entry->flags & CAP_ORPHANED))
49 {
50 if (ownerdata != NULL)
51 *ownerdata = entry->ownerdata;
52 return (1 << entry->value);
53 }
54
55 return 0;
56 }
57
58 unsigned int
59 capability_put(struct CapabilityIndex *idx, const char *cap, void *ownerdata)
60 {
61 struct CapabilityEntry *entry;
62
63 s_assert(idx != NULL);
64 if (!idx->highest_bit)
65 return 0xFFFFFFFF;
66
67 if ((entry = rb_dictionary_retrieve(idx->cap_dict, cap)) != NULL)
68 {
69 entry->flags &= ~CAP_ORPHANED;
70 if (ownerdata != NULL)
71 {
72 s_assert(entry->ownerdata == NULL);
73 entry->ownerdata = ownerdata;
74 }
75 return (1 << entry->value);
76 }
77
78 entry = rb_malloc(sizeof(struct CapabilityEntry));
79 entry->cap = rb_strdup(cap);
80 entry->flags = 0;
81 entry->value = idx->highest_bit;
82 entry->ownerdata = ownerdata;
83
84 rb_dictionary_add(idx->cap_dict, entry->cap, entry);
85
86 idx->highest_bit++;
87 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
88 idx->highest_bit = 0;
89
90 return (1 << entry->value);
91 }
92
93 unsigned int
94 capability_put_anonymous(struct CapabilityIndex *idx)
95 {
96 unsigned int value;
97
98 s_assert(idx != NULL);
99 if (!idx->highest_bit)
100 return 0xFFFFFFFF;
101 value = 1 << idx->highest_bit;
102 idx->highest_bit++;
103 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
104 idx->highest_bit = 0;
105 return value;
106 }
107
108 void
109 capability_orphan(struct CapabilityIndex *idx, const char *cap)
110 {
111 struct CapabilityEntry *entry;
112
113 s_assert(idx != NULL);
114
115 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
116 if (entry != NULL)
117 {
118 entry->flags &= ~CAP_REQUIRED;
119 entry->flags |= CAP_ORPHANED;
120 entry->ownerdata = NULL;
121 }
122 }
123
124 void
125 capability_require(struct CapabilityIndex *idx, const char *cap)
126 {
127 struct CapabilityEntry *entry;
128
129 s_assert(idx != NULL);
130
131 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
132 if (entry != NULL)
133 entry->flags |= CAP_REQUIRED;
134 }
135
136 static void
137 capability_destroy(rb_dictionary_element *delem, void *privdata)
138 {
139 s_assert(delem != NULL);
140
141 struct CapabilityEntry *entry = delem->data;
142 rb_free((char *)entry->cap);
143 rb_free(entry);
144 }
145
146 struct CapabilityIndex *
147 capability_index_create(const char *name)
148 {
149 struct CapabilityIndex *idx;
150
151 idx = rb_malloc(sizeof(struct CapabilityIndex));
152 idx->name = name;
153 idx->cap_dict = rb_dictionary_create(name, rb_strcasecmp);
154 idx->highest_bit = 1;
155
156 rb_dlinkAdd(idx, &idx->node, &capability_indexes);
157
158 return idx;
159 }
160
161 void
162 capability_index_destroy(struct CapabilityIndex *idx)
163 {
164 s_assert(idx != NULL);
165
166 rb_dlinkDelete(&idx->node, &capability_indexes);
167
168 rb_dictionary_destroy(idx->cap_dict, capability_destroy, NULL);
169 rb_free(idx);
170 }
171
172 const char *
173 capability_index_list(struct CapabilityIndex *idx, unsigned int cap_mask)
174 {
175 rb_dictionary_iter iter;
176 struct CapabilityEntry *entry;
177 static char buf[BUFSIZE];
178 char *t = buf;
179 int tl;
180
181 s_assert(idx != NULL);
182
183 *t = '\0';
184
185 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
186 {
187 if ((1 << entry->value) & cap_mask)
188 {
189 tl = sprintf(t, "%s ", entry->cap);
190 t += tl;
191 }
192 }
193
194 t--;
195 *t = '\0';
196
197 return buf;
198 }
199
200 unsigned int
201 capability_index_mask(struct CapabilityIndex *idx)
202 {
203 rb_dictionary_iter iter;
204 struct CapabilityEntry *entry;
205 unsigned int mask = 0;
206
207 s_assert(idx != NULL);
208
209 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
210 {
211 if (!(entry->flags & CAP_ORPHANED))
212 mask |= (1 << entry->value);
213 }
214
215 return mask;
216 }
217
218 unsigned int
219 capability_index_get_required(struct CapabilityIndex *idx)
220 {
221 rb_dictionary_iter iter;
222 struct CapabilityEntry *entry;
223 unsigned int mask = 0;
224
225 s_assert(idx != NULL);
226
227 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
228 {
229 if (!(entry->flags & CAP_ORPHANED) && (entry->flags & CAP_REQUIRED))
230 mask |= (1 << entry->value);
231 }
232
233 return mask;
234 }
235
236 void
237 capability_index_stats(void (*cb)(const char *line, void *privdata), void *privdata)
238 {
239 rb_dlink_node *node;
240 char buf[BUFSIZE];
241
242 RB_DLINK_FOREACH(node, capability_indexes.head)
243 {
244 struct CapabilityIndex *idx = node->data;
245 rb_dictionary_iter iter;
246 struct CapabilityEntry *entry;
247
248 snprintf(buf, sizeof buf, "'%s': allocated bits - %d", idx->name, (idx->highest_bit - 1));
249 cb(buf, privdata);
250
251 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
252 {
253 snprintf(buf, sizeof buf, "bit %d: '%s'", entry->value, entry->cap);
254 cb(buf, privdata);
255 }
256
257 snprintf(buf, sizeof buf, "'%s': remaining bits - %u", idx->name,
258 (unsigned int)((sizeof(unsigned int) * 8) - (idx->highest_bit - 1)));
259 cb(buf, privdata);
260 }
261
262 snprintf(buf, sizeof buf, "%ld capability indexes", rb_dlink_list_length(&capability_indexes));
263 cb(buf, privdata);
264 }