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(&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>