Example #1
0
/* clear values and optionally requests from property context
 *  ctx      -- property context
 *  requests -- 0 = don't clear requests, 1 = clear requests
 */
void prop_clear(struct propctx *ctx, int requests) 
{
    struct proppool *new_pool, *tmp;
    unsigned i;

    /* We're going to need a new proppool once we reset things */
    new_pool = alloc_proppool(ctx->mem_base->size +
			      (ctx->used_values+1) * sizeof(struct propval));
    if (new_pool == NULL) {
        _sasl_log(NULL, SASL_LOG_ERR, "failed to allocate memory\n");
        exit(1);
    }

    if(requests) {
	/* We're wiping the whole shebang */
	ctx->used_values = 0;
    } else {
	/* Need to keep around old requets */
	struct propval *new_values = (struct propval *)new_pool->data;
	for(i=0; i<ctx->used_values; i++) {
	    new_values[i].name = ctx->values[i].name;
	}
    }

    while(ctx->mem_base) {
	tmp = ctx->mem_base;
	ctx->mem_base = tmp->next;
	sasl_FREE(tmp);
    }
    
    /* Update allocation-related metadata */
    ctx->allocated_values = ctx->used_values+1;
    new_pool->unused =
	new_pool->size - (ctx->allocated_values * sizeof(struct propval));

    /* Setup pointers for the values array */
    ctx->values = (struct propval *)new_pool->data;
    ctx->prev_val = NULL;

    /* Setup the pools */
    ctx->mem_base = ctx->mem_cur = new_pool;

    /* Reset list_end and data_end for the new memory pool */
    ctx->list_end =
	(char **)((char *)ctx->mem_base->data + ctx->allocated_values * sizeof(struct propval));
    ctx->data_end = (char *)ctx->mem_base->data + ctx->mem_base->size;

    return;
}
Example #2
0
static int prop_init(struct propctx *ctx, unsigned estimate) 
{
    const unsigned VALUES_SIZE = PROP_DEFAULT * sizeof(struct propval);

    ctx->mem_base = alloc_proppool(VALUES_SIZE + estimate);
    if(!ctx->mem_base) return SASL_NOMEM;

    ctx->mem_cur = ctx->mem_base;

    ctx->values = (struct propval *)ctx->mem_base->data;
    ctx->mem_base->unused = ctx->mem_base->size - VALUES_SIZE;
    ctx->allocated_values = PROP_DEFAULT;
    ctx->used_values = 0;

    ctx->data_end = ctx->mem_base->data + ctx->mem_base->size;
    ctx->list_end = (char **)(ctx->mem_base->data + VALUES_SIZE);

    ctx->prev_val = NULL;

    return SASL_OK;
}
Example #3
0
/* add a property value to the context
 *  ctx    -- context from prop_new()/prop_request()
 *  name   -- name of property to which value will be added
 *            if NULL, add to the same name as previous prop_set/setvals call
 *  value  -- a value for the property; will be copied into context
 *            if NULL, remove existing values
 *  vallen -- length of value, if <= 0 then strlen(value) will be used
 */
