]> jfr.im git - solanum.git/blame_incremental - ircd/capability.c
logger: add idebug
[solanum.git] / ircd / capability.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2012 William Pitcock <nenolod@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
26static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
27
28struct CapabilityEntry *
29capability_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
38unsigned int
39capability_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
58unsigned int
59capability_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 return (1 << entry->value);
71 }
72
73 entry = rb_malloc(sizeof(struct CapabilityEntry));
74 entry->cap = cap;
75 entry->flags = 0;
76 entry->value = idx->highest_bit;
77 entry->ownerdata = ownerdata;
78
79 rb_dictionary_add(idx->cap_dict, entry->cap, entry);
80
81 idx->highest_bit++;
82 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
83 idx->highest_bit = 0;
84
85 return (1 << entry->value);
86}
87
88unsigned int
89capability_put_anonymous(struct CapabilityIndex *idx)
90{
91 unsigned int value;
92
93 s_assert(idx != NULL);
94 if (!idx->highest_bit)
95 return 0xFFFFFFFF;
96 value = 1 << idx->highest_bit;
97 idx->highest_bit++;
98 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
99 idx->highest_bit = 0;
100 return value;
101}
102
103void
104capability_orphan(struct CapabilityIndex *idx, const char *cap)
105{
106 struct CapabilityEntry *entry;
107
108 s_assert(idx != NULL);
109
110 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
111 if (entry != NULL)
112 {
113 entry->flags &= ~CAP_REQUIRED;
114 entry->flags |= CAP_ORPHANED;
115 entry->ownerdata = NULL;
116 }
117}
118
119void
120capability_require(struct CapabilityIndex *idx, const char *cap)
121{
122 struct CapabilityEntry *entry;
123
124 s_assert(idx != NULL);
125
126 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
127 if (entry != NULL)
128 entry->flags |= CAP_REQUIRED;
129}
130
131static void
132capability_destroy(rb_dictionary_element *delem, void *privdata)
133{
134 s_assert(delem != NULL);
135
136 rb_free(delem->data);
137}
138
139struct CapabilityIndex *
140capability_index_create(const char *name)
141{
142 struct CapabilityIndex *idx;
143
144 idx = rb_malloc(sizeof(struct CapabilityIndex));
145 idx->name = name;
146 idx->cap_dict = rb_dictionary_create(name, strcasecmp);
147 idx->highest_bit = 1;
148
149 rb_dlinkAdd(idx, &idx->node, &capability_indexes);
150
151 return idx;
152}
153
154void
155capability_index_destroy(struct CapabilityIndex *idx)
156{
157 s_assert(idx != NULL);
158
159 rb_dlinkDelete(&idx->node, &capability_indexes);
160
161 rb_dictionary_destroy(idx->cap_dict, capability_destroy, NULL);
162 rb_free(idx);
163}
164
165const char *
166capability_index_list(struct CapabilityIndex *idx, unsigned int cap_mask)
167{
168 rb_dictionary_iter iter;
169 struct CapabilityEntry *entry;
170 static char buf[BUFSIZE];
171 char *t = buf;
172 int tl;
173
174 s_assert(idx != NULL);
175
176 *t = '\0';
177
178 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
179 {
180 if ((1 << entry->value) & cap_mask)
181 {
182 tl = sprintf(t, "%s ", entry->cap);
183 t += tl;
184 }
185 }
186
187 t--;
188 *t = '\0';
189
190 return buf;
191}
192
193unsigned int
194capability_index_mask(struct CapabilityIndex *idx)
195{
196 rb_dictionary_iter iter;
197 struct CapabilityEntry *entry;
198 unsigned int mask = 0;
199
200 s_assert(idx != NULL);
201
202 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
203 {
204 if (!(entry->flags & CAP_ORPHANED))
205 mask |= (1 << entry->value);
206 }
207
208 return mask;
209}
210
211unsigned int
212capability_index_get_required(struct CapabilityIndex *idx)
213{
214 rb_dictionary_iter iter;
215 struct CapabilityEntry *entry;
216 unsigned int mask = 0;
217
218 s_assert(idx != NULL);
219
220 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
221 {
222 if (!(entry->flags & CAP_ORPHANED) && (entry->flags & CAP_REQUIRED))
223 mask |= (1 << entry->value);
224 }
225
226 return mask;
227}
228
229void
230capability_index_stats(void (*cb)(const char *line, void *privdata), void *privdata)
231{
232 rb_dlink_node *node;
233 char buf[BUFSIZE];
234
235 RB_DLINK_FOREACH(node, capability_indexes.head)
236 {
237 struct CapabilityIndex *idx = node->data;
238 rb_dictionary_iter iter;
239 struct CapabilityEntry *entry;
240
241 snprintf(buf, sizeof buf, "'%s': allocated bits - %d", idx->name, (idx->highest_bit - 1));
242 cb(buf, privdata);
243
244 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
245 {
246 snprintf(buf, sizeof buf, "bit %d: '%s'", entry->value, entry->cap);
247 cb(buf, privdata);
248 }
249
250 snprintf(buf, sizeof buf, "'%s': remaining bits - %u", idx->name,
251 (unsigned int)((sizeof(unsigned int) * 8) - (idx->highest_bit - 1)));
252 cb(buf, privdata);
253 }
254
255 snprintf(buf, sizeof buf, "%ld capability indexes", rb_dlink_list_length(&capability_indexes));
256 cb(buf, privdata);
257}