Annotation of embedaddon/strongswan/src/libstrongswan/settings/settings_types.c, revision 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>