[lxc-devel] [PATCH] lxc-destroy: remove btrfs subvolumes

Serge Hallyn serge.hallyn at ubuntu.com
Tue Apr 28 13:31:05 UTC 2015


Doing this requires some btrfs functions from bdev to be used in
utils.c  Because utils.h is imported by lxc_init.c, I had to create
a new initutils.[ch] which are used by both lxc_init.c and utils.c
We could instead put the btrfs functions into utils.c, which would
be a shorter patch, but it really doesn't belong there.  So I went
the other way figuring there may be more such cases coming up of
fns in utils.c needing code from bdev.c which can't go into lxc_init.

Currently, if we detect a btrfs subvolume we just remove it.  The
st_dev on that dir is different, so we cannot detect if this is
bound in from another fs easily.  If we care, we should check
whether this is a mountpoint, this patch doesn't do that.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/Makefile.am |   4 +-
 src/lxc/bdev.c      |  11 +-
 src/lxc/bdev.h      |  26 -----
 src/lxc/initutils.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/initutils.h |  53 ++++++++++
 src/lxc/lxc_init.c  |   2 +-
 src/lxc/utils.c     | 292 +++------------------------------------------------
 src/lxc/utils.h     |   9 +-
 8 files changed, 375 insertions(+), 315 deletions(-)
 create mode 100644 src/lxc/initutils.c
 create mode 100644 src/lxc/initutils.h

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 6778a19..ce46495 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -12,6 +12,7 @@ noinst_HEADERS = \
 	conf.h \
 	console.h \
 	error.h \
+	initutils.h \
 	list.h \
 	log.h \
 	lxc.h \
@@ -67,6 +68,7 @@ liblxc_so_SOURCES = \
 	cgfs.c \
 	cgroup.c cgroup.h \
 	lxc.h \
+	initutils.c initutils.h \
 	utils.c utils.h \
 	sync.c sync.h \
 	namespace.h namespace.c \
@@ -239,7 +241,7 @@ lxc_checkpoint_SOURCES = lxc_checkpoint.c
 if HAVE_STATIC_LIBCAP
 sbin_PROGRAMS += init.lxc.static
 
-init_lxc_static_SOURCES = lxc_init.c error.c log.c utils.c caps.c
+init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c
 
 if !HAVE_GETLINE
 if HAVE_FGETLN
diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
index cf7c043..0810975 100644
--- a/src/lxc/bdev.c
+++ b/src/lxc/bdev.c
@@ -1253,7 +1253,7 @@ int btrfs_list_get_path_rootid(int fd, u64 *treeid)
 	return 0;
 }
 
-static bool is_btrfs_fs(const char *path)
+bool is_btrfs_fs(const char *path)
 {
 	int fd, ret;
 	struct btrfs_ioctl_space_args sargs;
@@ -1531,7 +1531,7 @@ static int btrfs_do_destroy_subvol(const char *path)
 
 	fd = open(newfull, O_RDONLY);
 	if (fd < 0) {
-		ERROR("Error opening %s", newfull);
+		SYSERROR("Error opening %s", newfull);
 		free(newfull);
 		return -1;
 	}
@@ -1829,6 +1829,13 @@ ignore_search:
 	return btrfs_do_destroy_subvol(path);
 }
 
