Пример #1
0
/* copy the variables to shm mem */
int cfg_shmize(void)
{
	cfg_group_t	*group;
	cfg_block_t	*block = NULL;
	int	size;

	if (!cfg_group) return 0;

	/* Let us allocate one memory block that
	will contain all the variables */
	for (	size=0, group = cfg_group;
		group;
		group=group->next
	) {
		size = ROUND_POINTER(size);
		group->offset = size;
		size += group->size;
	}

	block = (cfg_block_t*)shm_malloc(sizeof(cfg_block_t)+size-1);
	if (!block) {
		LOG(L_ERR, "ERROR: cfg_clone_str(): not enough shm memory\n");
		goto error;
	}
	memset(block, 0, sizeof(cfg_block_t)+size-1);
	cfg_block_size = size;

	/* copy the memory fragments to the single block */
	for (	group = cfg_group;
		group;
		group=group->next
	) {
		if (group->dynamic == 0) {
			/* clone the strings to shm mem */
			if (cfg_shmize_strings(group)) goto error;

			/* copy the values to the new block */
			memcpy(block->vars+group->offset, group->vars, group->size);
		} else {
			/* The group was declared with NULL values,
			 * we have to fix it up.
			 * The fixup function takes care about the values,
			 * it fills up the block */
			if (cfg_script_fixup(group, block->vars+group->offset)) goto error;

			/* Notify the drivers about the new config definition.
			 * Temporary set the group handle so that the drivers have a chance to
			 * overwrite the default values. The handle must be reset after this
			 * because the main process does not have a local configuration. */
			*(group->handle) = block->vars+group->offset;
			cfg_notify_drivers(group->name, group->name_len,
					group->mapping->def);
			*(group->handle) = NULL;
		}
	}
	/* try to fixup the selects that failed to be fixed-up previously */
	if (cfg_fixup_selects()) goto error;

	/* install the new config */
	cfg_install_global(block, NULL, NULL, NULL);
	cfg_shmized = 1;

	return 0;

error:
	if (block) shm_free(block);
	return -1;
}
Пример #2
0
/* allocates memory for a new config script variable
 * The value of the variable is not set!
 */
cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type,
					char *descr)
{
	cfg_group_t	*group;
	cfg_script_var_t	*var;
	int	gname_len, vname_len, descr_len;

	LOG(L_DBG, "DEBUG: new_cfg_script_var(): declaring %s.%s\n", gname, vname);

	if (cfg_shmized) {
		LOG(L_ERR, "ERROR: new_cfg_script_var(): too late variable declaration, "
			"the config has been already shmized\n");
		return NULL;
	}

	gname_len = strlen(gname);
	vname_len = strlen(vname);
	/* the group may have been already declared */
	group = cfg_lookup_group(gname, gname_len);
	if (group) {
		if (group->dynamic == CFG_GROUP_STATIC) {
			/* the group has been already declared by a module or by the core */
			LOG(L_ERR, "ERROR: new_cfg_script_var(): "
				"configuration group has been already declared: %s\n",
				gname);
			return NULL;
		}
		/* the dynamic or empty group is found */
		/* verify that the variable does not exist */
		for (	var = (cfg_script_var_t *)group->vars;
			var;
			var = var->next
		) {
			if ((var->name_len == vname_len) &&
			(memcmp(var->name, vname, vname_len) == 0)) {
				LOG(L_ERR, "ERROR: new_cfg_script_var(): variable already exists: %s.%s\n",
						gname, vname);
				return NULL;
			}
		}
		if (group->dynamic == CFG_GROUP_UNKNOWN)
			group->dynamic = CFG_GROUP_DYNAMIC;

	} else {
		/* create a new group with NULL values, we will fix it later,
		when all the variables are known */
		group = cfg_new_group(gname, gname_len,
					0 /* num */, NULL /* mapping */,
					NULL /* vars */, 0 /* size */, NULL /* handle */);
					
		if (!group) goto error;
		group->dynamic = CFG_GROUP_DYNAMIC;
	}

	switch (type) {
	case CFG_VAR_INT:
		group->size = ROUND_INT(group->size);
		group->size += sizeof(int);
		break;

	case CFG_VAR_STR:
		group->size = ROUND_POINTER(group->size);
		group->size += sizeof(str);
		break;

	default:
		LOG(L_ERR, "ERROR: new_cfg_script_var(): unsupported variable type\n");
		return NULL;
	}

	group->num++;
	if (group->num > CFG_MAX_VAR_NUM) {
		LOG(L_ERR, "ERROR: new_cfg_script_var(): too many variables (%d) within a single group,"
			" the limit is %d. Increase CFG_MAX_VAR_NUM, or split the group into multiple"
			" definitions.\n",
			group->num, CFG_MAX_VAR_NUM);
		return NULL;
	}

	var = (cfg_script_var_t *)pkg_malloc(sizeof(cfg_script_var_t));
	if (!var) goto error;
	memset(var, 0, sizeof(cfg_script_var_t));
	var->type = type;

	/* add the variable to the group */
	var->next = (cfg_script_var_t *)(void *)group->vars;
	group->vars = (char *)(void *)var;

	/* clone the name of the variable */
	var->name = (char *)pkg_malloc(sizeof(char) * (vname_len + 1));
	if (!var->name) goto error;
	memcpy(var->name, vname, vname_len + 1);
	var->name_len = vname_len;

	if (descr) {
		/* save the description */
		descr_len = strlen(descr);
		var->descr = (char *)pkg_malloc(sizeof(char) * (descr_len + 1));
		if (!var->descr) goto error;
		memcpy(var->descr, descr, descr_len + 1);
	}

	return var;

error:
	LOG(L_ERR, "ERROR: new_cfg_script_var(): not enough memory\n");
	return NULL;
}
Пример #3
0
/* copy the variables to shm mem */
int cfg_shmize(void)
{
	cfg_group_t	*group;
	cfg_block_t	*block = NULL;
	int	size;

	if (!cfg_group) return 0;

	/* Let us allocate one memory block that
	 * will contain all the variables + meta-data
	 * in the following form:
	 * |-----------|
	 * | meta-data | <- group A: meta_offset
	 * | variables | <- group A: var_offset
	 * |-----------|
	 * | meta-data | <- group B: meta_offset
	 * | variables | <- group B: var_offset
	 * |-----------|
	 * |    ...    |
	 * |-----------|
	 *
	 * The additional array for the multiple values
	 * of the same variable is linked to the meta-data.
	 */
	for (	size=0, group = cfg_group;
		group;
		group=group->next
	) {
		size = ROUND_POINTER(size);
		group->meta_offset = size;
		size += sizeof(cfg_group_meta_t);

		size = ROUND_POINTER(size);
		group->var_offset = size;
		size += group->size;
	}

	block = (cfg_block_t*)shm_malloc(sizeof(cfg_block_t)+size-1);
	if (!block) {
		LOG(L_ERR, "ERROR: cfg_shmize(): not enough shm memory\n");
		goto error;
	}
	memset(block, 0, sizeof(cfg_block_t)+size-1);
	cfg_block_size = size;

	/* copy the memory fragments to the single block */
	for (	group = cfg_group;
		group;
		group=group->next
	) {
		if (group->dynamic == CFG_GROUP_STATIC) {
			/* clone the strings to shm mem */
			if (cfg_shmize_strings(group)) goto error;

			/* copy the values to the new block */
			memcpy(CFG_GROUP_DATA(block, group), group->vars, group->size);
		} else if (group->dynamic == CFG_GROUP_DYNAMIC) {
			/* The group was declared with NULL values,
			 * we have to fix it up.
			 * The fixup function takes care about the values,
			 * it fills up the block */
			if (cfg_script_fixup(group, CFG_GROUP_DATA(block, group))) goto error;

			/* Notify the drivers about the new config definition.
			 * Temporary set the group handle so that the drivers have a chance to
			 * overwrite the default values. The handle must be reset after this
			 * because the main process does not have a local configuration. */
			*(group->handle) = CFG_GROUP_DATA(block, group);
			cfg_notify_drivers(group->name, group->name_len,
					group->mapping->def);
			*(group->handle) = NULL;
		} else {
			LOG(L_ERR, "ERROR: cfg_shmize(): Configuration group is declared "
					"without any variable: %.*s\n",
					group->name_len, group->name);
			goto error;
		}

		/* Create the additional group instances with applying
		the temporary list. */
		if (apply_add_var_list(block, group))
			goto error;
	}

	/* try to fixup the selects that failed to be fixed-up previously */
	if (cfg_fixup_selects()) goto error;

	/* install the new config */
	cfg_install_global(block, NULL, NULL, NULL);
	cfg_shmized = 1;

	return 0;

error:
	if (block) shm_free(block);
	return -1;
}
Пример #4
0
/* fix-up the dynamically declared group:
 *  - allocate memory for the arrays
 *  - set the values within the memory block
 */
