diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
commit | b34738ed08c2227300d554b139e2495ca5da97d6 (patch) | |
tree | 62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libstrongswan/utils | |
parent | 0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff) | |
download | vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip |
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libstrongswan/utils')
-rw-r--r-- | src/libstrongswan/utils/backtrace.c | 87 | ||||
-rw-r--r-- | src/libstrongswan/utils/backtrace.h | 14 | ||||
-rw-r--r-- | src/libstrongswan/utils/enumerator.h | 4 | ||||
-rw-r--r-- | src/libstrongswan/utils/hashtable.c | 225 | ||||
-rw-r--r-- | src/libstrongswan/utils/host.c | 98 | ||||
-rw-r--r-- | src/libstrongswan/utils/identification.c | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/identification.h | 6 | ||||
-rw-r--r-- | src/libstrongswan/utils/iterator.h | 114 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 224 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.h | 7 | ||||
-rw-r--r-- | src/libstrongswan/utils/linked_list.c | 547 | ||||
-rw-r--r-- | src/libstrongswan/utils/linked_list.h | 60 | ||||
-rw-r--r-- | src/libstrongswan/utils/optionsfrom.c | 10 |
13 files changed, 635 insertions, 763 deletions
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c index 5744439f8..cb83d9830 100644 --- a/src/libstrongswan/utils/backtrace.c +++ b/src/libstrongswan/utils/backtrace.c @@ -50,10 +50,8 @@ struct private_backtrace_t { void *frames[]; }; -/** - * Implementation of backtrace_t.log - */ -static void log_(private_backtrace_t *this, FILE *file, bool detailed) +METHOD(backtrace_t, log_, void, + private_backtrace_t *this, FILE *file, bool detailed) { #ifdef HAVE_BACKTRACE size_t i; @@ -129,11 +127,8 @@ static void log_(private_backtrace_t *this, FILE *file, bool detailed) #endif /* HAVE_BACKTRACE */ } -/** - * Implementation of backtrace_t.contains_function - */ -static bool contains_function(private_backtrace_t *this, - char *function[], int count) +METHOD(backtrace_t, contains_function, bool, + private_backtrace_t *this, char *function[], int count) { #ifdef HAVE_DLADDR int i, j; @@ -157,10 +152,70 @@ static bool contains_function(private_backtrace_t *this, return FALSE; } +METHOD(backtrace_t, equals, bool, + private_backtrace_t *this, backtrace_t *other_public) +{ + private_backtrace_t *other = (private_backtrace_t*)other_public; + int i; + + if (this == other) + { + return TRUE; + } + if (this->frame_count != other->frame_count) + { + return FALSE; + } + for (i = 0; i < this->frame_count; i++) + { + if (this->frames[i] != other->frames[i]) + { + return FALSE; + } + } + return TRUE; +} + /** - * Implementation of backtrace_t.destroy. + * Frame enumerator */ -static void destroy(private_backtrace_t *this) +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** reference to backtrace */ + private_backtrace_t *bt; + /** current position */ + int i; +} frame_enumerator_t; + +METHOD(enumerator_t, frame_enumerate, bool, + frame_enumerator_t *this, void **addr) +{ + if (this->i < this->bt->frame_count) + { + *addr = this->bt->frames[this->i++]; + return TRUE; + } + return FALSE; +} + +METHOD(backtrace_t, create_frame_enumerator, enumerator_t*, + private_backtrace_t *this) +{ + frame_enumerator_t *enumerator; + + INIT(enumerator, + .public = { + .enumerate = (void*)_frame_enumerate, + .destroy = (void*)free, + }, + .bt = this, + ); + return &enumerator->public; +} + +METHOD(backtrace_t, destroy, void, + private_backtrace_t *this) { free(this); } @@ -182,9 +237,13 @@ backtrace_t *backtrace_create(int skip) memcpy(this->frames, frames + skip, frame_count * sizeof(void*)); this->frame_count = frame_count; - this->public.log = (void(*)(backtrace_t*,FILE*,bool))log_; - this->public.contains_function = (bool(*)(backtrace_t*, char *function[], int count))contains_function; - this->public.destroy = (void(*)(backtrace_t*))destroy; + this->public = (backtrace_t) { + .log = _log_, + .contains_function = _contains_function, + .equals = _equals, + .create_frame_enumerator = _create_frame_enumerator, + .destroy = _destroy, + }; return &this->public; } diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h index e8ccfc1bd..9d59d2503 100644 --- a/src/libstrongswan/utils/backtrace.h +++ b/src/libstrongswan/utils/backtrace.h @@ -50,6 +50,20 @@ struct backtrace_t { bool (*contains_function)(backtrace_t *this, char *function[], int count); /** + * Check two backtraces for equality. + * + * @param other backtrace to compare to this + * @return TRUE if backtraces are equal + */ + bool (*equals)(backtrace_t *this, backtrace_t *other); + /** + * Create an enumerator over the stack frame addresses. + * + * @return enumerator_t over void* + */ + enumerator_t* (*create_frame_enumerator)(backtrace_t *this); + + /** * Destroy a backtrace instance. */ void (*destroy)(backtrace_t *this); diff --git a/src/libstrongswan/utils/enumerator.h b/src/libstrongswan/utils/enumerator.h index 537bf69e1..12b5712ae 100644 --- a/src/libstrongswan/utils/enumerator.h +++ b/src/libstrongswan/utils/enumerator.h @@ -26,7 +26,7 @@ typedef struct enumerator_t enumerator_t; #include "../utils.h" /** - * Enumerate is simpler, but more flexible than iterator. + * Enumerator interface, allows enumeration over collections. */ struct enumerator_t { @@ -36,7 +36,7 @@ struct enumerator_t { * The enumerate function takes a variable argument list containing * pointers where the enumerated values get written. * - * @param ... variable list of enumerated items, implementation dependant + * @param ... variable list of enumerated items, implementation dependent * @return TRUE if pointers returned */ bool (*enumerate)(enumerator_t *this, ...); diff --git a/src/libstrongswan/utils/hashtable.c b/src/libstrongswan/utils/hashtable.c index 49b0bb68c..33f645170 100644 --- a/src/libstrongswan/utils/hashtable.c +++ b/src/libstrongswan/utils/hashtable.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2010 Tobias Brunner + * Copyright (C) 2008-2011 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -13,7 +13,6 @@ * for more details. */ -#include <utils/linked_list.h> #include "hashtable.h" @@ -40,12 +39,17 @@ struct pair_t { * Cached hash (used in case of a resize). */ u_int hash; + + /** + * Next pair in an overflow list. + */ + pair_t *next; }; /** * Creates an empty pair object. */ -pair_t *pair_create(void *key, void *value, u_int hash) +static inline pair_t *pair_create(void *key, void *value, u_int hash) { pair_t *this; @@ -93,7 +97,7 @@ struct private_hashtable_t { /** * The actual table. */ - linked_list_t **table; + pair_t **table; /** * The hashing function. @@ -129,23 +133,21 @@ struct private_enumerator_t { u_int row; /** + * number of remaining items in hashtable + */ + u_int count; + + /** * current pair */ - pair_t *pair; + pair_t *current; /** - * enumerator for the current row + * previous pair (used by remove_at) */ - enumerator_t *current; -}; + pair_t *prev; -/** - * Compare a pair in a list with the given key. - */ -static inline bool pair_equals(pair_t *pair, private_hashtable_t *this, void *key) -{ - return this->equals(key, pair->key); -} +}; /** * This function returns the next-highest power of two for the given number. @@ -175,7 +177,7 @@ static void init_hashtable(private_hashtable_t *this, u_int capacity) this->mask = this->capacity - 1; this->load_factor = 0.75; - this->table = calloc(this->capacity, sizeof(linked_list_t*)); + this->table = calloc(this->capacity, sizeof(pair_t*)); } /** @@ -183,7 +185,7 @@ static void init_hashtable(private_hashtable_t *this, u_int capacity) */ static void rehash(private_hashtable_t *this) { - linked_list_t **old_table; + pair_t **old_table; u_int row, old_capacity; if (this->capacity >= MAX_CAPACITY) @@ -198,29 +200,17 @@ static void rehash(private_hashtable_t *this) for (row = 0; row < old_capacity; row++) { - enumerator_t *enumerator; - linked_list_t *list, *new_list; - pair_t *pair; + pair_t *pair, *next; u_int new_row; - list = old_table[row]; - if (list) - { - enumerator = list->create_enumerator(list); - while (enumerator->enumerate(enumerator, &pair)) - { - new_row = pair->hash & this->mask; - - list->remove_at(list, enumerator); - new_list = this->table[new_row]; - if (!new_list) - { - new_list = this->table[new_row] = linked_list_create(); - } - new_list->insert_last(new_list, pair); - } - enumerator->destroy(enumerator); - list->destroy(list); + pair = old_table[row]; + while (pair) + { /* insert pair at the front of new bucket*/ + next = pair->next; + new_row = pair->hash & this->mask; + pair->next = this->table[new_row]; + this->table[new_row] = pair; + pair = next; } } free(old_table); @@ -230,38 +220,28 @@ METHOD(hashtable_t, put, void*, private_hashtable_t *this, void *key, void *value) { void *old_value = NULL; - linked_list_t *list; - u_int hash; - u_int row; + pair_t *pair; + u_int hash, row; hash = this->hash(key); row = hash & this->mask; - list = this->table[row]; - if (list) - { - enumerator_t *enumerator; - pair_t *pair; - - enumerator = list->create_enumerator(list); - while (enumerator->enumerate(enumerator, &pair)) + pair = this->table[row]; + while (pair) + { /* search existing bucket for key */ + if (this->equals(key, pair->key)) { - if (pair_equals(pair, this, key)) - { - old_value = pair->value; - pair->value = value; - pair->key = key; - break; - } + old_value = pair->value; + pair->value = value; + pair->key = key; + break; } - enumerator->destroy(enumerator); - } - else - { - list = this->table[row] = linked_list_create(); + pair = pair->next; } - if (!old_value) - { - list->insert_last(list, pair_create(key, value, hash)); + if (!pair) + { /* insert at the front of bucket */ + pair = pair_create(key, value, hash); + pair->next = this->table[row]; + this->table[row] = pair; this->count++; } if (this->count >= this->capacity * this->load_factor) @@ -275,17 +255,17 @@ METHOD(hashtable_t, get, void*, private_hashtable_t *this, void *key) { void *value = NULL; - linked_list_t *list; pair_t *pair; - list = this->table[this->hash(key) & this->mask]; - if (list) + pair = this->table[this->hash(key) & this->mask]; + while (pair) { - if (list->find_first(list, (linked_list_match_t)pair_equals, - (void**)&pair, this, key) == SUCCESS) + if (this->equals(key, pair->key)) { value = pair->value; + break; } + pair = pair->next; } return value; } @@ -294,27 +274,30 @@ METHOD(hashtable_t, remove_, void*, private_hashtable_t *this, void *key) { void *value = NULL; - linked_list_t *list; + pair_t *pair, *prev = NULL; + u_int row; - list = this->table[this->hash(key) & this->mask]; - if (list) + row = this->hash(key) & this->mask; + pair = this->table[row]; + while (pair) { - enumerator_t *enumerator; - pair_t *pair; - - enumerator = list->create_enumerator(list); - while (enumerator->enumerate(enumerator, &pair)) + if (this->equals(key, pair->key)) { - if (pair_equals(pair, this, key)) + if (prev) { - list->remove_at(list, enumerator); - value = pair->value; - this->count--; - free(pair); - break; + prev->next = pair->next; } + else + { + this->table[row] = pair->next; + } + value = pair->value; + this->count--; + free(pair); + break; } - enumerator->destroy(enumerator); + prev = pair; + pair = pair->next; } return value; } @@ -324,14 +307,18 @@ METHOD(hashtable_t, remove_at, void, { if (enumerator->table == this && enumerator->current) { - linked_list_t *list; - list = this->table[enumerator->row]; - if (list) + pair_t *current = enumerator->current; + if (enumerator->prev) { - list->remove_at(list, enumerator->current); - free(enumerator->pair); - this->count--; + enumerator->prev->next = current->next; + } + else + { + this->table[enumerator->row] = current->next; } + enumerator->current = enumerator->prev; + free(current); + this->count--; } } @@ -344,50 +331,35 @@ METHOD(hashtable_t, get_count, u_int, METHOD(enumerator_t, enumerate, bool, private_enumerator_t *this, void **key, void **value) { - while (this->row < this->table->capacity) + while (this->count && this->row < this->table->capacity) { + this->prev = this->current; if (this->current) { - if (this->current->enumerate(this->current, &this->pair)) - { - if (key) - { - *key = this->pair->key; - } - if (value) - { - *value = this->pair->value; - } - return TRUE; - } - this->current->destroy(this->current); - this->current = NULL; + this->current = this->current->next; } else { - linked_list_t *list; - list = this->table->table[this->row]; - if (list) + this->current = this->table->table[this->row]; + } + if (this->current) + { + if (key) { - this->current = list->create_enumerator(list); - continue; + *key = this->current->key; } + if (value) + { + *value = this->current->value; + } + this->count--; + return TRUE; } this->row++; } return FALSE; } -METHOD(enumerator_t, enumerator_destroy, void, - private_enumerator_t *this) -{ - if (this->current) - { - this->current->destroy(this->current); - } - free(this); -} - METHOD(hashtable_t, create_enumerator, enumerator_t*, private_hashtable_t *this) { @@ -396,9 +368,10 @@ METHOD(hashtable_t, create_enumerator, enumerator_t*, INIT(enumerator, .enumerator = { .enumerate = (void*)_enumerate, - .destroy = (void*)_enumerator_destroy, + .destroy = (void*)free, }, .table = this, + .count = this->count, ); return &enumerator->enumerator; @@ -407,15 +380,17 @@ METHOD(hashtable_t, create_enumerator, enumerator_t*, METHOD(hashtable_t, destroy, void, private_hashtable_t *this) { - linked_list_t *list; + pair_t *pair, *next; u_int row; for (row = 0; row < this->capacity; row++) { - list = this->table[row]; - if (list) + pair = this->table[row]; + while (pair) { - list->destroy_function(list, free); + next = pair->next; + free(pair); + pair = next; } } free(this->table); diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c index 615d85c95..d3020a5d0 100644 --- a/src/libstrongswan/utils/host.c +++ b/src/libstrongswan/utils/host.c @@ -40,7 +40,7 @@ struct private_host_t { host_t public; /** - * low-lewel structure, wich stores the address + * low-lewel structure, which stores the address */ union { /** generic type */ @@ -59,26 +59,20 @@ struct private_host_t { }; -/** - * implements host_t.get_sockaddr - */ -static sockaddr_t *get_sockaddr(private_host_t *this) +METHOD(host_t, get_sockaddr, sockaddr_t*, + private_host_t *this) { return &(this->address); } -/** - * implements host_t.get_sockaddr_len - */ -static socklen_t *get_sockaddr_len(private_host_t *this) +METHOD(host_t, get_sockaddr_len, socklen_t*, + private_host_t *this) { return &(this->socklen); } -/** - * Implementation of host_t.is_anyaddr. - */ -static bool is_anyaddr(private_host_t *this) +METHOD(host_t, is_anyaddr, bool, + private_host_t *this) { switch (this->address.sa_family) { @@ -163,10 +157,8 @@ int host_printf_hook(char *dst, size_t dstlen, printf_hook_spec_t *spec, return print_in_hook(dst, dstlen, "%*s", spec->width, buffer); } -/** - * Implementation of host_t.get_address. - */ -static chunk_t get_address(private_host_t *this) +METHOD(host_t, get_address, chunk_t, + private_host_t *this) { chunk_t address = chunk_empty; @@ -192,18 +184,14 @@ static chunk_t get_address(private_host_t *this) } } -/** - * implements host_t.get_family - */ -static int get_family(private_host_t *this) +METHOD(host_t, get_family, int, + private_host_t *this) { return this->address.sa_family; } -/** - * implements host_t.get_port - */ -static u_int16_t get_port(private_host_t *this) +METHOD(host_t, get_port, u_int16_t, + private_host_t *this) { switch (this->address.sa_family) { @@ -222,10 +210,8 @@ static u_int16_t get_port(private_host_t *this) } } -/** - * implements host_t.set_port - */ -static void set_port(private_host_t *this, u_int16_t port) +METHOD(host_t, set_port, void, + private_host_t *this, u_int16_t port) { switch (this->address.sa_family) { @@ -246,19 +232,19 @@ static void set_port(private_host_t *this, u_int16_t port) } } -/** - * Implements host_t.clone. - */ -static private_host_t *clone_(private_host_t *this) +METHOD(host_t, clone_, host_t*, + private_host_t *this) { - private_host_t *new = malloc_thing(private_host_t); + private_host_t *new; + new = malloc_thing(private_host_t); memcpy(new, this, sizeof(private_host_t)); - return new; + + return &new->public; } /** - * Impelements host_t.ip_equals + * Implements host_t.ip_equals */ static bool ip_equals(private_host_t *this, private_host_t *other) { @@ -332,10 +318,8 @@ static bool equals(private_host_t *this, private_host_t *other) return FALSE; } -/** - * Implements host_t.destroy - */ -static void destroy(private_host_t *this) +METHOD(host_t, destroy, void, + private_host_t *this) { free(this); } @@ -345,20 +329,24 @@ static void destroy(private_host_t *this) */ static private_host_t *host_create_empty(void) { - private_host_t *this = malloc_thing(private_host_t); - - this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr; - this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len; - this->public.clone = (host_t* (*) (host_t*))clone_; - this->public.get_family = (int (*) (host_t*))get_family; - this->public.get_address = (chunk_t (*) (host_t *)) get_address; - this->public.get_port = (u_int16_t (*) (host_t *))get_port; - this->public.set_port = (void (*) (host_t *,u_int16_t))set_port; - this->public.get_differences = get_differences; - this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals; - this->public.equals = (bool (*) (host_t *,host_t *)) equals; - this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr; - this->public.destroy = (void (*) (host_t*))destroy; + private_host_t *this; + + INIT(this, + .public = { + .get_sockaddr = _get_sockaddr, + .get_sockaddr_len = _get_sockaddr_len, + .clone = _clone_, + .get_family = _get_family, + .get_address = _get_address, + .get_port = _get_port, + .set_port = _set_port, + .get_differences = get_differences, + .ip_equals = (bool (*)(host_t *,host_t *))ip_equals, + .equals = (bool (*)(host_t *,host_t *)) equals, + .is_anyaddr = _is_anyaddr, + .destroy = _destroy, + }, + ); return this; } @@ -585,7 +573,7 @@ host_t *host_create_from_subnet(char *string, int *bits) *bits = atoi(pos + 1); return host_create_from_string(buf, 0); } - net = host_create_from_string(buf, 0); + net = host_create_from_string(string, 0); if (net) { if (net->get_family(net) == AF_INET) diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index 252cfa28e..9f0007f78 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -81,6 +81,7 @@ static const x501rdn_t x501rdns[] = { {"N", OID_NAME, ASN1_PRINTABLESTRING}, {"G", OID_GIVEN_NAME, ASN1_PRINTABLESTRING}, {"I", OID_INITIALS, ASN1_PRINTABLESTRING}, + {"dnQualifier", OID_DN_QUALIFIER, ASN1_PRINTABLESTRING}, {"ID", OID_UNIQUE_IDENTIFIER, ASN1_PRINTABLESTRING}, {"EN", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING}, {"employeeNumber", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING}, @@ -219,6 +220,7 @@ METHOD(enumerator_t, rdn_part_enumerate, bool, {OID_NAME, ID_PART_RDN_N}, {OID_GIVEN_NAME, ID_PART_RDN_G}, {OID_INITIALS, ID_PART_RDN_I}, + {OID_DN_QUALIFIER, ID_PART_RDN_DNQ}, {OID_UNIQUE_IDENTIFIER, ID_PART_RDN_ID}, {OID_EMAIL_ADDRESS, ID_PART_RDN_E}, {OID_EMPLOYEE_NUMBER, ID_PART_RDN_EN}, diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index c463b0274..3978b23f3 100644 --- a/src/libstrongswan/utils/identification.h +++ b/src/libstrongswan/utils/identification.h @@ -171,6 +171,8 @@ enum id_part_t { ID_PART_RDN_G, /** Initials RDN of a DN */ ID_PART_RDN_I, + /** DN Qualifier RDN of a DN */ + ID_PART_RDN_DNQ, /** UniqueIdentifier RDN of a DN */ ID_PART_RDN_ID, /** Locality RDN of a DN */ @@ -293,12 +295,12 @@ struct identification_t { * * In favour of pluto, domainnames are prepended with an @, since * pluto resolves domainnames without an @ to IPv4 addresses. Since - * we use a seperate host_t class for addresses, this doesn't + * we use a separate host_t class for addresses, this doesn't * make sense for us. * * A distinguished name may contain one or more of the following RDNs: * ND, UID, DC, CN, S, SN, serialNumber, C, L, ST, O, OU, T, D, - * N, G, I, ID, EN, EmployeeNumber, E, Email, emailAddress, UN, + * N, G, I, dnQualifier, ID, EN, EmployeeNumber, E, Email, emailAddress, UN, * unstructuredName, TCGID. * * This constructor never returns NULL. If it does not find a suitable diff --git a/src/libstrongswan/utils/iterator.h b/src/libstrongswan/utils/iterator.h deleted file mode 100644 index 9be65b229..000000000 --- a/src/libstrongswan/utils/iterator.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup iterator iterator - * @{ @ingroup utils - */ - -#ifndef ITERATOR_H_ -#define ITERATOR_H_ - -#include <library.h> - - -typedef struct iterator_t iterator_t; - -/** - * Iterator interface, allows iteration over collections. - * - * iterator_t defines an interface for iterating over collections. - * It allows searching, deleting, updating and inserting. - * - * @deprecated Use enumerator instead. - */ -struct iterator_t { - - /** - * Return number of list items. - * - * @return number of list items - */ - int (*get_count) (iterator_t *this); - - /** - * Iterate over all items. - * - * The easy way to iterate over items. - * - * @param value item - * @return TRUE, if there was an element available, FALSE otherwise - */ - bool (*iterate) (iterator_t *this, void** value); - - /** - * Inserts a new item before the given iterator position. - * - * The iterator position is not changed after inserting - * - * @param item value to insert in list - */ - void (*insert_before) (iterator_t *this, void *item); - - /** - * Inserts a new item after the given iterator position. - * - * The iterator position is not changed after inserting. - * - * @param this calling iterator - * @param item value to insert in list - */ - void (*insert_after) (iterator_t *this, void *item); - - /** - * Replace the current item at current iterator position. - * - * The iterator position is not changed after replacing. - * - * @param this calling iterator - * @param old old value will be written here(can be NULL) - * @param new new value - * @return SUCCESS, FAILED if iterator is on an invalid position - */ - status_t (*replace) (iterator_t *this, void **old, void *new); - - /** - * Removes an element from list at the given iterator position. - * - * The iterator is set the the following position: - * - to the item before, if available - * - it gets reseted, otherwise - * - * @return SUCCESS, FAILED if iterator is on an invalid position - */ - status_t (*remove) (iterator_t *this); - - /** - * Resets the iterator position. - * - * After reset, the iterator_t objects doesn't point to an element. - * A call to iterator_t.has_next is necessary to do any other operations - * with the resetted iterator. - */ - void (*reset) (iterator_t *this); - - /** - * Destroys an iterator. - */ - void (*destroy) (iterator_t *this); -}; - -#endif /** ITERATOR_H_ @}*/ diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 39505d3f3..0a8789335 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -34,6 +34,7 @@ #include <library.h> #include <debug.h> #include <utils/backtrace.h> +#include <utils/hashtable.h> typedef struct private_leak_detective_t private_leak_detective_t; @@ -92,11 +93,6 @@ typedef struct memory_tail_t memory_tail_t; struct memory_header_t { /** - * Number of bytes following after the header - */ - u_int bytes; - - /** * Pointer to previous entry in linked list */ memory_header_t *previous; @@ -112,6 +108,11 @@ struct memory_header_t { backtrace_t *backtrace; /** + * Number of bytes following after the header + */ + u_int32_t bytes; + + /** * magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC */ u_int32_t magic; @@ -148,6 +149,37 @@ static memory_header_t first_header = { static bool installed = FALSE; /** + * Installs the malloc hooks, enables leak detection + */ +static void install_hooks() +{ + if (!installed) + { + old_malloc_hook = __malloc_hook; + old_realloc_hook = __realloc_hook; + old_free_hook = __free_hook; + __malloc_hook = malloc_hook; + __realloc_hook = realloc_hook; + __free_hook = free_hook; + installed = TRUE; + } +} + +/** + * Uninstalls the malloc hooks, disables leak detection + */ +static void uninstall_hooks() +{ + if (installed) + { + __malloc_hook = old_malloc_hook; + __free_hook = old_free_hook; + __realloc_hook = old_realloc_hook; + installed = FALSE; + } +} + +/** * Leak report white list * * List of functions using static allocation buffers or should be suppressed @@ -162,6 +194,7 @@ char *whitelist[] = { "__pthread_setspecific", /* glibc functions */ "mktime", + "ctime", "__gmtime_r", "localtime_r", "tzset", @@ -172,6 +205,7 @@ char *whitelist[] = { "getprotobynumber", "getservbyport", "getservbyname", + "gethostbyname", "gethostbyname2", "gethostbyname_r", "gethostbyname2_r", @@ -187,6 +221,9 @@ char *whitelist[] = { "getaddrinfo", "setlocale", "getpass", + "getpwent_r", + "setpwent", + "endpwent", /* ignore dlopen, as we do not dlclose to get proper leak reports */ "dlopen", "dlerror", @@ -236,31 +273,109 @@ char *whitelist[] = { "gnutls_global_init", }; + /** - * Report leaks at library destruction + * Hashtable hash function */ -static void report(private_leak_detective_t *this, bool detailed) +static u_int hash(backtrace_t *key) { - if (lib->leak_detective) + enumerator_t *enumerator; + void *addr; + u_int hash = 0; + + enumerator = key->create_frame_enumerator(key); + while (enumerator->enumerate(enumerator, &addr)) { - memory_header_t *hdr; - int leaks = 0, whitelisted = 0; + hash = chunk_hash_inc(chunk_from_thing(addr), hash); + } + enumerator->destroy(enumerator); + + return hash; +} + +/** + * Hashtable equals function + */ +static bool equals(backtrace_t *a, backtrace_t *b) +{ + return a->equals(a, b); +} - for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) +/** + * Summarize and print backtraces + */ +static int print_traces(private_leak_detective_t *this, + FILE *out, int thresh, bool detailed, int *whitelisted) +{ + int leaks = 0; + memory_header_t *hdr; + enumerator_t *enumerator; + hashtable_t *entries; + struct { + /** associated backtrace */ + backtrace_t *backtrace; + /** total size of all allocations */ + size_t bytes; + /** number of allocations */ + u_int count; + } *entry; + + uninstall_hooks(); + + entries = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 1024); + for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) + { + if (whitelisted && + hdr->backtrace->contains_function(hdr->backtrace, + whitelist, countof(whitelist))) { - if (hdr->backtrace->contains_function(hdr->backtrace, - whitelist, countof(whitelist))) - { - whitelisted++; - } - else - { - fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1); - /* skip the first frame, contains leak detective logic */ - hdr->backtrace->log(hdr->backtrace, stderr, detailed); - leaks++; - } + (*whitelisted)++; + continue; + } + entry = entries->get(entries, hdr->backtrace); + if (entry) + { + entry->bytes += hdr->bytes; + entry->count++; + } + else + { + INIT(entry, + .backtrace = hdr->backtrace, + .bytes = hdr->bytes, + .count = 1, + ); + entries->put(entries, hdr->backtrace, entry); } + leaks++; + } + enumerator = entries->create_enumerator(entries); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + if (!thresh || entry->bytes >= thresh) + { + fprintf(out, "%d bytes total, %d allocations, %d bytes average:\n", + entry->bytes, entry->count, entry->bytes / entry->count); + entry->backtrace->log(entry->backtrace, out, detailed); + } + free(entry); + } + enumerator->destroy(enumerator); + entries->destroy(entries); + + install_hooks(); + return leaks; +} + +METHOD(leak_detective_t, report, void, + private_leak_detective_t *this, bool detailed) +{ + if (lib->leak_detective) + { + int leaks = 0, whitelisted = 0; + + leaks = print_traces(this, stderr, 0, detailed, &whitelisted); switch (leaks) { case 0: @@ -281,35 +396,26 @@ static void report(private_leak_detective_t *this, bool detailed) } } -/** - * Installs the malloc hooks, enables leak detection - */ -static void install_hooks() +METHOD(leak_detective_t, usage, void, + private_leak_detective_t *this, FILE *out) { - if (!installed) - { - old_malloc_hook = __malloc_hook; - old_realloc_hook = __realloc_hook; - old_free_hook = __free_hook; - __malloc_hook = malloc_hook; - __realloc_hook = realloc_hook; - __free_hook = free_hook; - installed = TRUE; - } -} + int oldpolicy, thresh; + bool detailed; + pthread_t thread_id = pthread_self(); + struct sched_param oldparams, params; -/** - * Uninstalls the malloc hooks, disables leak detection - */ -static void uninstall_hooks() -{ - if (installed) - { - __malloc_hook = old_malloc_hook; - __free_hook = old_free_hook; - __realloc_hook = old_realloc_hook; - installed = FALSE; - } + thresh = lib->settings->get_int(lib->settings, + "libstrongswan.leak_detective.usage_threshold", 10240); + detailed = lib->settings->get_bool(lib->settings, + "libstrongswan.leak_detective.detailed", TRUE); + + pthread_getschedparam(thread_id, &oldpolicy, &oldparams); + params.__sched_priority = sched_get_priority_max(SCHED_FIFO); + pthread_setschedparam(thread_id, SCHED_FIFO, ¶ms); + + print_traces(this, out, thresh, detailed, NULL); + + pthread_setschedparam(thread_id, oldpolicy, &oldparams); } /** @@ -492,10 +598,8 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) return hdr + 1; } -/** - * Implementation of leak_detective_t.destroy - */ -static void destroy(private_leak_detective_t *this) +METHOD(leak_detective_t, destroy, void, + private_leak_detective_t *this) { if (installed) { @@ -509,10 +613,15 @@ static void destroy(private_leak_detective_t *this) */ leak_detective_t *leak_detective_create() { - private_leak_detective_t *this = malloc_thing(private_leak_detective_t); + private_leak_detective_t *this; - this->public.report = (void(*)(leak_detective_t*,bool))report; - this->public.destroy = (void(*)(leak_detective_t*))destroy; + INIT(this, + .public = { + .report = _report, + .usage = _usage, + .destroy = _destroy, + }, + ); if (getenv("LEAK_DETECTIVE_DISABLE") == NULL) { @@ -526,7 +635,6 @@ leak_detective_t *leak_detective_create() fprintf(stderr, "setting CPU affinity failed: %m"); } - lib->leak_detective = TRUE; install_hooks(); } return &this->public; diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h index fa45a6076..8c80d2532 100644 --- a/src/libstrongswan/utils/leak_detective.h +++ b/src/libstrongswan/utils/leak_detective.h @@ -43,6 +43,13 @@ struct leak_detective_t { void (*report)(leak_detective_t *this, bool detailed); /** + * Report current memory usage to out. + * + * @param out target to write usage report to + */ + void (*usage)(leak_detective_t *this, FILE *out); + + /** * Destroy a leak_detective instance. */ void (*destroy)(leak_detective_t *this); diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c index 9b37359dc..59d416f2f 100644 --- a/src/libstrongswan/utils/linked_list.c +++ b/src/libstrongswan/utils/linked_list.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2008 Tobias Brunner + * Copyright (C) 2007-2011 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -51,13 +51,11 @@ struct element_t { */ element_t *element_create(void *value) { - element_t *this = malloc_thing(element_t); - - this->previous = NULL; - this->next = NULL; - this->value = value; - - return (this); + element_t *this; + INIT(this, + .value = value, + ); + return this; } @@ -91,34 +89,6 @@ struct private_linked_list_t { element_t *last; }; - -typedef struct private_iterator_t private_iterator_t; - -/** - * Private variables and functions of linked list iterator. - */ -struct private_iterator_t { - /** - * Public part of linked list iterator. - */ - iterator_t public; - - /** - * Associated linked list. - */ - private_linked_list_t * list; - - /** - * Current element of the iterator. - */ - element_t *current; - - /** - * Direction of iterator. - */ - bool forward; -}; - typedef struct private_enumerator_t private_enumerator_t; /** @@ -140,241 +110,78 @@ struct private_enumerator_t { * current item */ element_t *current; + + /** + * enumerator has enumerated all items + */ + bool finished; }; -/** - * Implementation of private_enumerator_t.enumerator.enumerate. - */ -static bool enumerate(private_enumerator_t *this, void **item) +METHOD(enumerator_t, enumerate, bool, + private_enumerator_t *this, void **item) { + if (this->finished) + { + return FALSE; + } if (!this->current) { - if (!this->list->first) - { - return FALSE; - } this->current = this->list->first; } else { - if (!this->current->next) - { - return FALSE; - } this->current = this->current->next; } - *item = this->current->value; - return TRUE; -} - -/** - * Implementation of linked_list_t.create_enumerator. - */ -static enumerator_t* create_enumerator(private_linked_list_t *this) -{ - private_enumerator_t *enumerator = malloc_thing(private_enumerator_t); - - enumerator->enumerator.enumerate = (void*)enumerate; - enumerator->enumerator.destroy = (void*)free; - enumerator->list = this; - enumerator->current = NULL; - - return &enumerator->enumerator; -} - -/** - * Implementation of iterator_t.get_count. - */ -static int get_list_count(private_iterator_t *this) -{ - return this->list->count; -} - -/** - * Implementation of iterator_t.iterate. - */ -static bool iterate(private_iterator_t *this, void** value) -{ - if (this->forward) - { - this->current = this->current ? this->current->next : this->list->first; - } - else - { - this->current = this->current ? this->current->previous : this->list->last; - } - if (this->current == NULL) + if (!this->current) { + this->finished = TRUE; return FALSE; } - *value = this->current->value; + *item = this->current->value; return TRUE; } -/** - * Implementation of iterator_t.reset. - */ -static void iterator_reset(private_iterator_t *this) +METHOD(linked_list_t, create_enumerator, enumerator_t*, + private_linked_list_t *this) { - this->current = NULL; -} + private_enumerator_t *enumerator; -/** - * Implementation of iterator_t.remove. - */ -static status_t iterator_remove(private_iterator_t *this) -{ - element_t *new_current; + INIT(enumerator, + .enumerator = { + .enumerate = (void*)_enumerate, + .destroy = (void*)free, + }, + .list = this, + ); - if (this->current == NULL) - { - return NOT_FOUND; - } - - if (this->list->count == 0) - { - return NOT_FOUND; - } - /* find out the new iterator position, depending on iterator direction */ - if (this->forward && this->current->previous != NULL) - { - new_current = this->current->previous; - } - else if (!this->forward && this->current->next != NULL) - { - new_current = this->current->next; - } - else - { - new_current = NULL; - } - - /* now delete the entry :-) */ - if (this->current->previous == NULL) - { - if (this->current->next == NULL) - { - this->list->first = NULL; - this->list->last = NULL; - } - else - { - this->current->next->previous = NULL; - this->list->first = this->current->next; - } - } - else if (this->current->next == NULL) - { - this->current->previous->next = NULL; - this->list->last = this->current->previous; - } - else - { - this->current->previous->next = this->current->next; - this->current->next->previous = this->current->previous; - } - - this->list->count--; - free(this->current); - /* set the new iterator position */ - this->current = new_current; - return SUCCESS; -} - -/** - * Implementation of iterator_t.insert_before. - */ -static void insert_before(private_iterator_t * iterator, void *item) -{ - if (iterator->current == NULL) - { - iterator->list->public.insert_first(&(iterator->list->public), item); - return; - } - - element_t *element = element_create(item); - if (iterator->current->previous == NULL) - { - iterator->current->previous = element; - element->next = iterator->current; - iterator->list->first = element; - } - else - { - iterator->current->previous->next = element; - element->previous = iterator->current->previous; - iterator->current->previous = element; - element->next = iterator->current; - } - iterator->list->count++; + return &enumerator->enumerator; } -/** - * Implementation of iterator_t.replace. - */ -static status_t replace(private_iterator_t *this, void **old_item, void *new_item) +METHOD(linked_list_t, reset_enumerator, void, + private_linked_list_t *this, private_enumerator_t *enumerator) { - if (this->current == NULL) - { - return NOT_FOUND; - } - if (old_item != NULL) - { - *old_item = this->current->value; - } - this->current->value = new_item; - - return SUCCESS; + enumerator->current = NULL; + enumerator->finished = FALSE; } -/** - * Implementation of iterator_t.insert_after. - */ -static void insert_after(private_iterator_t *iterator, void *item) +METHOD(linked_list_t, has_more, bool, + private_linked_list_t *this, private_enumerator_t *enumerator) { - if (iterator->current == NULL) - { - iterator->list->public.insert_first(&(iterator->list->public),item); - return; - } - - element_t *element = element_create(item); - if (iterator->current->next == NULL) - { - iterator->current->next = element; - element->previous = iterator->current; - iterator->list->last = element; - } - else + if (enumerator->current) { - iterator->current->next->previous = element; - element->next = iterator->current->next; - iterator->current->next = element; - element->previous = iterator->current; + return enumerator->current->next != NULL; } - iterator->list->count++; + return !enumerator->finished && this->first != NULL; } -/** - * Implementation of iterator_t.destroy. - */ -static void iterator_destroy(private_iterator_t *this) -{ - free(this); -} - -/** - * Implementation of linked_list_t.get_count. - */ -static int get_count(private_linked_list_t *this) +METHOD(linked_list_t, get_count, int, + private_linked_list_t *this) { return this->count; } -/** - * Implementation of linked_list_t.insert_first. - */ -static void insert_first(private_linked_list_t *this, void *item) +METHOD(linked_list_t, insert_first, void, + private_linked_list_t *this, void *item) { element_t *element; @@ -384,15 +191,11 @@ static void insert_first(private_linked_list_t *this, void *item) /* first entry in list */ this->first = element; this->last = element; - element->previous = NULL; - element->next = NULL; } else { - element_t *old_first_element = this->first; - element->next = old_first_element; - element->previous = NULL; - old_first_element->previous = element; + element->next = this->first; + this->first->previous = element; this->first = element; } this->count++; @@ -401,7 +204,8 @@ static void insert_first(private_linked_list_t *this, void *item) /** * unlink an element form the list, returns following element */ -static element_t* remove_element(private_linked_list_t *this, element_t *element) +static element_t* remove_element(private_linked_list_t *this, + element_t *element) { element_t *next, *previous; @@ -432,10 +236,8 @@ static element_t* remove_element(private_linked_list_t *this, element_t *element return next; } -/** - * Implementation of linked_list_t.get_first. - */ -static status_t get_first(private_linked_list_t *this, void **item) +METHOD(linked_list_t, get_first, status_t, + private_linked_list_t *this, void **item) { if (this->count == 0) { @@ -445,10 +247,8 @@ static status_t get_first(private_linked_list_t *this, void **item) return SUCCESS; } -/** - * Implementation of linked_list_t.remove_first. - */ -static status_t remove_first(private_linked_list_t *this, void **item) +METHOD(linked_list_t, remove_first, status_t, + private_linked_list_t *this, void **item) { if (get_first(this, item) == SUCCESS) { @@ -458,36 +258,79 @@ static status_t remove_first(private_linked_list_t *this, void **item) return NOT_FOUND; } -/** - * Implementation of linked_list_t.insert_last. - */ -static void insert_last(private_linked_list_t *this, void *item) +METHOD(linked_list_t, insert_last, void, + private_linked_list_t *this, void *item) { - element_t *element = element_create(item); + element_t *element; + element = element_create(item); if (this->count == 0) { /* first entry in list */ this->first = element; this->last = element; - element->previous = NULL; - element->next = NULL; } else { - element_t *old_last_element = this->last; - element->previous = old_last_element; - element->next = NULL; - old_last_element->next = element; + element->previous = this->last; + this->last->next = element; this->last = element; } this->count++; } -/** - * Implementation of linked_list_t.get_last. - */ -static status_t get_last(private_linked_list_t *this, void **item) +METHOD(linked_list_t, insert_before, void, + private_linked_list_t *this, private_enumerator_t *enumerator, + void *item) +{ + element_t *current, *element; + + current = enumerator->current; + if (!current) + { + if (enumerator->finished) + { + this->public.insert_last(&this->public, item); + } + else + { + this->public.insert_first(&this->public, item); + } + return; + } + element = element_create(item); + if (current->previous) + { + current->previous->next = element; + element->previous = current->previous; + current->previous = element; + element->next = current; + } + else + { + current->previous = element; + element->next = current; + this->first = element; + } + this->count++; +} + +METHOD(linked_list_t, replace, void*, + private_linked_list_t *this, private_enumerator_t *enumerator, + void *item) +{ + void *old = NULL; + + if (enumerator->current) + { + old = enumerator->current->value; + enumerator->current->value = item; + } + return old; +} + +METHOD(linked_list_t, get_last, status_t, + private_linked_list_t *this, void **item) { if (this->count == 0) { @@ -497,10 +340,8 @@ static status_t get_last(private_linked_list_t *this, void **item) return SUCCESS; } -/** - * Implementation of linked_list_t.remove_last. - */ -static status_t remove_last(private_linked_list_t *this, void **item) +METHOD(linked_list_t, remove_last, status_t, + private_linked_list_t *this, void **item) { if (get_last(this, item) == SUCCESS) { @@ -510,11 +351,8 @@ static status_t remove_last(private_linked_list_t *this, void **item) return NOT_FOUND; } -/** - * Implementation of linked_list_t.remove. - */ -static int remove_(private_linked_list_t *this, void *item, - bool (*compare)(void *,void*)) +METHOD(linked_list_t, remove_, int, + private_linked_list_t *this, void *item, bool (*compare)(void*,void*)) { element_t *current = this->first; int removed = 0; @@ -535,10 +373,8 @@ static int remove_(private_linked_list_t *this, void *item, return removed; } -/** - * Implementation of linked_list_t.remove_at. - */ -static void remove_at(private_linked_list_t *this, private_enumerator_t *enumerator) +METHOD(linked_list_t, remove_at, void, + private_linked_list_t *this, private_enumerator_t *enumerator) { element_t *current; @@ -550,11 +386,9 @@ static void remove_at(private_linked_list_t *this, private_enumerator_t *enumera } } -/** - * Implementation of linked_list_t.find_first. - */ -static status_t find_first(private_linked_list_t *this, linked_list_match_t match, - void **item, void *d1, void *d2, void *d3, void *d4, void *d5) +METHOD(linked_list_t, find_first, status_t, + private_linked_list_t *this, linked_list_match_t match, + void **item, void *d1, void *d2, void *d3, void *d4, void *d5) { element_t *current = this->first; @@ -574,11 +408,9 @@ static status_t find_first(private_linked_list_t *this, linked_list_match_t matc return NOT_FOUND; } -/** - * Implementation of linked_list_t.find_last. - */ -static status_t find_last(private_linked_list_t *this, linked_list_match_t match, - void **item, void *d1, void *d2, void *d3, void *d4, void *d5) +METHOD(linked_list_t, find_last, status_t, + private_linked_list_t *this, linked_list_match_t match, + void **item, void *d1, void *d2, void *d3, void *d4, void *d5) { element_t *current = this->last; @@ -598,27 +430,24 @@ static status_t find_last(private_linked_list_t *this, linked_list_match_t match return NOT_FOUND; } -/** - * Implementation of linked_list_t.invoke_offset. - */ -static void invoke_offset(private_linked_list_t *this, size_t offset, - void *d1, void *d2, void *d3, void *d4, void *d5) +METHOD(linked_list_t, invoke_offset, void, + private_linked_list_t *this, size_t offset, + void *d1, void *d2, void *d3, void *d4, void *d5) { element_t *current = this->first; + linked_list_invoke_t *method; while (current) { - linked_list_invoke_t *method = current->value + offset; + method = current->value + offset; (*method)(current->value, d1, d2, d3, d4, d5); current = current->next; } } -/** - * Implementation of linked_list_t.invoke_function. - */ -static void invoke_function(private_linked_list_t *this, linked_list_invoke_t fn, - void *d1, void *d2, void *d3, void *d4, void *d5) +METHOD(linked_list_t, invoke_function, void, + private_linked_list_t *this, linked_list_invoke_t fn, + void *d1, void *d2, void *d3, void *d4, void *d5) { element_t *current = this->first; @@ -629,14 +458,13 @@ static void invoke_function(private_linked_list_t *this, linked_list_invoke_t fn } } -/** - * Implementation of linked_list_t.clone_offset - */ -static linked_list_t *clone_offset(private_linked_list_t *this, size_t offset) +METHOD(linked_list_t, clone_offset, linked_list_t*, + private_linked_list_t *this, size_t offset) { - linked_list_t *clone = linked_list_create(); element_t *current = this->first; + linked_list_t *clone; + clone = linked_list_create(); while (current) { void* (**method)(void*) = current->value + offset; @@ -647,29 +475,26 @@ static linked_list_t *clone_offset(private_linked_list_t *this, size_t offset) return clone; } -/** - * Implementation of linked_list_t.clone_function - */ -static linked_list_t *clone_function(private_linked_list_t *this, void* (*fn)(void*)) +METHOD(linked_list_t, clone_function, linked_list_t*, + private_linked_list_t *this, void* (*fn)(void*)) { - linked_list_t *clone = linked_list_create(); element_t *current = this->first; + linked_list_t *clone; + clone = linked_list_create(); while (current) { clone->insert_last(clone, fn(current->value)); current = current->next; } - return clone; } -/** - * Implementation of linked_list_t.destroy. - */ -static void destroy(private_linked_list_t *this) +METHOD(linked_list_t, destroy, void, + private_linked_list_t *this) { void *value; + /* Remove all list items before destroying list */ while (remove_first(this, &value) == SUCCESS) { @@ -679,10 +504,8 @@ static void destroy(private_linked_list_t *this) free(this); } -/** - * Implementation of linked_list_t.destroy_offset. - */ -static void destroy_offset(private_linked_list_t *this, size_t offset) +METHOD(linked_list_t, destroy_offset, void, + private_linked_list_t *this, size_t offset) { element_t *current = this->first, *next; @@ -697,10 +520,8 @@ static void destroy_offset(private_linked_list_t *this, size_t offset) free(this); } -/** - * Implementation of linked_list_t.destroy_function. - */ -static void destroy_function(private_linked_list_t *this, void (*fn)(void*)) +METHOD(linked_list_t, destroy_function, void, + private_linked_list_t *this, void (*fn)(void*)) { element_t *current = this->first, *next; @@ -714,60 +535,40 @@ static void destroy_function(private_linked_list_t *this, void (*fn)(void*)) free(this); } -/** - * Implementation of linked_list_t.create_iterator. - */ -static iterator_t *create_iterator(private_linked_list_t *linked_list, bool forward) -{ - private_iterator_t *this = malloc_thing(private_iterator_t); - - this->public.get_count = (int (*) (iterator_t*)) get_list_count; - this->public.iterate = (bool (*) (iterator_t*, void **value)) iterate; - this->public.insert_before = (void (*) (iterator_t*, void *item)) insert_before; - this->public.insert_after = (void (*) (iterator_t*, void *item)) insert_after; - this->public.replace = (status_t (*) (iterator_t*, void **, void *)) replace; - this->public.remove = (status_t (*) (iterator_t*)) iterator_remove; - this->public.reset = (void (*) (iterator_t*)) iterator_reset; - this->public.destroy = (void (*) (iterator_t*)) iterator_destroy; - - this->forward = forward; - this->current = NULL; - this->list = linked_list; - - return &this->public; -} - /* * Described in header. */ linked_list_t *linked_list_create() { - private_linked_list_t *this = malloc_thing(private_linked_list_t); - - this->public.get_count = (int (*) (linked_list_t *)) get_count; - this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool))create_iterator; - this->public.create_enumerator = (enumerator_t*(*)(linked_list_t*))create_enumerator; - this->public.get_first = (status_t (*) (linked_list_t *, void **item))get_first; - this->public.get_last = (status_t (*) (linked_list_t *, void **item))get_last; - this->public.find_first = (status_t (*) (linked_list_t *, linked_list_match_t,void**,...))find_first; - this->public.find_last = (status_t (*) (linked_list_t *, linked_list_match_t,void**,...))find_last; - this->public.insert_first = (void (*) (linked_list_t *, void *item))insert_first; - this->public.insert_last = (void (*) (linked_list_t *, void *item))insert_last; - this->public.remove_first = (status_t (*) (linked_list_t *, void **item))remove_first; - this->public.remove_last = (status_t (*) (linked_list_t *, void **item))remove_last; - this->public.remove = (int(*)(linked_list_t*, void *item, bool (*compare)(void *,void*)))remove_; - this->public.remove_at = (void(*)(linked_list_t*, enumerator_t *enumerator))remove_at; - this->public.invoke_offset = (void (*)(linked_list_t*,size_t,...))invoke_offset; - this->public.invoke_function = (void (*)(linked_list_t*,linked_list_invoke_t,...))invoke_function; - this->public.clone_offset = (linked_list_t * (*)(linked_list_t*,size_t))clone_offset; - this->public.clone_function = (linked_list_t * (*)(linked_list_t*,void*(*)(void*)))clone_function; - this->public.destroy = (void (*) (linked_list_t *))destroy; - this->public.destroy_offset = (void (*) (linked_list_t *,size_t))destroy_offset; - this->public.destroy_function = (void (*)(linked_list_t*,void(*)(void*)))destroy_function; - - this->count = 0; - this->first = NULL; - this->last = NULL; + private_linked_list_t *this; + + INIT(this, + .public = { + .get_count = _get_count, + .create_enumerator = _create_enumerator, + .reset_enumerator = (void*)_reset_enumerator, + .has_more = (void*)_has_more, + .get_first = _get_first, + .get_last = _get_last, + .find_first = (void*)_find_first, + .find_last = (void*)_find_last, + .insert_first = _insert_first, + .insert_last = _insert_last, + .insert_before = (void*)_insert_before, + .replace = (void*)_replace, + .remove_first = _remove_first, + .remove_last = _remove_last, + .remove = _remove_, + .remove_at = (void*)_remove_at, + .invoke_offset = (void*)_invoke_offset, + .invoke_function = (void*)_invoke_function, + .clone_offset = _clone_offset, + .clone_function = _clone_function, + .destroy = _destroy, + .destroy_offset = _destroy_offset, + .destroy_function = _destroy_function, + }, + ); return &this->public; } diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h index 1444c93fc..293ca8661 100644 --- a/src/libstrongswan/utils/linked_list.h +++ b/src/libstrongswan/utils/linked_list.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2008 Tobias Brunner + * Copyright (C) 2007-2011 Tobias Brunner * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -25,7 +25,6 @@ typedef struct linked_list_t linked_list_t; -#include <utils/iterator.h> #include <utils/enumerator.h> /** @@ -62,27 +61,29 @@ struct linked_list_t { int (*get_count) (linked_list_t *this); /** - * Creates a iterator for the given list. - * - * @warning Created iterator_t object has to get destroyed by the caller. + * Create an enumerator over the list. * - * @deprecated Iterator is obsolete and will disappear, it is too - * complicated to implement. Use enumerator instead. + * @note The enumerator's position is invalid before the first call + * to enumerate(). * - * @param forward iterator direction (TRUE: front to end) - * @return new iterator_t object + * @return enumerator over list items */ - iterator_t *(*create_iterator) (linked_list_t *this, bool forward); + enumerator_t* (*create_enumerator)(linked_list_t *this); /** - * Create an enumerator over the list. + * Resets the enumerator's current position to the beginning of the list. * - * The enumerator is a "lightweight" iterator. It only has two methods - * and should therefore be much easier to implement. + * @param enumerator enumerator to reset + */ + void (*reset_enumerator)(linked_list_t *this, enumerator_t *enumerator); + + /** + * Checks if there are more elements following after the enumerator's + * current position. * - * @return enumerator over list items + * @param enumerator enumerator to check */ - enumerator_t* (*create_enumerator)(linked_list_t *this); + bool (*has_more)(linked_list_t *this, enumerator_t *enumerator); /** * Inserts a new item at the beginning of the list. @@ -100,6 +101,32 @@ struct linked_list_t { status_t (*remove_first) (linked_list_t *this, void **item); /** + * Inserts a new item before the item the enumerator currently points to. + * + * If this method is called before starting the enumeration the item is + * inserted first. If it is called after all items have been enumerated + * the item is inserted last. This is helpful when inserting items into + * a sorted list. + * + * @note The position of the enumerator is not changed. + * + * @param enumerator enumerator with position + * @param item item value to insert in list + */ + void (*insert_before)(linked_list_t *this, enumerator_t *enumerator, + void *item); + + /** + * Replaces the item the enumerator currently points to with the given item. + * + * @param enumerator enumerator with position + * @param item item value to replace current item with + * @return current item or NULL if the enumerator is at an + * invalid position + */ + void *(*replace)(linked_list_t *this, enumerator_t *enumerator, void *item); + + /** * Remove an item from the list where the enumerator points to. * * @param enumerator enumerator with position @@ -125,7 +152,6 @@ struct linked_list_t { /** * Returns the value of the first list item without removing it. * - * @param this calling object * @param item returned value of first item * @return SUCCESS, NOT_FOUND if list is empty */ @@ -141,7 +167,6 @@ struct linked_list_t { /** * Removes the last item in the list and returns its value. * - * @param this calling object * @param item returned value of last item, or NULL * @return SUCCESS, NOT_FOUND if list is empty */ @@ -150,7 +175,6 @@ struct linked_list_t { /** * Returns the value of the last list item without removing it. * - * @param this calling object * @param item returned value of last item * @return SUCCESS, NOT_FOUND if list is empty */ diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c index e51780290..5fd4cfd4d 100644 --- a/src/libstrongswan/utils/optionsfrom.c +++ b/src/libstrongswan/utils/optionsfrom.c @@ -67,7 +67,6 @@ METHOD(options_t, from, bool, int newargc; int next; /* place for next argument */ char **newargv; - size_t bytes; chunk_t src, line, token; bool good = TRUE; int linepos = 0; @@ -99,7 +98,14 @@ METHOD(options_t, from, bool, src.ptr = this->buffers[this->nuses] = malloc(src.len + 1); /* read the whole file into a chunk */ - bytes = fread(src.ptr, 1, src.len, fd); + if (fread(src.ptr, 1, src.len, fd) != src.len) + { + DBG1(DBG_LIB, "optionsfrom: unable to read file '%s': %s", + filename, strerror(errno)); + free(src.ptr); + fclose(fd); + return FALSE; + } fclose(fd); if (this->room) |