From: Serge Hallyn Date: Tue, 28 Apr 2015 13:31:05 +0000 (+0000) Subject: lxc-destroy: remove btrfs subvolumes X-Git-Tag: lxc-1.1.3~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7a09b8aaebed9043b89939e136802d09771965cd;p=thirdparty%2Flxc.git lxc-destroy: remove btrfs subvolumes 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 Acked-by: Stéphane Graber --- diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index 6778a1917..ce464950d 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 95d10a49f..d45b21690 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 d97b9df42..2144c1926 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 000000000..dbb5d52f5 --- /dev/null +++ b/src/lxc/initutils.c @@ -0,0 +1,293 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * + * 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 000000000..b4f9e545e --- /dev/null +++ b/src/lxc/initutils.h @@ -0,0 +1,53 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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 0778bfe5d..62ed4ad1b 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 fe71e9aa4..e597725f5 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 cc1890604..5dbc80373 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -32,17 +32,14 @@ #include #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))