int cfg_script_fixup(cfg_group_t *group, unsigned char *block)
{
	cfg_mapping_t		*mapping = NULL;
	cfg_def_t		*def = NULL;
	void			**handle = NULL;
	int			i, offset;
	cfg_script_var_t	*script_var, *script_var2;
	str			s;

	mapping = (cfg_mapping_t *)pkg_malloc(sizeof(cfg_mapping_t)*group->num);
	if (!mapping) goto error;
	memset(mapping, 0, sizeof(cfg_mapping_t)*group->num);

	/* The variable definition array must look like as if it was declared
	 * in C code, thus, add an additional slot at the end with NULL values */
	def = (cfg_def_t *)pkg_malloc(sizeof(cfg_def_t)*(group->num + 1));
	if (!def) goto error;
	memset(def, 0, sizeof(cfg_def_t)*(group->num + 1));

	/* fill the definition and the mapping arrays */
	offset = 0;
	for (	i = 0, script_var = (cfg_script_var_t *)group->vars;
		script_var;
		i++, script_var = script_var->next
	) {
		/* there has been already memory allocated for the name */
		def[i].name = script_var->name;
		def[i].type = script_var->type | (script_var->type << CFG_INPUT_SHIFT);
		def[i].descr = script_var->descr;
		def[i].min = script_var->min;
		def[i].max = script_var->max;

		mapping[i].def = &(def[i]);
		mapping[i].name_len = script_var->name_len;
		mapping[i].pos = i;

		switch (script_var->type) {
		case CFG_VAR_INT:
			offset = ROUND_INT(offset);
			mapping[i].offset = offset;

			*(int *)(block + offset) = script_var->val.i;

			offset += sizeof(int);
			break;

		case CFG_VAR_STR:
			offset = ROUND_POINTER(offset);
			mapping[i].offset = offset;

			if (cfg_clone_str(&(script_var->val.s), &s)) goto error;
			memcpy(block + offset, &s, sizeof(str));
			mapping[i].flag |= cfg_var_shmized;

			offset += sizeof(str);
			break;
		}
	}

	/* allocate a handle even if it will not be used to
	directly access the variable, like handle->variable
	cfg_get_* functions access the memory block via the handle
	to make sure that it is always safe, thus, it must be created */
	handle = (void **)pkg_malloc(sizeof(void *));
	if (!handle) goto error;
	*handle = NULL;
	group->handle = handle;

	group->mapping = mapping;

	/* everything went fine, we can free the temporary list */
	script_var = (cfg_script_var_t *)group->vars;
	group->vars = NULL;
	while (script_var) {
		script_var2 = script_var->next;
		if ((script_var->type == CFG_VAR_STR) && script_var->val.s.s)
			pkg_free(script_var->val.s.s);
		pkg_free(script_var);
		script_var = script_var2;
	}

	return 0;

error:
	if (mapping) pkg_free(mapping);
	if (def) pkg_free(def);
	if (handle) pkg_free(handle);

	LOG(L_ERR, "ERROR: cfg_script_fixup(): not enough memory\n");
	return -1;
}