+bool btrfs_try_remove_subvol(const char *path)
+{
+	if (!btrfs_detect(path))
+		return false;
+	return btrfs_recursive_destroy(path) == 0;
+}
+
 static int btrfs_destroy(struct bdev *orig)
 {
 	return btrfs_recursive_destroy(orig->src);
diff --git a/src/lxc/bdev.h b/src/lxc/bdev.h
index d97b9df..2144c19 100644
--- a/src/lxc/bdev.h
+++ b/src/lxc/bdev.h
@@ -105,30 +105,4 @@ bool attach_block_device(struct lxc_conf *conf);
 void detach_block_device(struct lxc_conf *conf);
 
 bool rootfs_is_blockdev(struct lxc_conf *conf);
-
-/* define constants if the kernel/glibc headers don't define them */
-#ifndef MS_DIRSYNC
-#define MS_DIRSYNC  128
-#endif
-
-#ifndef MS_REC
-#define MS_REC 16384
-#endif
-
-#ifndef MNT_DETACH
-#define MNT_DETACH 2
-#endif
-
-#ifndef MS_SLAVE
-#define MS_SLAVE (1<<19)
-#endif
-
-#ifndef MS_RELATIME
-#define MS_RELATIME (1 << 21)
-#endif
-
-#ifndef MS_STRICTATIME
-#define MS_STRICTATIME (1 << 24)
-#endif
-
 #endif
diff --git a/src/lxc/initutils.c b/src/lxc/initutils.c
new file mode 100644
index 0000000..dbb5d52
--- /dev/null
+++ b/src/lxc/initutils.c
@@ -0,0 +1,293 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <daniel.lezcano at free.fr>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "initutils.h"
+#include "log.h"
+
+lxc_log_define(lxc_initutils, lxc);
+
+static int mount_fs(const char *source, const char *target, const char *type)
+{
+	/* the umount may fail */
+	if (umount(target))
+		WARN("failed to unmount %s : %s", target, strerror(errno));
+
+	if (mount(source, target, type, 0, NULL)) {
+		ERROR("failed to mount %s : %s", target, strerror(errno));
+		return -1;
+	}
+
+	DEBUG("'%s' mounted on '%s'", source, target);
+
+	return 0;
+}
+
+extern void lxc_setup_fs(void)
+{
+	if (mount_fs("proc", "/proc", "proc"))
+		INFO("failed to remount proc");
+
+	/* if we can't mount /dev/shm, continue anyway */
+	if (mount_fs("shmfs", "/dev/shm", "tmpfs"))
+		INFO("failed to mount /dev/shm");
+
+	/* If we were able to mount /dev/shm, then /dev exists */
+	/* Sure, but it's read-only per config :) */
+	if (access("/dev/mqueue", F_OK) && mkdir("/dev/mqueue", 0666)) {
+		DEBUG("failed to create '/dev/mqueue'");
+		return;
+	}
+
+	/* continue even without posix message queue support */
+	if (mount_fs("mqueue", "/dev/mqueue", "mqueue"))
+		INFO("failed to mount /dev/mqueue");
+}
+
+static char *copy_global_config_value(char *p)
+{
+	int len = strlen(p);
+	char *retbuf;
+
+	if (len < 1)
+		return NULL;
+	if (p[len-1] == '\n') {
+		p[len-1] = '\0';
+		len--;
+	}
+	retbuf = malloc(len+1);
+	if (!retbuf)
+		return NULL;
+	strcpy(retbuf, p);
+	return retbuf;
+}
+
+const char *lxc_global_config_value(const char *option_name)
+{
+	static const char * const options[][2] = {
+		{ "lxc.bdev.lvm.vg",        DEFAULT_VG      },
+		{ "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL },
+		{ "lxc.bdev.zfs.root",      DEFAULT_ZFSROOT },
+		{ "lxc.lxcpath",            NULL            },
+		{ "lxc.default_config",     NULL            },
+		{ "lxc.cgroup.pattern",     NULL            },
+		{ "lxc.cgroup.use",         NULL            },
+		{ NULL, NULL },
+	};
+
+	/* placed in the thread local storage pool for non-bionic targets */
+#ifdef HAVE_TLS
+	static __thread const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
+#else
+	static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
+#endif
+
+	/* user_config_path is freed as soon as it is used */
+	char *user_config_path = NULL;
+
+	/*
+	 * The following variables are freed at bottom unconditionally.
+	 * So NULL the value if it is to be returned to the caller
+	 */
+	char *user_default_config_path = NULL;
+	char *user_lxc_path = NULL;
+	char *user_cgroup_pattern = NULL;
+
+	if (geteuid() > 0) {
+		const char *user_home = getenv("HOME");
+		if (!user_home)
+			user_home = "/";
+
+		user_config_path = malloc(sizeof(char) * (22 + strlen(user_home)));
+		user_default_config_path = malloc(sizeof(char) * (26 + strlen(user_home)));
+		user_lxc_path = malloc(sizeof(char) * (19 + strlen(user_home)));
+
+		sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home);
+		sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home);
+		sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home);
+		user_cgroup_pattern = strdup("lxc/%n");
+	}
+	else {
+		user_config_path = strdup(LXC_GLOBAL_CONF);
+		user_default_config_path = strdup(LXC_DEFAULT_CONFIG);
+		user_lxc_path = strdup(LXCPATH);
+		user_cgroup_pattern = strdup(DEFAULT_CGROUP_PATTERN);
+	}
+
+	const char * const (*ptr)[2];
+	size_t i;
+	char buf[1024], *p, *p2;
+	FILE *fin = NULL;
+
+	for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) {
+		if (!strcmp(option_name, (*ptr)[0]))
+			break;
+	}
+	if (!(*ptr)[0]) {
+		free(user_config_path);
+		free(user_default_config_path);
+		free(user_lxc_path);
+		free(user_cgroup_pattern);
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (values[i]) {
+		free(user_config_path);
+		free(user_default_config_path);
+		free(user_lxc_path);
+		free(user_cgroup_pattern);
+		return values[i];
+	}
+
+	fin = fopen_cloexec(user_config_path, "r");
+	free(user_config_path);
+	if (fin) {
+		while (fgets(buf, 1024, fin)) {
+			if (buf[0] == '#')
+				continue;
+			p = strstr(buf, option_name);
+			if (!p)
+				continue;
+			/* see if there was just white space in front
+			 * of the option name
+			 */
+			for (p2 = buf; p2 < p; p2++) {
+				if (*p2 != ' ' && *p2 != '\t')
+					break;
+			}
+			if (p2 < p)
+				continue;
+			p = strchr(p, '=');
+			if (!p)
+				continue;
+			/* see if there was just white space after
+			 * the option name
+			 */
+			for (p2 += strlen(option_name); p2 < p; p2++) {
+				if (*p2 != ' ' && *p2 != '\t')
+					break;
+			}
+			if (p2 < p)
+				continue;
+			p++;
+			while (*p && (*p == ' ' || *p == '\t')) p++;
+			if (!*p)
+				continue;
+
+			if (strcmp(option_name, "lxc.lxcpath") == 0) {
+				free(user_lxc_path);
+				user_lxc_path = copy_global_config_value(p);
+				remove_trailing_slashes(user_lxc_path);
+				values[i] = user_lxc_path;
+				user_lxc_path = NULL;
+				goto out;
+			}
+
+			values[i] = copy_global_config_value(p);
+			goto out;
+		}
+	}
+	/* could not find value, use default */
+	if (strcmp(option_name, "lxc.lxcpath") == 0) {
+		remove_trailing_slashes(user_lxc_path);
+		values[i] = user_lxc_path;
+		user_lxc_path = NULL;
+	}
+	else if (strcmp(option_name, "lxc.default_config") == 0) {
+		values[i] = user_default_config_path;
+		user_default_config_path = NULL;
+	}
+	else if (strcmp(option_name, "lxc.cgroup.pattern") == 0) {
+		values[i] = user_cgroup_pattern;
+		user_cgroup_pattern = NULL;
+	}
+	else
+		values[i] = (*ptr)[1];
+
+	/* special case: if default value is NULL,
+	 * and there is no config, don't view that
+	 * as an error... */
+	if (!values[i])
+		errno = 0;
+
+out:
+	if (fin)
+		fclose(fin);
+
+	free(user_cgroup_pattern);
+	free(user_default_config_path);
+	free(user_lxc_path);
+
+	return values[i];
+}
+
+extern void remove_trailing_slashes(char *p)
+{
+	int l = strlen(p);
+	while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
+		p[l] = '\0';
+}
+
+FILE *fopen_cloexec(const char *path, const char *mode)
+{
+	int open_mode = 0;
+	int step = 0;
+	int fd;
+	int saved_errno = 0;
+	FILE *ret;
+
+	if (!strncmp(mode, "r+", 2)) {
+		open_mode = O_RDWR;
+		step = 2;
+	} else if (!strncmp(mode, "r", 1)) {
+		open_mode = O_RDONLY;
+		step = 1;
+	} else if (!strncmp(mode, "w+", 2)) {
+		open_mode = O_RDWR | O_TRUNC | O_CREAT;
+		step = 2;
+	} else if (!strncmp(mode, "w", 1)) {
+		open_mode = O_WRONLY | O_TRUNC | O_CREAT;
+		step = 1;
+	} else if (!strncmp(mode, "a+", 2)) {
+		open_mode = O_RDWR | O_CREAT | O_APPEND;
+		step = 2;
+	} else if (!strncmp(mode, "a", 1)) {
+		open_mode = O_WRONLY | O_CREAT | O_APPEND;
+		step = 1;
+	}
+	for (; mode[step]; step++)
+		if (mode[step] == 'x')
+			open_mode |= O_EXCL;
+	open_mode |= O_CLOEXEC;
+
+	fd = open(path, open_mode, 0666);
+	if (fd < 0)
+		return NULL;
+
+	ret = fdopen(fd, mode);
+	saved_errno = errno;
+	if (!ret)
+		close(fd);
+	errno = saved_errno;
+	return ret;
+}
diff --git a/src/lxc/initutils.h b/src/lxc/initutils.h
new file mode 100644
index 0000000..b4f9e54
--- /dev/null
+++ b/src/lxc/initutils.h
@@ -0,0 +1,53 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <daniel.lezcano at free.fr>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __LXC_INITUTILS_H
+#define __LXC_INITUTILS_H
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+
+#include "config.h"
+
+#define DEFAULT_VG "lxc"
+#define DEFAULT_THIN_POOL "lxc"
+#define DEFAULT_ZFSROOT "lxc"
+
+extern void lxc_setup_fs(void);
+extern const char *lxc_global_config_value(const char *option_name);
+
+/* open a file with O_CLOEXEC */
+extern void remove_trailing_slashes(char *p);
+FILE *fopen_cloexec(const char *path, const char *mode);
+
+#endif /* __LXC_INITUTILS_H */
diff --git a/src/lxc/lxc_init.c b/src/lxc/lxc_init.c
index 0778bfe..62ed4ad 100644
--- a/src/lxc/lxc_init.c
+++ b/src/lxc/lxc_init.c
@@ -36,7 +36,7 @@
 #include "log.h"
 #include "caps.h"
 #include "error.h"
