Annotation of embedaddon/strongswan/src/libstrongswan/settings/settings_types.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2010-2018 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "settings_types.h"
17:
18: /*
19: * Described in header
20: */
21: kv_t *settings_kv_create(char *key, char *value)
22: {
23: kv_t *this;
24:
25: INIT(this,
26: .key = key,
27: .value = value,
28: );
29: return this;
30: }
31:
32: /*
33: * Described in header
34: */
35: void settings_kv_destroy(kv_t *this, array_t *contents)
36: {
37: free(this->key);
38: if (contents && this->value)
39: {
40: array_insert(contents, ARRAY_TAIL, this->value);
41: }
42: else
43: {
44: free(this->value);
45: }
46: free(this);
47: }
48:
49: /*
50: * Described in header
51: */
52: section_t *settings_section_create(char *name)
53: {
54: section_t *this;
55:
56: INIT(this,
57: .name = name,
58: );
59: return this;
60: }
61:
62: static void section_destroy(section_t *section, int idx, array_t *contents)
63: {
64: settings_section_destroy(section, contents);
65: }
66:
67: static void kv_destroy(kv_t *kv, int idx, array_t *contents)
68: {
69: settings_kv_destroy(kv, contents);
70: }
71:
72: static void ref_destroy(section_ref_t *ref, int idx, void *ctx)
73: {
74: free(ref->name);
75: free(ref);
76: }
77:
78: /*
79: * Described in header
80: */
81: void settings_section_destroy(section_t *this, array_t *contents)
82: {
83: array_destroy_function(this->sections, (void*)section_destroy, contents);
84: array_destroy(this->sections_order);
85: array_destroy_function(this->kv, (void*)kv_destroy, contents);
86: array_destroy(this->kv_order);
87: array_destroy_function(this->references, (void*)ref_destroy, NULL);
88: free(this->name);
89: free(this);
90: }
91:
92: /*
93: * Described in header
94: */
95: void settings_kv_set(kv_t *kv, char *value, array_t *contents)
96: {
97: if (value && kv->value && streq(value, kv->value))
98: { /* no update required */
99: free(value);
100: return;
101: }
102:
103: /* if the new value was shorter we could overwrite the existing one but that
104: * could lead to reads of partially updated values from other threads that
105: * have a pointer to the existing value, so we replace it anyway */
106: if (kv->value && contents)
107: {
108: array_insert(contents, ARRAY_TAIL, kv->value);
109: }
110: else
111: {
112: free(kv->value);
113: }
114: kv->value = value;
115: }
116:
117: /*
118: * Described in header
119: */
120: void settings_kv_add(section_t *section, kv_t *kv, array_t *contents)
121: {
122: kv_t *found;
123:
124: if (array_bsearch(section->kv, kv->key, settings_kv_find, &found) == -1)
125: {
126: array_insert_create(§ion->kv, ARRAY_TAIL, kv);
127: array_sort(section->kv, settings_kv_sort, NULL);
128: array_insert_create(§ion->kv_order, ARRAY_TAIL, kv);
129: }
130: else
131: {
132: settings_kv_set(found, kv->value, contents);
133: kv->value = NULL;
134: settings_kv_destroy(kv, NULL);
135: }
136: }
137:
138: /*
139: * Described in header
140: */
141: void settings_reference_add(section_t *section, char *name, bool permanent)
142: {
143: section_ref_t *ref;
144: int i;
145:
146: for (i = 0; i < array_count(section->references); i++)
147: {
148: array_get(section->references, i, &ref);
149: if (ref->permanent && !permanent)
150: { /* add it before any permanent references */
151: break;
152: }
153: if (ref->permanent == permanent && streq(name, ref->name))
154: {
155: free(name);
156: return;
157: }
158: }
159:
160: INIT(ref,
161: .name = name,
162: .permanent = permanent,
163: );
164: array_insert_create(§ion->references, i, ref);
165: }
166:
167: /*
168: * Add a section to the given parent, optionally remove settings/subsections
169: * not found when extending an existing section
170: */
171: static void add_section(section_t *parent, section_t *section,
172: array_t *contents, bool purge)
173: {
174: section_t *found;
175:
176: if (array_bsearch(parent->sections, section->name, settings_section_find,
177: &found) == -1)
178: {
179: array_insert_create(&parent->sections, ARRAY_TAIL, section);
180: array_sort(parent->sections, settings_section_sort, NULL);
181: array_insert_create(&parent->sections_order, ARRAY_TAIL, section);
182: }
183: else
184: {
185: settings_section_extend(found, section, contents, purge);
186: settings_section_destroy(section, contents);
187: }
188: }
189:
190: /*
191: * Described in header
192: */
193: void settings_section_add(section_t *parent, section_t *section,
194: array_t *contents)
195: {
196: add_section(parent, section, contents, FALSE);
197: }
198:
199: /**
200: * Purge contents of a section, returns TRUE if section can be safely removed.
201: */
202: static bool section_purge(section_t *this, array_t *contents)
203: {
204: section_t *current;
205: section_ref_t *ref;
206: int i, idx;
207:
208: array_destroy_function(this->kv, (void*)kv_destroy, contents);
209: this->kv = NULL;
210: array_destroy(this->kv_order);
211: this->kv_order = NULL;
212: /* remove non-permanent references */
213: for (i = array_count(this->references) - 1; i >= 0; i--)
214: {
215: array_get(this->references, i, &ref);
216: if (!ref->permanent)
217: {
218: array_remove(this->references, i, NULL);
219: ref_destroy(ref, 0, NULL);
220: }
221: }
222: if (!array_count(this->references))
223: {
224: array_destroy(this->references);
225: this->references = NULL;
226: }
227: for (i = array_count(this->sections_order) - 1; i >= 0; i--)
228: {
229: array_get(this->sections_order, i, ¤t);
230: if (section_purge(current, contents))
231: {
232: array_remove(this->sections_order, i, NULL);
233: idx = array_bsearch(this->sections, current->name,
234: settings_section_find, NULL);
235: array_remove(this->sections, idx, NULL);
236: settings_section_destroy(current, contents);
237: }
238: }
239: /* we ensure sections configured with permanent references (or having any
240: * such subsections) are not removed */
241: return !this->references && !array_count(this->sections);
242: }
243:
244: /*
245: * Described in header
246: */
247: void settings_section_extend(section_t *base, section_t *extension,
248: array_t *contents, bool purge)
249: {
250: enumerator_t *enumerator;
251: section_t *section;
252: section_ref_t *ref;
253: kv_t *kv;
254: array_t *sections = NULL, *kvs = NULL;
255: int idx;
256:
257: if (purge)
258: { /* remove sections, settings in base not found in extension, the others
259: * are removed too (from the _order list) so they can be inserted in the
260: * order found in extension, non-permanent references are removed */
261: enumerator = array_create_enumerator(base->sections_order);
262: while (enumerator->enumerate(enumerator, (void**)§ion))
263: {
264: if (array_bsearch(extension->sections, section->name,
265: settings_section_find, NULL) == -1)
266: {
267: idx = array_bsearch(base->sections, section->name,
268: settings_section_find, NULL);
269: if (section_purge(section, contents))
270: { /* only remove them if we can purge them */
271: array_remove(base->sections, idx, NULL);
272: array_remove_at(base->sections_order, enumerator);
273: settings_section_destroy(section, contents);
274: }
275: }
276: else
277: {
278: array_remove_at(base->sections_order, enumerator);
279: array_insert_create(§ions, ARRAY_TAIL, section);
280: array_sort(sections, settings_section_sort, NULL);
281: }
282: }
283: enumerator->destroy(enumerator);
284:
285: while (array_remove(base->kv_order, 0, &kv))
286: {
287: if (array_bsearch(extension->kv, kv->key, settings_kv_find,
288: NULL) == -1)
289: {
290: idx = array_bsearch(base->kv, kv->key, settings_kv_find, NULL);
291: array_remove(base->kv, idx, NULL);
292: settings_kv_destroy(kv, contents);
293: }
294: else
295: {
296: array_insert_create(&kvs, ARRAY_TAIL, kv);
297: array_sort(kvs, settings_kv_sort, NULL);
298: }
299: }
300:
301: enumerator = array_create_enumerator(base->references);
302: while (enumerator->enumerate(enumerator, (void**)&ref))
303: {
304: if (ref->permanent)
305: { /* permanent references are ignored */
306: continue;
307: }
308: array_remove_at(base->references, enumerator);
309: ref_destroy(ref, 0, NULL);
310: }
311: enumerator->destroy(enumerator);
312: }
313:
314: while (array_remove(extension->sections_order, 0, §ion))
315: {
316: idx = array_bsearch(sections, section->name,
317: settings_section_find, NULL);
318: if (idx != -1)
319: {
320: section_t *existing;
321:
322: array_remove(sections, idx, &existing);
323: array_insert(base->sections_order, ARRAY_TAIL, existing);
324: }
325: idx = array_bsearch(extension->sections, section->name,
326: settings_section_find, NULL);
327: array_remove(extension->sections, idx, NULL);
328: add_section(base, section, contents, purge);
329: }
330:
331: while (array_remove(extension->kv_order, 0, &kv))
332: {
333: idx = array_bsearch(kvs, kv->key, settings_kv_find, NULL);
334: if (idx != -1)
335: {
336: kv_t *existing;
337:
338: array_remove(kvs, idx, &existing);
339: array_insert(base->kv_order, ARRAY_TAIL, existing);
340: }
341: idx = array_bsearch(extension->kv, kv->key, settings_kv_find, NULL);
342: array_remove(extension->kv, idx, NULL);
343: settings_kv_add(base, kv, contents);
344: }
345:
346: while (array_remove(extension->references, 0, &ref))
347: {
348: if (ref->permanent)
349: { /* ignore permanent references in the extension */
350: continue;
351: }
352: settings_reference_add(base, strdup(ref->name), FALSE);
353: ref_destroy(ref, 0, NULL);
354: }
355: array_destroy(sections);
356: array_destroy(kvs);
357: }
358:
359: /*
360: * Described in header
361: */
362: int settings_section_find(const void *a, const void *b)
363: {
364: const char *key = a;
365: const section_t *item = b;
366: return strcmp(key, item->name);
367: }
368:
369: /*
370: * Described in header
371: */
372: int settings_section_sort(const void *a, const void *b, void *user)
373: {
374: const section_t *sa = a, *sb = b;
375: return strcmp(sa->name, sb->name);
376: }
377:
378: /*
379: * Described in header
380: */
381: int settings_kv_find(const void *a, const void *b)
382: {
383: const char *key = a;
384: const kv_t *item = b;
385: return strcmp(key, item->key);
386: }
387:
388: /*
389: * Described in header
390: */
391: int settings_kv_sort(const void *a, const void *b, void *user)
392: {
393: const kv_t *kva = a, *kvb = b;
394: return strcmp(kva->key, kvb->key);
395: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>