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

Stéphane Graber stgraber at ubuntu.com
Tue May 26 15:03:25 UTC 2015


On Tue, Apr 28, 2015 at 01:31:05PM +0000, Serge Hallyn wrote:
> 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>

Acked-by: Stéphane Graber <stgraber 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
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20150526/22857ec9/attachment.sig>


More information about the lxc-devel mailing list