-#include "utils.h"
+#include "initutils.h"
 
 lxc_log_define(lxc_init, lxc);
 
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index fe71e9a..e597725 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -69,6 +69,11 @@
 
 lxc_log_define(lxc_utils, lxc);
 
+/*
+ * if path is btrfs, tries to remove it and any subvolumes beneath it
+ */
+extern bool btrfs_try_remove_subvol(const char *path);
+
 static int _recursive_rmdir(char *dirname, dev_t pdev,
 			    const char *exclude, int level, bool onedev)
 {
@@ -127,11 +132,16 @@ static int _recursive_rmdir(char *dirname, dev_t pdev,
 		ret = lstat(pathname, &mystat);
 		if (ret) {
 			ERROR("%s: failed to stat %s", __func__, pathname);
-			failed=1;
+			failed = 1;
 			continue;
 		}
-		if (onedev && mystat.st_dev != pdev)
+		if (onedev && mystat.st_dev != pdev) {
+			/* TODO should we be checking /proc/self/mountinfo for
+			 * pathname and not doing this if found? */
+			if (btrfs_try_remove_subvol(pathname))
+				INFO("Removed btrfs subvolume at %s\n", pathname);
 			continue;
+		}
 		if (S_ISDIR(mystat.st_mode)) {
 			if (_recursive_rmdir(pathname, pdev, exclude, level+1, onedev) < 0)
 				failed=1;
@@ -143,11 +153,9 @@ static int _recursive_rmdir(char *dirname, dev_t pdev,
 		}
 	}
 
-	if (rmdir(dirname) < 0) {
-		if (!hadexclude) {
-			ERROR("%s: failed to delete %s", __func__, dirname);
-			failed=1;
-		}
+	if (rmdir(dirname) < 0 && !btrfs_try_remove_subvol(dirname) && !hadexclude) {
+		ERROR("%s: failed to delete %s", __func__, dirname);
+		failed=1;
 	}
 
 	ret = closedir(dir);
@@ -196,43 +204,6 @@ extern int lxc_rmdir_onedev(char *path, const char *exclude)
 	return _recursive_rmdir(path, mystat.st_dev, exclude, 0, onedev);
 }
 
-static int mount_fs(const char *source, const char *target, const char *type)
-{
-	/* the umount may fail */
-	if (umount(target))
-		WARN("failed to unmount %s : %s", target, strerror(errno));
-
-	if (mount(source, target, type, 0, NULL)) {
-		ERROR("failed to mount %s : %s", target, strerror(errno));
-		return -1;
-	}
-
-	DEBUG("'%s' mounted on '%s'", source, target);
-
-	return 0;
-}
-
-extern void lxc_setup_fs(void)
-{
-	if (mount_fs("proc", "/proc", "proc"))
-		INFO("failed to remount proc");
-
-	/* if we can't mount /dev/shm, continue anyway */
-	if (mount_fs("shmfs", "/dev/shm", "tmpfs"))
-		INFO("failed to mount /dev/shm");
-
-	/* If we were able to mount /dev/shm, then /dev exists */
-	/* Sure, but it's read-only per config :) */
-	if (access("/dev/mqueue", F_OK) && mkdir("/dev/mqueue", 0666)) {
-		DEBUG("failed to create '/dev/mqueue'");
-		return;
-	}
-
-	/* continue even without posix message queue support */
-	if (mount_fs("mqueue", "/dev/mqueue", "mqueue"))
-		INFO("failed to mount /dev/mqueue");
-}
-
 /* borrowed from iproute2 */
 extern int get_u16(unsigned short *val, const char *arg, int base)
 {
@@ -275,195 +246,6 @@ extern int mkdir_p(const char *dir, mode_t mode)
 	return 0;
 }
 
-extern void remove_trailing_slashes(char *p)
-{
-	int l = strlen(p);
-	while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
-		p[l] = '\0';
-}
-
-static char *copy_global_config_value(char *p)
-{
-	int len = strlen(p);
-	char *retbuf;
-
-	if (len < 1)
-		return NULL;
-	if (p[len-1] == '\n') {
-		p[len-1] = '\0';
-		len--;
-	}
-	retbuf = malloc(len+1);
-	if (!retbuf)
-		return NULL;
-	strcpy(retbuf, p);
-	return retbuf;
-}
-
-#define DEFAULT_VG "lxc"
-#define DEFAULT_THIN_POOL "lxc"
-#define DEFAULT_ZFSROOT "lxc"
-
-const char *lxc_global_config_value(const char *option_name)
-{
-	static const char * const options[][2] = {
-		{ "lxc.bdev.lvm.vg",        DEFAULT_VG      },
-		{ "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL },
-		{ "lxc.bdev.zfs.root",      DEFAULT_ZFSROOT },
-		{ "lxc.lxcpath",            NULL            },
-		{ "lxc.default_config",     NULL            },
-		{ "lxc.cgroup.pattern",     NULL            },
-		{ "lxc.cgroup.use",         NULL            },
-		{ NULL, NULL },
-	};
-
-	/* placed in the thread local storage pool for non-bionic targets */
-#ifdef HAVE_TLS
-	static __thread const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
-#else
-	static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
-#endif
-
-	/* user_config_path is freed as soon as it is used */
-	char *user_config_path = NULL;
-
-	/*
-	 * The following variables are freed at bottom unconditionally.
-	 * So NULL the value if it is to be returned to the caller
-	 */
-	char *user_default_config_path = NULL;
-	char *user_lxc_path = NULL;
-	char *user_cgroup_pattern = NULL;
-
-	if (geteuid() > 0) {
-		const char *user_home = getenv("HOME");
-		if (!user_home)
-			user_home = "/";
-
-		user_config_path = malloc(sizeof(char) * (22 + strlen(user_home)));
-		user_default_config_path = malloc(sizeof(char) * (26 + strlen(user_home)));
-		user_lxc_path = malloc(sizeof(char) * (19 + strlen(user_home)));
-
-		sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home);
-		sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home);
-		sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home);
-		user_cgroup_pattern = strdup("lxc/%n");
-	}
-	else {
-		user_config_path = strdup(LXC_GLOBAL_CONF);
-		user_default_config_path = strdup(LXC_DEFAULT_CONFIG);
-		user_lxc_path = strdup(LXCPATH);
-		user_cgroup_pattern = strdup(DEFAULT_CGROUP_PATTERN);
-	}
-
-	const char * const (*ptr)[2];
-	size_t i;
-	char buf[1024], *p, *p2;
-	FILE *fin = NULL;
-
-	for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) {
-		if (!strcmp(option_name, (*ptr)[0]))
-			break;
-	}
-	if (!(*ptr)[0]) {
-		free(user_config_path);
-		free(user_default_config_path);
-		free(user_lxc_path);
-		free(user_cgroup_pattern);
-		errno = EINVAL;
-		return NULL;
-	}
-
-	if (values[i]) {
-		free(user_config_path);
-		free(user_default_config_path);
-		free(user_lxc_path);
-		free(user_cgroup_pattern);
-		return values[i];
-	}
-
-	fin = fopen_cloexec(user_config_path, "r");
-	free(user_config_path);
-	if (fin) {
-		while (fgets(buf, 1024, fin)) {
-			if (buf[0] == '#')
-				continue;
-			p = strstr(buf, option_name);
-			if (!p)
-				continue;
-			/* see if there was just white space in front
-			 * of the option name
-			 */
-			for (p2 = buf; p2 < p; p2++) {
-				if (*p2 != ' ' && *p2 != '\t')
-					break;
-			}
-			if (p2 < p)
-				continue;
-			p = strchr(p, '=');
-			if (!p)
-				continue;
-			/* see if there was just white space after
-			 * the option name
-			 */
-			for (p2 += strlen(option_name); p2 < p; p2++) {
-				if (*p2 != ' ' && *p2 != '\t')
-					break;
-			}
-			if (p2 < p)
-				continue;
-			p++;
-			while (*p && (*p == ' ' || *p == '\t')) p++;
-			if (!*p)
-				continue;
-
-			if (strcmp(option_name, "lxc.lxcpath") == 0) {
-				free(user_lxc_path);
-				user_lxc_path = copy_global_config_value(p);
-				remove_trailing_slashes(user_lxc_path);
-				values[i] = user_lxc_path;
-				user_lxc_path = NULL;
-				goto out;
-			}
-
-			values[i] = copy_global_config_value(p);
-			goto out;
-		}
-	}
-	/* could not find value, use default */
-	if (strcmp(option_name, "lxc.lxcpath") == 0) {
-		remove_trailing_slashes(user_lxc_path);
-		values[i] = user_lxc_path;
-		user_lxc_path = NULL;
-	}
-	else if (strcmp(option_name, "lxc.default_config") == 0) {
-		values[i] = user_default_config_path;
-		user_default_config_path = NULL;
-	}
-	else if (strcmp(option_name, "lxc.cgroup.pattern") == 0) {
-		values[i] = user_cgroup_pattern;
-		user_cgroup_pattern = NULL;
-	}
-	else
-		values[i] = (*ptr)[1];
-
-	/* special case: if default value is NULL,
-	 * and there is no config, don't view that
-	 * as an error... */
-	if (!values[i])
-		errno = 0;
-
-out:
-	if (fin)
-		fclose(fin);
-
-	free(user_cgroup_pattern);
-	free(user_default_config_path);
-	free(user_lxc_path);
-
-	return values[i];
-}
-
 char *get_rundir()
 {
 	char *rundir;
@@ -669,50 +451,6 @@ const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
 	return (const char**)lxc_va_arg_list_to_argv(ap, skip, 0);
 }
 
