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(&section->kv, ARRAY_TAIL, kv);
                    127:                array_sort(section->kv, settings_kv_sort, NULL);
                    128:                array_insert_create(&section->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(&section->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, &current);
                    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**)&section))
                    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(&sections, 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, &section))
                    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>