[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