-FILE *fopen_cloexec(const char *path, const char *mode)
-{
-	int open_mode = 0;
-	int step = 0;
-	int fd;
-	int saved_errno = 0;
-	FILE *ret;
-
-	if (!strncmp(mode, "r+", 2)) {
-		open_mode = O_RDWR;
-		step = 2;
-	} else if (!strncmp(mode, "r", 1)) {
-		open_mode = O_RDONLY;
-		step = 1;
-	} else if (!strncmp(mode, "w+", 2)) {
-		open_mode = O_RDWR | O_TRUNC | O_CREAT;
-		step = 2;
-	} else if (!strncmp(mode, "w", 1)) {
-		open_mode = O_WRONLY | O_TRUNC | O_CREAT;
-		step = 1;
-	} else if (!strncmp(mode, "a+", 2)) {
-		open_mode = O_RDWR | O_CREAT | O_APPEND;
-		step = 2;
-	} else if (!strncmp(mode, "a", 1)) {
-		open_mode = O_WRONLY | O_CREAT | O_APPEND;
-		step = 1;
-	}
-	for (; mode[step]; step++)
-		if (mode[step] == 'x')
-			open_mode |= O_EXCL;
-	open_mode |= O_CLOEXEC;
-
-	fd = open(path, open_mode, 0666);
-	if (fd < 0)
-		return NULL;
-
-	ret = fdopen(fd, mode);
-	saved_errno = errno;
-	if (!ret)
-		close(fd);
-	errno = saved_errno;
-	return ret;
-}
-
 extern struct lxc_popen_FILE *lxc_popen(const char *command)
 {
 	struct lxc_popen_FILE *fp = NULL;
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index cc18906..5dbc803 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -32,17 +32,14 @@
 #include <unistd.h>
 
 #include "config.h"
+#include "initutils.h"
 
 /* returns 1 on success, 0 if there were any failures */
 extern int lxc_rmdir_onedev(char *path, const char *exclude);
-extern void lxc_setup_fs(void);
 extern int get_u16(unsigned short *val, const char *arg, int base);
 extern int mkdir_p(const char *dir, mode_t mode);
-extern void remove_trailing_slashes(char *p);
 extern char *get_rundir(void);
 
-extern const char *lxc_global_config_value(const char *option_name);
-
 /* Define getline() if missing from the C library */
 #ifndef HAVE_GETLINE
 #ifdef HAVE_FGETLN
@@ -148,10 +145,6 @@ static inline int signalfd(int fd, const sigset_t *mask, int flags)
 }
 #endif
 
-/* open a file with O_CLOEXEC */
-FILE *fopen_cloexec(const char *path, const char *mode);
-
-
 /* Struct to carry child pid from lxc_popen() to lxc_pclose().
  * Not an opaque struct to allow direct access to the underlying FILE *
  * (i.e., struct lxc_popen_FILE *file; fgets(buf, sizeof(buf), file->f))
-- 
2.1.4



More information about the lxc-devel mailing list