[lxc-devel] [patch 2/7] add variables resolution interface

Andrian Nord nightnord at gmail.com
Mon Dec 7 10:30:47 UTC 2009


Called from few places (from config file and from futher-comming mount
interface), so it's dedicated to it's own separate file.

It's assuming that user is a smart one, and is not trying to use
undefined variable (only rootfs by now). Otherwise he will get '(null)'
as result. That's done due to universal nature of parser. All checks
should be done inside handlers, if they are trying to somehow operate on
requested values.

I'm not using buffer allocation and reallocating string all the time, as
actual length of expanded string could be bigger as maximum
configuration file line length.

Here, how it could be improved: if there would be a set of functions
filling and dumping values to some kind of complete config structure
from any source (confile, command arguments, network, command interface,
any other..,), it will allow us, in connection with shared with confile
string->config.element mapping, to use this functions for universal
expanding of any existing option, just by calling corresponding
config-value-dump function, without any additional 'handlers'. If I'll
have some more time, i'll post my complete vision of that configuration
logic into sf bugzilla.

Signed-off-by: Andrian Nord <NightNord at gmail.com>

diff --git a/src/lxc/variables.c b/src/lxc/variables.c
new file mode 100644
index 0000000..5a53d9c
--- /dev/null
+++ b/src/lxc/variables.c
@@ -0,0 +1,218 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ * File by:
+ * Andrian Nord <nightnord at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <lxc/log.h>
+#include <lxc/conf.h>
+
+#include "parse.h"
+#include "config.h"
+
+lxc_log_define(lxc_variables, lxc);
+
+static char *resolve_var_lxcpath(const char *, struct lxc_conf *);
+static char *resolve_lxc_name(const char *, struct lxc_conf *);
+static char *resolve_lxc_rootfs(const char *, struct lxc_conf *);
+
+typedef char *(*resolve_cb)(const char *, struct lxc_conf *);
+
+struct map {
+	char *key;
+	resolve_cb cb;
+};
+
+static struct map map[] = {
+	{ "var.lxcpath",	resolve_var_lxcpath	},
+	{ "lxc.name",		resolve_lxc_name	},
+	{ "lxc.rootfs",		resolve_lxc_rootfs	},
+};
+
+static const size_t map_size = sizeof(map)/sizeof(struct map);
+
+static const struct map *getmap(const char* key)
+{
+	int i;
+
+	for (i = 0; i < map_size; i++) {
+		if (strncmp(map[i].key, key, strlen(key)) == 0)
+			return &map[i];
+	}
+
+	return NULL;
+}
+
+static char *resolve_var_lxcpath(const char *key, struct lxc_conf *lxc_conf)
+{
+	char *lxcpath = LXCPATH;
+
+	return lxcpath;
+}
+
+static char *resolve_lxc_name(const char *key, struct lxc_conf *lxc_conf)
+{
+	return lxc_conf->name;
+}
+
+static char *resolve_lxc_rootfs(const char *key, struct lxc_conf *lxc_conf)
+{
+	return lxc_conf->rootfs;
+}
+
+static int lxc_resolve_variable(const char *key, char** value,
+							struct lxc_conf *conf)
+{
+	const struct map *map;
+
+	*value = NULL;
+
+	map = getmap(key);
+
+	if (!map)
+		return -1;
+
+	*value = map->cb(key, conf);
+
+	if (!value)
+		return -1;
+
+	return 0;
+}
+
+int lxc_resolve_variables(const char *string, char **result,
+						struct lxc_conf *lxc_conf)
+{
+	char *buffer;
+	char *var, *tmp, *skipped;
+	char *key, *key_end, *space;
+	char *value;
+
+	int ret = -1;
+
+	buffer = strdup(string);
+
+	if (!buffer) {
+		SYSERROR("failed to allocate memory");
+		goto out;
+	}
+
+	skipped = var = buffer;
+	*result = malloc(sizeof(char));
+
+	if (!*result) {
+		SYSERROR("failed to allocate memory for single character 0o");
+		goto fail;
+	}
+
+	**result = '\0';
+
+	while ((var = strstr(var, "$"))) {
+		if (var != buffer && *(var-1) == '\\') {
+			var++;
+
+			continue;
+		}
+
+		*var = '\0';
+		key = var + 1;
+		key_end = NULL;
+
+		if (*key == '{') {
+			key_end = strchr(key + 1, '}');
+
+			if (!key_end) {
+				ERROR("no closing '}' in '%s'", key);
+				goto fail;
+			}
+
+			*key = '\0';
+			*key_end = '\0';
+			key++;
+
+			space = "";
+		} else {
+			key_end = key + lxc_char_next_space(key, strlen(key));
+
+			if ( *key_end == ' ' )
+				space = " ";
+			else if ( *key_end == '\t' )
+				space = "\t";
+			else
+				space = "";
+
+			*key_end = '\0';
+		}
+
+		if (lxc_resolve_variable(key, &value, lxc_conf)) {
+			ERROR("variable '%s' not found", key);
+			goto fail;
+		}
+
+		if (!key_end) {
+			skipped = value;
+			break;
+		}
+
+		var = key_end + 1;
+
+		if (!asprintf(&tmp, "%s%s%s%s", *result,
+						skipped, value, space)) {
+			SYSERROR("failed to allocate memory");
+			goto fail;
+		}
+
+		free(*result);
+		*result = tmp;
+
+		skipped = var;
+	}
+
+	if (skipped != buffer) {
+		if (!asprintf(&tmp, "%s%s", *result, skipped)) {
+			SYSERROR("failed to allocate memory");
+			goto fail;
+		}
+
+		*result = tmp;
+	} else {
+		free(*result);
+
+		*result = buffer;
+		
+		return 0;
+	}
+
+	ret = 0;
+
+	goto out;
+
+fail:
+	free(*result);
+out:
+	free(buffer);
+	return ret;
+}
diff --git a/src/lxc/variables.h b/src/lxc/variables.h
new file mode 100644
index 0000000..0e8c450
--- /dev/null
+++ b/src/lxc/variables.h
@@ -0,0 +1,34 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ * File by:
+ * Andrian Nord <NightNord at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __variables_h
+#define __variables_h
+
+struct lxc_conf;
+
+extern int lxc_resolve_variables(const char* string, char** result,
+						struct lxc_conf *lxc_conf);
+
+#endif




More information about the lxc-devel mailing list