int prop_set(struct propctx *ctx, const char *name,
	     const char *value, int vallen)
{
    struct propval *cur;

    if(!ctx) return SASL_BADPARAM;
    if(!name && !ctx->prev_val) return SASL_BADPARAM; 

    if(name) {
	struct propval *val;

	ctx->prev_val = NULL;
	
	for(val = ctx->values; val->name; val++) {
	    if(!strcmp(name,val->name)){
		ctx->prev_val = val;
		break;
	    }
	}

	/* Couldn't find it! */
	if(!ctx->prev_val) return SASL_BADPARAM;
    }

    cur = ctx->prev_val;

    if(name) /* New Entry */ {
	unsigned nvalues = 1; /* 1 for NULL entry */
	const char **old_values = NULL;
	char **tmp, **tmp2;
	size_t size;
	
	if(cur->values) {

	    if(!value) {
		/* If we would be adding a null value, then we are done */
		return SASL_OK;
	    }

	    old_values = cur->values;
	    tmp = (char **)cur->values;
	    while(*tmp) {
		nvalues++;
		tmp++;
	    }

	}

	if(value) {
	    nvalues++; /* for the new value */
	}

	size = nvalues * sizeof(char*);

	if(size > ctx->mem_cur->unused) {
	    size_t needed;

	    for(needed = ctx->mem_cur->size * 2; needed < size; needed *= 2);

	    /* Allocate a new proppool */
	    ctx->mem_cur->next = alloc_proppool(needed);
	    if(!ctx->mem_cur->next) return SASL_NOMEM;

	    ctx->mem_cur = ctx->mem_cur->next;

	    ctx->list_end = (char **)ctx->mem_cur->data;
	    ctx->data_end = ctx->mem_cur->data + needed;
	}

	/* Grab the memory */
	ctx->mem_cur->unused -= size;
	cur->values = (const char **)ctx->list_end;
	cur->values[nvalues - 1] = NULL;

	/* Finish updating the context */
	ctx->list_end = (char **)(cur->values + nvalues);

	/* If we don't have an actual value to fill in, we are done */
	if(!value)
	    return SASL_OK;

	tmp2 = (char **)cur->values;
	if(old_values) {
	    tmp = (char **)old_values;
	    
	    while(*tmp) {
		*tmp2 = *tmp;
		tmp++; tmp2++;
	    }
	}
	    
	/* Now allocate the last entry */
	if(vallen <= 0)
	    size = (size_t)(strlen(value) + 1);
	else
	    size = (size_t)(vallen + 1);

	if(size > ctx->mem_cur->unused) {
	    size_t needed;
	    
	    needed = ctx->mem_cur->size * 2;
	    
	    while(needed < size) {
		needed *= 2;
	    }

	    /* Allocate a new proppool */
	    ctx->mem_cur->next = alloc_proppool(needed);
	    if(!ctx->mem_cur->next) return SASL_NOMEM;

	    ctx->mem_cur = ctx->mem_cur->next;
	    ctx->list_end = (char **)ctx->mem_cur->data;
	    ctx->data_end = ctx->mem_cur->data + needed;
	}

	/* Update the data_end pointer */
	ctx->data_end -= size;
	ctx->mem_cur->unused -= size;

	/* Copy and setup the new value! */
	memcpy(ctx->data_end, value, size-1);
	ctx->data_end[size - 1] = '\0';
	cur->values[nvalues - 2] = ctx->data_end;

	cur->nvalues++;
	cur->valsize += ((unsigned) size - 1);
    } else /* Appending an entry */ {
	char **tmp;
	size_t size;

	/* If we are setting it to be NULL, we are done */
	if(!value) return SASL_OK;

	size = sizeof(char*);

	/* Is it in the current pool, and will it fit in the unused space? */
	if(size > ctx->mem_cur->unused &&
	    (void *)cur->values > (void *)(ctx->mem_cur->data) &&
	    (void *)cur->values < (void *)(ctx->mem_cur->data + ctx->mem_cur->size)) {
	    /* recursively call the not-fast way */
	    return prop_set(ctx, cur->name, value, vallen);
	}

	/* Note the invariant: the previous value list must be
	   at the top of the CURRENT pool at this point */

	/* Grab the memory */
	ctx->mem_cur->unused -= size;
	ctx->list_end++;

	*(ctx->list_end - 1) = NULL;
	tmp = (ctx->list_end - 2);

	/* Now allocate the last entry */
	if(vallen <= 0)
	    size = strlen(value) + 1;
	else
	    size = vallen + 1;

	if(size > ctx->mem_cur->unused) {
	    size_t needed;
	    
	    needed = ctx->mem_cur->size * 2;
	    
	    while(needed < size) {
		needed *= 2;
	    }

	    /* Allocate a new proppool */
	    ctx->mem_cur->next = alloc_proppool(needed);
	    if(!ctx->mem_cur->next) return SASL_NOMEM;

	    ctx->mem_cur = ctx->mem_cur->next;
	    ctx->list_end = (char **)ctx->mem_cur->data;
	    ctx->data_end = ctx->mem_cur->data + needed;
	}

	/* Update the data_end pointer */
	ctx->data_end -= size;
	ctx->mem_cur->unused -= size;

	/* Copy and setup the new value! */
	memcpy(ctx->data_end, value, size-1);
	ctx->data_end[size - 1] = '\0';
	*tmp = ctx->data_end;

	cur->nvalues++;
	cur->valsize += ((unsigned) size - 1);
    }
    
    return SASL_OK;
}