lxc_list_init(&new->caps);
lxc_list_init(&new->keepcaps);
lxc_list_init(&new->id_map);
+ lxc_list_init(&new->includes);
for (i=0; i<NUM_LXC_HOOKS; i++)
lxc_list_init(&new->hooks[i]);
lxc_list_init(&new->groups);
free(conf->saved_nics);
}
+static inline void lxc_clear_includes(struct lxc_conf *conf)
+{
+ struct lxc_list *it,*next;
+
+ lxc_list_for_each_safe(it, &conf->includes, next) {
+ lxc_list_del(it);
+ free(it->elem);
+ free(it);
+ }
+}
+
void lxc_conf_free(struct lxc_conf *conf)
{
if (!conf)
lxc_clear_saved_nics(conf);
lxc_clear_idmaps(conf);
lxc_clear_groups(conf);
+ lxc_clear_includes(conf);
free(conf);
}
struct lxc_conf {
int is_execute;
+ bool unexpanded;
char *fstab;
int tty;
int pts;
/* set to true when rootfs has been setup */
bool rootfs_setup;
+
+ /* list of included files */
+ struct lxc_list includes;
};
int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf,
return config_path_item(&lxc_conf->console.path, value);
}
+static int add_include_file(const char *fname, struct lxc_conf *lxc_conf)
+{
+ struct lxc_list *list;
+ char *v;
+ int len = strlen(fname);
+
+ list = malloc(sizeof(*list));
+ if (!list)
+ return -1;
+ lxc_list_init(list);
+ v = malloc(len+1);
+ if (!v) {
+ free(list);
+ return -1;
+ }
+ strncpy(v, fname, len);
+ v[len] = '\0';
+ list->elem = v;
+ lxc_list_add_tail(&lxc_conf->includes, list);
+ return 0;
+}
+
static int config_includefile(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
- return lxc_config_read(value, lxc_conf);
+ if (lxc_conf->unexpanded)
+ return add_include_file(value, lxc_conf);
+ return lxc_config_read(value, lxc_conf, NULL);
}
static int config_rootfs(const char *key, const char *value,
return parse_line(buffer, conf);
}
-int lxc_config_read(const char *file, struct lxc_conf *conf)
+int lxc_config_read(const char *file, struct lxc_conf *conf, struct lxc_conf *unexp_conf)
{
+ int ret;
+
if( access(file, R_OK) == -1 ) {
return -1;
}
if( ! conf->rcfile ) {
conf->rcfile = strdup( file );
}
- return lxc_file_for_each_line(file, parse_line, conf);
+ ret = lxc_file_for_each_line(file, parse_line, conf);
+ if (ret)
+ return ret;
+ if (!unexp_conf)
+ return 0;
+ if (!unexp_conf->rcfile) {
+ unexp_conf->rcfile = strdup( file );
+ }
+
+ return lxc_file_for_each_line(file, parse_line, unexp_conf);
}
int lxc_config_define_add(struct lxc_list *defines, char* arg)
struct lxc_list *it;
int i;
+ lxc_list_for_each(it, &c->includes) {
+ fprintf(fout, "lxc.include = %s\n", (char *)it->elem);
+ }
+
if (c->fstab)
fprintf(fout, "lxc.mount = %s\n", c->fstab);
lxc_list_for_each(it, &c->mount_list) {
extern struct lxc_config_t *lxc_getconfig(const char *key);
extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, char *retv, int inlen);
extern int lxc_listconfigs(char *retv, int inlen);
-extern int lxc_config_read(const char *file, struct lxc_conf *conf);
+extern int lxc_config_read(const char *file, struct lxc_conf *conf, struct lxc_conf *unexp_conf);
extern int lxc_config_define_add(struct lxc_list *defines, char* arg);
extern int lxc_config_define_load(struct lxc_list *defines,
return 1;
}
- if (rcfile && lxc_config_read(rcfile, conf)) {
+ if (rcfile && lxc_config_read(rcfile, conf, NULL)) {
ERROR("failed to read configuration file");
return 1;
}
lxc_conf_free(c->lxc_conf);
c->lxc_conf = NULL;
}
+ if (c->lxc_unexp_conf) {
+ lxc_conf_free(c->lxc_unexp_conf);
+ c->lxc_unexp_conf = NULL;
+ }
if (c->config_path) {
free(c->config_path);
c->config_path = NULL;
{
if (!c->lxc_conf)
c->lxc_conf = lxc_conf_init();
- if (c->lxc_conf && !lxc_config_read(fname, c->lxc_conf))
+ if (!c->lxc_unexp_conf) {
+ c->lxc_unexp_conf = lxc_conf_init();
+ if (c->lxc_unexp_conf)
+ c->lxc_unexp_conf->unexpanded = true;
+ }
+ if (c->lxc_conf && c->lxc_unexp_conf &&
+ !lxc_config_read(fname, c->lxc_conf,
+ c->lxc_unexp_conf))
return true;
return false;
}
static void lxcapi_clear_config(struct lxc_container *c)
{
- if (c && c->lxc_conf) {
- lxc_conf_free(c->lxc_conf);
- c->lxc_conf = NULL;
+ if (c) {
+ if (c->lxc_conf) {
+ lxc_conf_free(c->lxc_conf);
+ c->lxc_conf = NULL;
+ }
+ if (c->lxc_unexp_conf) {
+ lxc_conf_free(c->lxc_unexp_conf);
+ c->lxc_unexp_conf = NULL;
+ }
}
}
/* reload config to get the rootfs */
lxc_conf_free(c->lxc_conf);
c->lxc_conf = NULL;
+ c->lxc_unexp_conf = NULL;
if (!load_config_locked(c, c->configfile))
goto out_unlock;
fout = fopen(alt_file, "w");
if (!fout)
goto out;
- write_config(fout, c->lxc_conf);
+ write_config(fout, c->lxc_unexp_conf);
fclose(fout);
ret = true;
if (!c->lxc_conf)
c->lxc_conf = lxc_conf_init();
- if (!c->lxc_conf)
+ if (!c->lxc_unexp_conf) {
+ c->lxc_unexp_conf = lxc_conf_init();
+ c->lxc_unexp_conf->unexpanded = true;
+ }
+ if (!c->lxc_conf || !c->lxc_unexp_conf)
return false;
config = lxc_getconfig(key);
if (!config)
return false;
+ if (config->cb(key, v, c->lxc_unexp_conf) != 0)
+ return false;
return (0 == config->cb(key, v, c->lxc_conf));
}
SYSERROR("open %s", newpath);
goto out;
}
- write_config(fout, c->lxc_conf);
+ write_config(fout, c->lxc_unexp_conf);
fclose(fout);
c->lxc_conf->rootfs.path = origroot;
*/
struct lxc_conf *lxc_conf;
+ /*!
+ * \private
+ * The non-common, unexpanded configuration. This includes the
+ * list of lxc.include files, and does not contain any
+ * individual configuration items from the include files.
+ * Anything coming from the container's own configuration file
+ * or from lxcapi_set_config_item() does get added here.
+ */
+ struct lxc_conf *lxc_unexp_conf;
+
// public fields
/*! Human-readable string representing last error */
char *error_string;