Tue, 16 Jul 2013 12:14:13 +0200
ucx update
--- a/src/server/config/acl.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/config/acl.c Tue Jul 16 12:14:13 2013 +0200 @@ -59,7 +59,7 @@ } void free_acl_file(ACLFile *conf) { - ucx_mempool_free(conf->parser.mp); + ucx_mempool_destroy(conf->parser.mp); free(conf); }
--- a/src/server/config/initconf.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/config/initconf.c Tue Jul 16 12:14:13 2013 +0200 @@ -55,7 +55,7 @@ } void free_init_config(InitConfig *conf) { - ucx_mempool_free(conf->parser.mp); + ucx_mempool_destroy(conf->parser.mp); free(conf); }
--- a/src/server/config/keyfile.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/config/keyfile.c Tue Jul 16 12:14:13 2013 +0200 @@ -58,7 +58,7 @@ if(conf->users) { ucx_list_free(conf->users); } - ucx_mempool_free(conf->parser.mp); + ucx_mempool_destroy(conf->parser.mp); free(conf); }
--- a/src/server/config/mimeconf.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/config/mimeconf.c Tue Jul 16 12:14:13 2013 +0200 @@ -61,7 +61,7 @@ } void free_mime_config(MimeConfig *conf) { - ucx_mempool_free(conf->parser.mp); + ucx_mempool_destroy(conf->parser.mp); free(conf); }
--- a/src/server/config/objconf.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/config/objconf.c Tue Jul 16 12:14:13 2013 +0200 @@ -70,7 +70,7 @@ } // free mempool - ucx_mempool_free(conf->parser.mp); + ucx_mempool_destroy(conf->parser.mp); free(conf); }
--- a/src/server/config/serverconf.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/config/serverconf.c Tue Jul 16 12:14:13 2013 +0200 @@ -57,7 +57,7 @@ } void free_server_config(ServerConfig *conf) { - ucx_mempool_free(conf->parser.mp); + ucx_mempool_destroy(conf->parser.mp); free(conf); }
--- a/src/server/daemon/acldata.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/daemon/acldata.c Tue Jul 16 12:14:13 2013 +0200 @@ -52,7 +52,7 @@ if(ref == 0) { UcxMapIterator i = ucx_map_iterator(acldata->namedACLs); WSAcl *acl; - UCX_MAP_FOREACH(acl, i) { + UCX_MAP_FOREACH(key, acl, i) { free(acl->ace); free(acl->ece); if(acl->acl.authprompt) {
--- a/src/server/daemon/config.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/daemon/config.c Tue Jul 16 12:14:13 2013 +0200 @@ -256,7 +256,7 @@ //int b = 0; UcxMapIterator iter = ucx_map_iterator(serverconfig->host_vs); VirtualServer *vs; - UCX_MAP_FOREACH(vs, iter) { + UCX_MAP_FOREACH(key, vs, iter) { if(!sstrcmp(vsname, vs->name)) { listener->default_vs.vs = vs; break; @@ -316,6 +316,7 @@ f->data = NULL; f->file = sstrdup(file); f->reload = mime_conf_reload; + f->last_modified = 0; // load the file content //f->reload(f, cfg); @@ -535,6 +536,7 @@ f->data = NULL; f->file = sstrdup(file); f->reload = keyfile_reload; + f->last_modified = 0; //f->reload(f, cfg); if(cfgmgr_reload_file(f, cfg, NULL)) { free(f->file.ptr); @@ -617,6 +619,7 @@ f->data = NULL; f->file = sstrdup(file); f->reload = object_conf_reload; + f->last_modified = 0; //f->reload(f, cfg); if(cfgmgr_reload_file(f, cfg, NULL)) { free(f->file.ptr); @@ -640,6 +643,7 @@ aclf->data = NULL; aclf->file = sstrdup(file); aclf->reload = acl_conf_reload; + aclf->last_modified = 0; //aclf->reload(aclf, cfg); if(cfgmgr_reload_file(aclf, cfg, NULL)) { free(aclf->file.ptr); @@ -820,7 +824,7 @@ printf("free MimeConfig %"PRIxPTR"\n", (intptr_t)conf); UcxMapIterator i = ucx_map_iterator(conf->map); char *str; - UCX_MAP_FOREACH(str, i) { + UCX_MAP_FOREACH(key, str, i) { free(str); } ucx_map_free(conf->map);
--- a/src/server/daemon/configmanager.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/daemon/configmanager.c Tue Jul 16 12:14:13 2013 +0200 @@ -77,10 +77,12 @@ if(f->last_modified != s.st_mtime) { /* reload the file */ printf("reload: %s\n", f->file.ptr); - log_ereport( - LOG_INFORM, - "reload configuration file: %s", - f->file.ptr); + if(f->last_modified != 0) { + log_ereport( + LOG_INFORM, + "reload configuration file: %s", + f->file.ptr); + } f->reload(f, conf); f->last_modified = s.st_mtime; if(reload) { @@ -96,7 +98,7 @@ /* check config files */ UcxMapIterator iter = ucx_map_iterator(config_files); ConfigFile *f; - UCX_MAP_FOREACH(f, iter) { + UCX_MAP_FOREACH(key, f, iter) { if(cfgmgr_reload_file(f, current_config, &cfgreload) == -1) { return -1; }
--- a/src/server/daemon/keyfile_auth.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/daemon/keyfile_auth.c Tue Jul 16 12:14:13 2013 +0200 @@ -54,7 +54,7 @@ if(ref == 0) { UcxMapIterator i = ucx_map_iterator(keyfile->users); KeyfileUser *user; - UCX_MAP_FOREACH(user, i) { + UCX_MAP_FOREACH(key, user, i) { free(user->user.name); free(user->hash); for(int i=0;i<user->numgroups;i++) {
--- a/src/server/ucx/allocator.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/allocator.c Tue Jul 16 12:14:13 2013 +0200 @@ -29,6 +29,19 @@ #include <stdlib.h> #include "allocator.h" +UcxAllocator default_allocator = { + NULL, + ucx_default_malloc, + ucx_default_calloc, + ucx_default_realloc, + ucx_default_free +}; + +UcxAllocator *ucx_default_allocator() { + UcxAllocator *allocator = &default_allocator; + return allocator; +} + void *ucx_default_malloc(void *ignore, size_t n) { return malloc(n); } @@ -40,3 +53,7 @@ void *ucx_default_realloc(void *ignore, void *data, size_t n) { return realloc(data, n); } + +void ucx_default_free(void *ignore, void *data) { + free(data); +}
--- a/src/server/ucx/allocator.h Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/allocator.h Tue Jul 16 12:14:13 2013 +0200 @@ -38,20 +38,26 @@ typedef void*(*ucx_allocator_malloc)(void *pool, size_t n); typedef void*(*ucx_allocator_calloc)(void *pool, size_t n, size_t size); typedef void*(*ucx_allocator_realloc)(void *pool, void *data, size_t n); +typedef void(*ucx_allocator_free)(void *pool, void *data); typedef struct { void *pool; - ucx_allocator_malloc malloc; - ucx_allocator_calloc calloc; + ucx_allocator_malloc malloc; + ucx_allocator_calloc calloc; ucx_allocator_realloc realloc; + ucx_allocator_free free; } UcxAllocator; +UcxAllocator *ucx_default_allocator(); + void *ucx_default_malloc(void *ignore, size_t n); void *ucx_default_calloc(void *ignore, size_t n, size_t size); void *ucx_default_realloc(void *ignore, void *data, size_t n); +void ucx_default_free(void *ignore, void *data); #define UCX_ALLOCATOR_DEFAULT {NULL, \ - ucx_default_malloc, ucx_default_calloc, ucx_default_realloc} + ucx_default_malloc, ucx_default_calloc, ucx_default_realloc, \ + ucx_default_free } #ifdef __cplusplus }
--- a/src/server/ucx/map.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/map.c Tue Jul 16 12:14:13 2013 +0200 @@ -32,18 +32,30 @@ #include "map.h" UcxMap *ucx_map_new(size_t size) { + return ucx_map_new_allocator(size, NULL); +} + +UcxMap *ucx_map_new_allocator(size_t size, UcxAllocator *allocator) { if(size == 0) { size = 16; } + + if(!allocator) { + allocator = ucx_default_allocator(); + } - UcxMap *map = (UcxMap*)malloc(sizeof(UcxMap)); + UcxMap *map = (UcxMap*)allocator->malloc(allocator->pool, sizeof(UcxMap)); if(map == NULL) { return NULL; } - - map->map = (UcxMapElement**)calloc(size, sizeof(UcxMapElement*)); + + map->allocator = allocator; + map->map = (UcxMapElement**)allocator->calloc( + allocator->pool, + size, + sizeof(UcxMapElement*)); if(map->map == NULL) { - free(map); + allocator->free(allocator->pool, map); return NULL; } map->size = size; @@ -58,25 +70,25 @@ if (elem != NULL) { do { UcxMapElement *next = elem->next; - free(elem->key.data); - free(elem); + map->allocator->free(map->allocator->pool, elem->key.data); + map->allocator->free(map->allocator->pool, elem); elem = next; } while (elem != NULL); } } - free(map->map); + map->allocator->free(map->allocator->pool, map->map); } void ucx_map_free(UcxMap *map) { ucx_map_free_elmlist(map); - free(map); + map->allocator->free(map->allocator->pool, map); } int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to, copy_func fnc, void *data) { UcxMapIterator i = ucx_map_iterator(from); void *value; - UCX_MAP_FOREACH(value, i) { + UCX_MAP_FOREACH(key, value, i) { int ret = ucx_map_put(to, i.cur->key, fnc ? fnc(value, data) : value); if(ret != 0) { return 1; @@ -102,9 +114,13 @@ oldmap.map = map->map; oldmap.size = map->size; oldmap.count = map->count; + oldmap.allocator = map->allocator; map->size = (map->count * 5) >> 1; - map->map = (UcxMapElement**)calloc(map->size, sizeof(UcxMapElement*)); + map->map = (UcxMapElement**)map->allocator->calloc( + map->allocator->pool, + map->size, + sizeof(UcxMapElement*)); if(map->map == NULL) { *map = oldmap; return 1; @@ -119,6 +135,8 @@ } int ucx_map_put(UcxMap *map, UcxKey key, void *data) { + UcxAllocator *allocator = map->allocator; + if(key.hash == 0) { key.hash = ucx_hash((char*)key.data, key.len); } @@ -133,7 +151,9 @@ } if (elm == NULL || elm->key.hash != key.hash) { - UcxMapElement *e = (UcxMapElement*)malloc(sizeof(UcxMapElement)); + UcxMapElement *e = (UcxMapElement*)allocator->malloc( + allocator->pool, + sizeof(UcxMapElement)); if(e == NULL) { return -1; } @@ -148,7 +168,7 @@ } if(elm->key.data == NULL) { - void *kd = malloc(key.len); + void *kd = allocator->malloc(allocator->pool, key.len); if (kd == NULL) { return -1; } @@ -181,7 +201,7 @@ } else { map->map[slot] = elm->next; } - free(elm); + map->allocator->free(map->allocator->pool, elm); map->count--; } @@ -262,7 +282,7 @@ return i; } -int ucx_map_iter_next(UcxMapIterator *i, void **elm) { +int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm) { UcxMapElement *e = i->cur; if(e == NULL) { @@ -276,6 +296,7 @@ if(e->data != NULL) { i->cur = e; *elm = e->data; + *key = e->key; return 0; } @@ -292,123 +313,3 @@ return 1; } -int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator, - ucx_map_coder decoder, void* decdata) { - - int c; int r, n; - - char *key, *value; - - while ((c = fgetc(f)) > 0) { - /* Discard leading spaces and comments */ - if (c < 33) continue; - if (c == '#' || c == '!') { - while ((c = (char) fgetc(f)) > 0) { - if (c == '\n') break; - } - continue; - } - - /* read into key buffer */ - n = 16; - key = (char*) malloc(n); - r = 0; - do { - if (c == '=') break; - if (r > n - 2) { - n *= 2; - key = (char*) realloc(key, n); - } - key[r] = c; - r++; - } while ((c = fgetc(f)) > 0); - if (c <= 0) { - free(key); - return 1; - } - key[r] = 0; - while (key[--r] == ' ') key[r] = 0; - - /* skip whitespaces */ - while ((c = fgetc(f)) > 0) { - if (c > 32) break; - } - if (c <= 0) { - free(key); - return 1; - } - - /* read into value buffer */ - n = 64; - value = (char*) malloc(n); - r = 0; - do { - if (c == '\n') break; - if (r > n - 2) { - n *= 2; - value = (char*) realloc(value, n); - } - value[r] = c; - r++; - } while ((c = fgetc(f)) > 0); - value[r] = 0; - while (value[--r] < 33) value[r] = 0; - - if (decoder) { - size_t decodedSize; - void *decoded = decoder(value, decdata, &decodedSize); - free(value); - value = (char*) decoded; - r = decodedSize; - } else { - r += 2; - value = (char*) realloc(value, r); - } - - if (allocator.pool) { - void *pooledValue = allocator.malloc(allocator.pool, r); - memcpy(pooledValue, value, r); - free(value); - value = (char*) pooledValue; - } - - ucx_map_cstr_put(map, key, value); - free(key); - } - - return 0; -} - -int ucx_map_store_enc(UcxMap *map, FILE *f, - ucx_map_coder encoder, void *encdata) { - UcxMapIterator iter = ucx_map_iterator(map); - char *k, *v; - sstr_t key, value; - size_t written; - - UCX_MAP_FOREACH(v, iter) { - k = (char*) iter.cur->key.data; - key = sstrn(k, iter.cur->key.len); - if (encoder) { - size_t encodedSize; - void *encoded = encoder(v, encdata, &encodedSize); - value = sstrn((char*) encoded,encodedSize - 1); - } else { - value = sstr(v); - } - - written = 0; - written += fwrite(key.ptr, 1, key.length, f); - written += fwrite(" = ", 1, 3, f); - written += fwrite(value.ptr, 1, value.length, f); - written += fwrite("\n", 1, 1, f); - - if (encoder) { - free(value.ptr); - } - - if (written != key.length + value.length + 4) return 1; - } - - return 0; -}
--- a/src/server/ucx/map.h Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/map.h Tue Jul 16 12:14:13 2013 +0200 @@ -38,8 +38,8 @@ extern "C" { #endif -#define UCX_MAP_FOREACH(elm,iter) \ - for(;ucx_map_iter_next(&iter,(void**)&elm)==0;) +#define UCX_MAP_FOREACH(key,elm,iter) \ + for(UcxKey key;ucx_map_iter_next(&iter,&key, (void**)&elm)==0;) typedef struct UcxMap UcxMap; typedef struct UcxKey UcxKey; @@ -55,6 +55,7 @@ typedef void*(*ucx_map_coder)(void*,void*,size_t*); struct UcxMap { + UcxAllocator *allocator; UcxMapElement **map; size_t size; size_t count; @@ -80,6 +81,7 @@ UcxMap *ucx_map_new(size_t size); +UcxMap *ucx_map_new_allocator(size_t size, UcxAllocator *allocator); void ucx_map_free(UcxMap *map); /* you cannot clone maps with more than 390 mio entries */ int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to, @@ -92,11 +94,11 @@ void* ucx_map_remove(UcxMap *map, UcxKey key); #define ucx_map_sstr_put(m, s, d) \ - ucx_map_put(m, ucx_key(s.ptr, s.length), d) + ucx_map_put(m, ucx_key(s.ptr, s.length), (void*)d) #define ucx_map_cstr_put(m, s, d) \ - ucx_map_put(m, ucx_key((void*)s, strlen(s)), d) + ucx_map_put(m, ucx_key((void*)s, strlen(s)), (void*)d) #define ucx_map_int_put(m, i, d) \ - ucx_map_put(m, ucx_key((void*)&i, sizeof(i)), d) + ucx_map_put(m, ucx_key((void*)&i, sizeof(i)), (void*)d) #define ucx_map_sstr_get(m, s) \ ucx_map_get(m, ucx_key(s.ptr, s.length)) @@ -118,17 +120,8 @@ UcxMapIterator ucx_map_iterator(UcxMap *map); -int ucx_map_iter_next(UcxMapIterator *i, void **elm); - -/* use macros for string maps only, values are not encoded */ -#define ucx_map_load(map, f, alloc) ucx_map_load_enc(map, f, alloc, NULL, NULL) -#define ucx_map_store(map, f) ucx_map_store_enc(map, f, NULL, NULL) +int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm); -int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator, - ucx_map_coder decoder, void* decdata); -/* encoders shall provide null terminated strings*/ -int ucx_map_store_enc(UcxMap *map, FILE *f, - ucx_map_coder encoder, void* encdata); #ifdef __cplusplus }
--- a/src/server/ucx/mempool.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/mempool.c Tue Jul 16 12:14:13 2013 +0200 @@ -112,7 +112,7 @@ return newm + sizeof(ucx_destructor); } } - fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", + fprintf(stderr, "FATAL: 0x%08"PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", (intptr_t)ptr, (intptr_t)pool); exit(1); } else { @@ -120,14 +120,37 @@ } } -void ucx_mempool_free(UcxMempool *pool) { +void ucx_mempool_free(UcxMempool *pool, void *ptr) { + ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor)); + for(size_t i=0 ; i<pool->ndata ; i++) { + if(chunk == pool->data[i]) { + if(chunk->destructor != NULL) { + chunk->destructor(&chunk->c); + } + free(chunk); + size_t last_index = pool->ndata - 1; + if(i != last_index) { + pool->data[i] = pool->data[last_index]; + } + pool->ndata--; + return; + } + } + fprintf(stderr, "FATAL: 0x%08"PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", + (intptr_t)ptr, (intptr_t)pool); + exit(1); +} + +void ucx_mempool_destroy(UcxMempool *pool) { ucx_memchunk *chunk; for(size_t i=0 ; i<pool->ndata ; i++) { chunk = (ucx_memchunk*) pool->data[i]; - if(chunk->destructor != NULL) { - chunk->destructor(&chunk->c); + if(chunk) { + if(chunk->destructor != NULL) { + chunk->destructor(&chunk->c); + } + free(chunk); } - free(chunk); } free(pool->data); free(pool); @@ -145,3 +168,17 @@ rd->ptr = ptr; ucx_mempool_set_destr(rd, ucx_mempool_shared_destr); } + +UcxAllocator* ucx_mempool_allocator(UcxMempool *pool) { + UcxAllocator *allocator = (UcxAllocator*)ucx_mempool_malloc( + pool, sizeof(UcxAllocator)); + if(!allocator) { + return NULL; + } + allocator->malloc = (ucx_allocator_malloc)ucx_mempool_malloc; + allocator->calloc = (ucx_allocator_calloc)ucx_mempool_calloc; + allocator->realloc = (ucx_allocator_realloc)ucx_mempool_realloc; + allocator->free = (ucx_allocator_free)ucx_mempool_free; + allocator->pool = pool; + return allocator; +}
--- a/src/server/ucx/mempool.h Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/mempool.h Tue Jul 16 12:14:13 2013 +0200 @@ -45,10 +45,6 @@ size_t size; } UcxMempool; -#define UCX_ALLOCATOR_MEMPOOL(pool) {pool, \ - (ucx_allocator_malloc) ucx_mempool_malloc, \ - (ucx_allocator_calloc) ucx_mempool_calloc, \ - (ucx_allocator_realloc) ucx_mempool_realloc} #define ucx_mempool_new_default() ucx_mempool_new(16) UcxMempool *ucx_mempool_new(size_t n); @@ -57,12 +53,14 @@ void *ucx_mempool_malloc(UcxMempool *pool, size_t n); void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize); void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n); +void ucx_mempool_free(UcxMempool *pool, void *ptr); -void ucx_mempool_free(UcxMempool *pool); +void ucx_mempool_destroy(UcxMempool *pool); void ucx_mempool_set_destr(void *ptr, ucx_destructor func); void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr); +UcxAllocator* ucx_mempool_allocator(UcxMempool *pool); #ifdef __cplusplus }
--- a/src/server/ucx/objs.mk Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/objs.mk Tue Jul 16 12:14:13 2013 +0200 @@ -38,6 +38,9 @@ UCXOBJ += allocator.o UCXOBJ += utils.o UCXOBJ += buffer.o +UCXOBJ += test.o +UCXOBJ += properties.o +UCXOBJ += logging.o UCXOBJS = $(UCXOBJ:%=$(UCX_OBJPRE)%) UCXSOURCE = $(UCXOBJ:%.o=ucx/%.c)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/ucx/properties.c Tue Jul 16 12:14:13 2013 +0200 @@ -0,0 +1,265 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "properties.h" + +UcxProperties *ucx_properties_new() { + UcxProperties *parser = (UcxProperties*)malloc( + sizeof(UcxProperties)); + if(!parser) { + return NULL; + } + + parser->buffer = NULL; + parser->buflen = 0; + parser->pos = 0; + parser->tmp = NULL; + parser->tmplen = 0; + parser->tmpcap = 0; + parser->error = 0; + parser->delimiter = '='; + parser->comment1 = '#'; + parser->comment2 = 0; + parser->comment3 = 0; + + return parser; +} + +void ucx_properties_free(UcxProperties *parser) { + if(parser->tmp) { + free(parser->tmp); + } + free(parser); +} + +void ucx_properties_fill(UcxProperties *parser, char *buf, size_t len) { + parser->buffer = buf; + parser->buflen = len; + parser->pos = 0; +} + +static void parser_tmp_append(UcxProperties *parser, char *buf, size_t len) { + if(parser->tmpcap - parser->tmplen < len) { + size_t newcap = parser->tmpcap + len + 64; + parser->tmp = (char*)realloc(parser->tmp, newcap); + parser->tmpcap = newcap; + } + memcpy(parser->tmp + parser->tmplen, buf, len); + parser->tmplen += len; +} + +int ucx_properties_next(UcxProperties *parser, sstr_t *name, sstr_t *value) { + if(parser->tmplen > 0) { + char *buf = parser->buffer + parser->pos; + size_t len = parser->buflen - parser->pos; + sstr_t str = sstrn(buf, len); + sstr_t nl = sstrchr(str, '\n'); + if(nl.ptr) { + size_t newlen = (size_t)(nl.ptr - buf) + 1; + parser_tmp_append(parser, buf, newlen); + // the tmp buffer contains exactly one line now + + char *orig_buf = parser->buffer; + size_t orig_len = parser->buflen; + + parser->buffer = parser->tmp; + parser->buflen = parser->tmplen; + parser->pos = 0; + parser->tmp = NULL; + parser->tmpcap = 0; + parser->tmplen = 0; + // run ucx_properties_next with the tmp buffer as main buffer + int ret = ucx_properties_next(parser, name, value); + + // restore original buffer + parser->tmp = parser->buffer; + parser->buffer = orig_buf; + parser->buflen = orig_len; + parser->pos = newlen; + + /* + * if ret == 0 the tmp buffer contained just space or a comment + * we parse again with the original buffer to get a name/value + * or a new tmp buffer + */ + return ret ? ret : ucx_properties_next(parser, name, value); + } else { + parser_tmp_append(parser, buf, len); + return 0; + } + } else if(parser->tmp) { + free(parser->tmp); + parser->tmp = NULL; + } + + char comment1 = parser->comment1; + char comment2 = parser->comment2; + char comment3 = parser->comment3; + char delimiter = parser->delimiter; + + // get one line and parse it + while(parser->pos < parser->buflen) { + char *buf = parser->buffer + parser->pos; + size_t len = parser->buflen - parser->pos; + + /* + * First we check if we have at least one line. We also get indices of + * delimiter and comment chars + */ + size_t delimiter_index = 0; + size_t comment_index = 0; + int has_comment = 0; + + size_t i = 0; + char c = 0; + for(;i<len;i++) { + c = buf[i]; + if(c == comment1 || c == comment2 || c == comment3) { + if(comment_index == 0) { + comment_index = i; + has_comment = 1; + } + } else if(c == delimiter) { + if(delimiter_index == 0 && !has_comment) { + delimiter_index = i; + } + } else if(c == '\n') { + break; + } + } + + if(c != '\n') { + // we don't have enough data for a line + // store remaining bytes in temporary buffer for next round + parser->tmpcap = len + 128; + parser->tmp = (char*)malloc(parser->tmpcap); + parser->tmplen = len; + memcpy(parser->tmp, buf, len); + return 0; + } + + sstr_t line = has_comment ? sstrn(buf, comment_index) : sstrn(buf, i); + // check line + if(delimiter_index == 0) { + line = sstrtrim(line); + if(line.length != 0) { + parser->error = 1; + } + } else { + sstr_t n = sstrn(buf, delimiter_index); + sstr_t v = sstrn(buf+delimiter_index+1, i-delimiter_index-1); + n = sstrtrim(n); + v = sstrtrim(v); + if(n.length != 0 || v.length != 0) { + *name = n; + *value = v; + parser->pos += i + 1; + return 1; + } else { + parser->error = 1; + } + } + + parser->pos += i + 1; + } + + return 0; +} + +int ucx_properties2map(UcxProperties *parser, UcxMap *map) { + sstr_t name; + sstr_t value; + while(ucx_properties_next(parser, &name, &value)) { + name = sstrdup_alloc(map->allocator, name); + if(!name.ptr) { + return 1; + } + value = sstrdup_alloc(map->allocator, value); + if(!value.ptr) { + map->allocator->free(map->allocator->pool, value.ptr); + return 1; + } + if(ucx_map_sstr_put(map, name, value.ptr)) { + map->allocator->free(map->allocator->pool, name.ptr); + map->allocator->free(map->allocator->pool, value.ptr); + return 1; + } + } + if(parser->error) { + return 1; + } else { + return 0; + } +} + +int ucx_properties_load(UcxMap *map, FILE *file) { + UcxProperties *parser = ucx_properties_new(); + if(!parser || !map || !file) { + return 1; + } + + int error = 0; + size_t r; + char buf[1024]; + while((r = fread(buf, 1, 1024, file)) != 0) { + ucx_properties_fill(parser, buf, r); + if(ucx_properties2map(parser, map)) { + error = 1; + break; + } + } + + ucx_properties_free(parser); + return error; +} + +int ucx_properties_store(UcxMap *map, FILE *file) { + UcxMapIterator iter = ucx_map_iterator(map); + char *v; + sstr_t value; + size_t written; + + UCX_MAP_FOREACH(k, v, iter) { + value = sstr(v); + + written = 0; + written += fwrite(k.data, 1, k.len, file); + written += fwrite(" = ", 1, 3, file); + written += fwrite(value.ptr, 1, value.length, file); + written += fwrite("\n", 1, 1, file); + + if (written != k.len + value.length + 4) return 1; + } + + return 0; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/ucx/properties.h Tue Jul 16 12:14:13 2013 +0200 @@ -0,0 +1,68 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PROPERTIES_H +#define PROPERTIES_H + +#include "ucx.h" +#include "map.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *buffer; + size_t buflen; + size_t pos; + char *tmp; + size_t tmplen; + size_t tmpcap; + int error; + char delimiter; + char comment1; + char comment2; + char comment3; +} UcxProperties; + + +UcxProperties *ucx_properties_new(); +void ucx_properties_free(UcxProperties *parser); +void ucx_properties_fill(UcxProperties *parser, char *buf, size_t len); +int ucx_properties_next(UcxProperties *parser, sstr_t *name, sstr_t *value); +int ucx_properties2map(UcxProperties *parser, UcxMap *map); + +int ucx_properties_load(UcxMap *map, FILE *file); +int ucx_properties_store(UcxMap *map, FILE *file); + +#ifdef __cplusplus +} +#endif + +#endif /* PROPERTIES_H */ +
--- a/src/server/ucx/string.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/string.c Tue Jul 16 12:14:13 2013 +0200 @@ -31,6 +31,7 @@ #include <stdarg.h> #include "string.h" +#include "allocator.h" sstr_t sstr(char *s) { sstr_t string; @@ -106,6 +107,18 @@ return new_sstr; } +sstr_t sstrchr(sstr_t s, int c) { + for(size_t i=0;i<s.length;i++) { + if(s.ptr[i] == c) { + return sstrsubs(s, i); + } + } + sstr_t n; + n.ptr = NULL; + n.length = 0; + return n; +} + sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n) { if (d.length == 0) { return NULL; @@ -168,16 +181,30 @@ sstr_t sstrdup(sstr_t s) { sstr_t newstring; newstring.ptr = (char*) malloc(s.length + 1); - newstring.length = 0; if (newstring.ptr) { newstring.length = s.length; newstring.ptr[newstring.length] = 0; - + memcpy(newstring.ptr, s.ptr, s.length); } else { newstring.length = 0; } + + return newstring; +} +sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s) { + sstr_t newstring; + newstring.ptr = (char*)allocator->malloc(allocator->pool, s.length + 1); + if (newstring.ptr) { + newstring.length = s.length; + newstring.ptr[newstring.length] = 0; + + memcpy(newstring.ptr, s.ptr, s.length); + } else { + newstring.length = 0; + } + return newstring; } @@ -218,7 +245,6 @@ return newstr; } - // webserver extension int sstr_startswith(sstr_t string, sstr_t cmp) {
--- a/src/server/ucx/string.h Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/ucx/string.h Tue Jul 16 12:14:13 2013 +0200 @@ -30,6 +30,7 @@ #define _SSTRING_H #include "ucx.h" +#include "allocator.h" #include "mempool.h" #include "../public/nsapi.h" #include <stddef.h> @@ -94,6 +95,11 @@ sstr_t sstrsubsl(sstr_t s, size_t start, size_t length); /* + * + */ +sstr_t sstrchr(sstr_t s, int c); + +/* * splits s into n parts * * s the string to split @@ -114,13 +120,14 @@ int sstrcmp(sstr_t s1, sstr_t s2); sstr_t sstrdup(sstr_t s); +sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s); sstr_t sstrtrim(sstr_t string); // webserver extension int sstr_startswith(sstr_t string, sstr_t cmp); sstr_t sstrdup_mp(UcxMempool *pool, sstr_t s); -sstr_t sstrdup_pool(pool_handle_t *pool, sstr_t s); +sstr_t sstrdup_pool(pool_handle_t *pool, sstr_t s); #ifdef __cplusplus }
--- a/src/server/webdav/webdav.c Thu Jul 11 14:21:23 2013 +0200 +++ b/src/server/webdav/webdav.c Tue Jul 16 12:14:13 2013 +0200 @@ -316,7 +316,7 @@ sbuf_puts(out, "<D:multistatus"); UcxMapIterator nsiter = ucx_map_iterator(davrq->nsmap->map); XmlNs *ns; - UCX_MAP_FOREACH(ns, nsiter) { + UCX_MAP_FOREACH(key, ns, nsiter) { sbuf_puts(out, " xmlns:"); sbuf_puts(out, ns->prefix); sbuf_puts(out, "=\""); @@ -422,7 +422,7 @@ sbuf_puts(davrq->out, "<D:multistatus"); UcxMapIterator nsiter = ucx_map_iterator(davrq->nsmap->map); XmlNs *ns; - UCX_MAP_FOREACH(ns, nsiter) { + UCX_MAP_FOREACH(key, ns, nsiter) { sbuf_puts(davrq->out, " xmlns:"); sbuf_puts(davrq->out, ns->prefix); sbuf_puts(davrq->out, "=\""); @@ -791,7 +791,7 @@ UcxMapIterator iter = ucx_map_iterator(propstat->map); UcxDlist *proplist; - UCX_MAP_FOREACH(proplist, iter) { + UCX_MAP_FOREACH(key, proplist, iter) { if(proplist) { sbuf_puts(out, "<D:propstat>\n<D:prop>\n");