[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