[lxc-devel] [lxc/master] tools: remove non api symbols
brauner on Github
lxc-bot at linuxcontainers.org
Wed Jan 17 23:45:50 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 381 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180117/524dfeed/attachment.bin>
-------------- next part --------------
From aa697c89b751c1e76f89f5aa1c313ce74ae7af33 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:13:09 +0100
Subject: [PATCH 01/30] tools: move lxc-attach to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 6 +-
src/lxc/confile.c | 41 ------
src/lxc/confile.h | 2 -
src/lxc/tools/arguments.c | 9 +-
src/lxc/tools/lxc_attach.c | 12 +-
src/lxc/tools/lxc_autostart.c | 1 -
src/lxc/tools/tool_utils.c | 336 ++++++++++++++++++++++++++++++++++++++++++
src/lxc/tools/tool_utils.h | 56 +++++++
8 files changed, 406 insertions(+), 57 deletions(-)
create mode 100644 src/lxc/tools/tool_utils.c
create mode 100644 src/lxc/tools/tool_utils.h
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 895684e0b..75037a5fa 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -4,7 +4,6 @@ pkginclude_HEADERS = \
version.h
noinst_HEADERS = \
- tools/arguments.h \
attach.h \
storage/storage.h \
storage/aufs.h \
@@ -18,6 +17,9 @@ noinst_HEADERS = \
storage/rsync.h \
storage/zfs.h \
storage/storage_utils.h \
+ tools/arguments.h \
+ tools/tool_utils.h \
+ tools/tool_list.h \
cgroups/cgroup.h \
cgroups/cgroup_utils.h \
caps.h \
@@ -266,7 +268,7 @@ AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir)
endif
LDADD=liblxc.la @CAP_LIBS@ @APPARMOR_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
-lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c
+lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c tools/tool_utils.c
lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c
lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c
lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 3deec58bf..5980d8664 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -2380,47 +2380,6 @@ signed long lxc_config_parse_arch(const char *arch)
return -1;
}
-int lxc_fill_elevated_privileges(char *flaglist, int *flags)
-{
- char *token, *saveptr = NULL;
- int i, aflag;
- struct {
- const char *token;
- int flag;
- } all_privs[] = {
- { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
- { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
- { "LSM", LXC_ATTACH_LSM_EXEC },
- { NULL, 0 }
- };
-
- if (!flaglist) {
- /* For the sake of backward compatibility, drop all privileges
- * if none is specified.
- */
- for (i = 0; all_privs[i].token; i++)
- *flags |= all_privs[i].flag;
-
- return 0;
- }
-
- token = strtok_r(flaglist, "|", &saveptr);
- while (token) {
- aflag = -1;
- for (i = 0; all_privs[i].token; i++)
- if (!strcmp(all_privs[i].token, token))
- aflag = all_privs[i].flag;
- if (aflag < 0)
- return -1;
-
- *flags |= aflag;
-
- token = strtok_r(NULL, "|", &saveptr);
- }
-
- return 0;
-}
-
/* Write out a configuration file. */
void write_config(FILE *fout, struct lxc_conf *c)
{
diff --git a/src/lxc/confile.h b/src/lxc/confile.h
index d50217860..6c69bc7a5 100644
--- a/src/lxc/confile.h
+++ b/src/lxc/confile.h
@@ -92,8 +92,6 @@ extern int lxc_config_define_load(struct lxc_list *defines,
/* needed for lxc-attach */
extern signed long lxc_config_parse_arch(const char *arch);
-extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
-
extern int lxc_clear_config_item(struct lxc_conf *c, const char *key);
extern void write_config(FILE *fout, struct lxc_conf *c);
diff --git a/src/lxc/tools/arguments.c b/src/lxc/tools/arguments.c
index 30fb714fd..7116dd6bc 100644
--- a/src/lxc/tools/arguments.c
+++ b/src/lxc/tools/arguments.c
@@ -182,6 +182,13 @@ static int lxc_arguments_lxcpath_add(struct lxc_arguments *args,
return 0;
}
+void remove_trailing_slashes(char *p)
+{
+ int l = strlen(p);
+ while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
+ p[l] = '\0';
+}
+
extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
char *const argv[])
{
@@ -250,7 +257,7 @@ extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
/* If no lxcpaths were given, use default */
if (!args->lxcpath_cnt) {
ret = lxc_arguments_lxcpath_add(
- args, lxc_global_config_value("lxc.lxcpath"));
+ args, lxc_get_global_config_item("lxc.lxcpath"));
if (ret < 0)
return ret;
}
diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 926bf079e..b2c405d3a 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -27,6 +27,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
@@ -36,16 +37,8 @@
#include <lxc/lxccontainer.h>
-#include "attach.h"
#include "arguments.h"
-#include "caps.h"
-#include "conf.h"
-#include "confile.h"
-#include "console.h"
-#include "log.h"
-#include "list.h"
-#include "mainloop.h"
-#include "utils.h"
+#include "tool_utils.h"
static const struct option my_longopts[] = {
{"elevated-privileges", optional_argument, 0, 'e'},
@@ -290,7 +283,6 @@ int main(int argc, char *argv[])
r = lxc_log_init(&log);
if (r)
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
if (geteuid()) {
if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
diff --git a/src/lxc/tools/lxc_autostart.c b/src/lxc/tools/lxc_autostart.c
index 48727b9f1..a3d4a8a8a 100644
--- a/src/lxc/tools/lxc_autostart.c
+++ b/src/lxc/tools/lxc_autostart.c
@@ -24,7 +24,6 @@
#include <lxc/lxccontainer.h>
#include "arguments.h"
-#include "list.h"
#include "log.h"
#include "utils.h"
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
new file mode 100644
index 000000000..39b388161
--- /dev/null
+++ b/src/lxc/tools/tool_utils.c
@@ -0,0 +1,336 @@
+/* liblxcapi
+ *
+ * Copyright © 2018 Christian Brauner <christian.brauner at ubuntu.com>.
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <linux/sched.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#if HAVE_SYS_PERSONALITY_H
+#include <sys/personality.h>
+#endif
+
+#include <lxc/lxccontainer.h>
+
+#include "tool_utils.h"
+
+int lxc_fill_elevated_privileges(char *flaglist, int *flags)
+{
+ char *token, *saveptr = NULL;
+ int i, aflag;
+ struct {
+ const char *token;
+ int flag;
+ } all_privs[] = {
+ { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
+ { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
+ { "LSM", LXC_ATTACH_LSM_EXEC },
+ { NULL, 0 }
+ };
+
+ if (!flaglist) {
+ /* For the sake of backward compatibility, drop all privileges
+ * if none is specified.
+ */
+ for (i = 0; all_privs[i].token; i++)
+ *flags |= all_privs[i].flag;
+
+ return 0;
+ }
+
+ token = strtok_r(flaglist, "|", &saveptr);
+ while (token) {
+ aflag = -1;
+ for (i = 0; all_privs[i].token; i++)
+ if (!strcmp(all_privs[i].token, token))
+ aflag = all_privs[i].flag;
+ if (aflag < 0)
+ return -1;
+
+ *flags |= aflag;
+
+ token = strtok_r(NULL, "|", &saveptr);
+ }
+
+ return 0;
+}
+
+signed long lxc_config_parse_arch(const char *arch)
+{
+#if HAVE_SYS_PERSONALITY_H
+ size_t i;
+ struct per_name {
+ char *name;
+ unsigned long per;
+ } pername[] = {
+ { "x86", PER_LINUX32 },
+ { "linux32", PER_LINUX32 },
+ { "i386", PER_LINUX32 },
+ { "i486", PER_LINUX32 },
+ { "i586", PER_LINUX32 },
+ { "i686", PER_LINUX32 },
+ { "athlon", PER_LINUX32 },
+ { "mips", PER_LINUX32 },
+ { "mipsel", PER_LINUX32 },
+ { "ppc", PER_LINUX32 },
+ { "arm", PER_LINUX32 },
+ { "armv7l", PER_LINUX32 },
+ { "armhf", PER_LINUX32 },
+ { "armel", PER_LINUX32 },
+ { "powerpc", PER_LINUX32 },
+ { "linux64", PER_LINUX },
+ { "x86_64", PER_LINUX },
+ { "amd64", PER_LINUX },
+ { "mips64", PER_LINUX },
+ { "mips64el", PER_LINUX },
+ { "ppc64", PER_LINUX },
+ { "ppc64le", PER_LINUX },
+ { "ppc64el", PER_LINUX },
+ { "powerpc64", PER_LINUX },
+ { "s390x", PER_LINUX },
+ { "aarch64", PER_LINUX },
+ { "arm64", PER_LINUX },
+ };
+ size_t len = sizeof(pername) / sizeof(pername[0]);
+
+ for (i = 0; i < len; i++) {
+ if (!strcmp(pername[i].name, arch))
+ return pername[i].per;
+ }
+#endif
+
+ return -1;
+}
+
+enum {
+ LXC_NS_USER,
+ LXC_NS_MNT,
+ LXC_NS_PID,
+ LXC_NS_UTS,
+ LXC_NS_IPC,
+ LXC_NS_NET,
+ LXC_NS_CGROUP,
+ LXC_NS_MAX
+};
+
+const static struct ns_info {
+ const char *proc_name;
+ int clone_flag;
+} ns_info[LXC_NS_MAX] = {
+ [LXC_NS_USER] = { "user", CLONE_NEWUSER },
+ [LXC_NS_MNT] = { "mnt", CLONE_NEWNS },
+ [LXC_NS_PID] = { "pid", CLONE_NEWPID },
+ [LXC_NS_UTS] = { "uts", CLONE_NEWUTS },
+ [LXC_NS_IPC] = { "ipc", CLONE_NEWIPC },
+ [LXC_NS_NET] = { "net", CLONE_NEWNET },
+ [LXC_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP }
+};
+
+int lxc_namespace_2_cloneflag(const char *namespace)
+{
+ int i;
+ for (i = 0; i < LXC_NS_MAX; i++)
+ if (!strcasecmp(ns_info[i].proc_name, namespace))
+ return ns_info[i].clone_flag;
+
+ fprintf(stderr, "Invalid namespace name \"%s\"", namespace);
+ return -EINVAL;
+}
+
+int lxc_fill_namespace_flags(char *flaglist, int *flags)
+{
+ char *token, *saveptr = NULL;
+ int aflag;
+
+ if (!flaglist) {
+ fprintf(stderr, "At least one namespace is needed\n");
+ return -1;
+ }
+
+ token = strtok_r(flaglist, "|", &saveptr);
+ while (token) {
+
+ aflag = lxc_namespace_2_cloneflag(token);
+ if (aflag < 0)
+ return -1;
+
+ *flags |= aflag;
+
+ token = strtok_r(NULL, "|", &saveptr);
+ }
+
+ return 0;
+}
+
+#if HAVE_LIBCAP
+
+#ifndef PR_CAPBSET_READ
+#define PR_CAPBSET_READ 23
+#endif
+
+int lxc_caps_init(void)
+{
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+ uid_t euid = geteuid();
+
+ if (!uid)
+ return 0;
+
+ if (uid && !euid) {
+ if (prctl(PR_SET_KEEPCAPS, 1)) {
+ fprintf(stderr, "%s - Failed to set PR_SET_KEEPCAPS\n", strerror(errno));
+ return -1;
+ }
+
+ if (setresgid(gid, gid, gid)) {
+ fprintf(stderr, "%s - Failed to change gid to %d\n", strerror(errno), gid);
+ return -1;
+ }
+
+ if (setresuid(uid, uid, uid)) {
+ fprintf(stderr, "%s - Failed to change uid to %d\n", strerror(errno), uid);
+ return -1;
+ }
+
+ if (lxc_caps_up()) {
+ fprintf(stderr, "%s - Failed to restore capabilities\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int lxc_caps_up(void)
+{
+ cap_t caps;
+ cap_value_t cap;
+ int ret;
+
+ /* when we are run as root, we don't want to play
+ * with the capabilities */
+ if (!getuid())
+ return 0;
+
+ caps = cap_get_proc();
+ if (!caps) {
+ fprintf(stderr, "%s - Failed to cap_get_proc\n", strerror(errno));
+ return -1;
+ }
+
+ for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
+ cap_flag_value_t flag;
+
+ ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
+ if (ret) {
+ if (errno == EINVAL) {
+ break;
+ } else {
+ fprintf(stderr, "%s- Failed to call cap_get_flag\n", strerror(errno));
+ goto out;
+ }
+ }
+
+ ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
+ if (ret) {
+ fprintf(stderr, "%s - Failed to call cap_set_flag", strerror(errno));
+ goto out;
+ }
+ }
+
+ ret = cap_set_proc(caps);
+ if (ret) {
+ fprintf(stderr, "%s - Failed to cap_set_proc", strerror(errno));
+ goto out;
+ }
+
+out:
+ cap_free(caps);
+ return 0;
+}
+
+#endif
+
+int lxc_wait_for_pid_status(pid_t pid)
+{
+ int status, ret;
+
+again:
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ if (errno == EINTR)
+ goto again;
+ return -1;
+ }
+ if (ret != pid)
+ goto again;
+ return status;
+}
+
+int lxc_safe_int(const char *numstr, int *converted)
+{
+ char *err = NULL;
+ signed long int sli;
+
+ errno = 0;
+ sli = strtol(numstr, &err, 0);
+ if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
+ return -ERANGE;
+
+ if (errno != 0 && sli == 0)
+ return -EINVAL;
+
+ if (err == numstr || *err != '\0')
+ return -EINVAL;
+
+ if (sli > INT_MAX || sli < INT_MIN)
+ return -ERANGE;
+
+ *converted = (int)sli;
+ return 0;
+}
+
+int lxc_safe_long(const char *numstr, long int *converted)
+{
+ char *err = NULL;
+ signed long int sli;
+
+ errno = 0;
+ sli = strtol(numstr, &err, 0);
+ if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
+ return -ERANGE;
+
+ if (errno != 0 && sli == 0)
+ return -EINVAL;
+
+ if (err == numstr || *err != '\0')
+ return -EINVAL;
+
+ *converted = sli;
+ return 0;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
new file mode 100644
index 000000000..59479dfa0
--- /dev/null
+++ b/src/lxc/tools/tool_utils.h
@@ -0,0 +1,56 @@
+/* liblxcapi
+ *
+ * Copyright © 2018 Christian Brauner <christian.brauner at ubuntu.com>.
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __LXC_UTILS_H
+#define __LXC_UTILS_H
+
+/* Properly support loop devices on 32bit systems. */
+#define _FILE_OFFSET_BITS 64
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
+extern signed long lxc_config_parse_arch(const char *arch);
+extern int lxc_namespace_2_cloneflag(const char *namespace);
+extern int lxc_fill_namespace_flags(char *flaglist, int *flags);
+
+#if HAVE_LIBCAP
+#include <sys/capability.h>
+
+extern int lxc_caps_up(void);
+extern int lxc_caps_init(void);
+#else
+static inline int lxc_caps_up(void) {
+ return 0;
+}
+
+static inline int lxc_caps_init(void) {
+ return 0;
+}
+#endif
+
+extern int lxc_wait_for_pid_status(pid_t pid);
+extern int lxc_safe_int(const char *numstr, int *converted);
+extern int lxc_safe_long(const char *numstr, long int *converted);
+
+#endif /* __LXC_UTILS_H */
From cb52863038b72e7747b502d7fa958444ef807e8b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:25:15 +0100
Subject: [PATCH 02/30] tools: lxc-autostart: non-functional changes
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_autostart.c | 180 +++++++++++++++++++-----------------------
1 file changed, 80 insertions(+), 100 deletions(-)
diff --git a/src/lxc/tools/lxc_autostart.c b/src/lxc/tools/lxc_autostart.c
index a3d4a8a8a..b3823af2f 100644
--- a/src/lxc/tools/lxc_autostart.c
+++ b/src/lxc/tools/lxc_autostart.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -144,14 +146,13 @@ int lists_contain_common_entry(struct lxc_list *p1, struct lxc_list *p2) {
return 0;
}
-/*
- * This is a variation of get_list below it.
- * This version allows two additional features.
- * If a list is passed to it, it adds to it.
- * It allows for empty entries (i.e. "group1,,group2") generating
- * and empty list entry.
+/* This is a variation of get_list below it. This version allows two additional
+ * features. If a list is passed to it, it adds to it. It allows for empty
+ * entries (i.e. "group1,,group2") generating and empty list entry.
*/
-static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list) {
+static struct lxc_list *accumulate_list(char *input, char *delimiter,
+ struct lxc_list *str_list)
+{
char *workstr = NULL;
char *workptr = NULL;
char *next_ptr = NULL;
@@ -159,45 +160,33 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc
struct lxc_list *workstr_list;
workstr = strdup(input);
- if (!workstr) {
+ if (!workstr)
return NULL;
- }
workstr_list = str_list;
- if ( ! workstr_list ) {
+ if (!workstr_list) {
workstr_list = malloc(sizeof(*workstr_list));
lxc_list_init(workstr_list);
}
for (workptr = workstr; workptr; workptr = next_ptr) {
- /*
- * We can't use strtok_r here because it collapses
- * multiple delimiters into 1 making empty fields
- * impossible...
+ /* We can't use strtok_r here because it collapses multiple
+ * delimiters into 1 making empty fields impossible...
*/
- /* token = strtok_r(workptr, delimiter, &sptr); */
- next_ptr = strchr( workptr, *delimiter );
-
- if( next_ptr ) {
+ next_ptr = strchr(workptr, *delimiter);
+ if (next_ptr)
*next_ptr++ = '\0';
- }
- /*
- * At this point, we'd like to check to see if this
- * group is already contained in the list and ignore
- * it if it is... This also helps us with any
- * corner cases where a string begins or ends with a
- * delimiter.
+ /* At this point, we'd like to check to see if this group is
+ * already contained in the list and ignore it if it is... This
+ * also helps us with any corner cases where a string begins or
+ * ends with a delimiter.
*/
-
- if ( list_contains_entry( workptr, workstr_list ) ) {
- if ( *workptr ) {
- fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr );
- fflush(stderr);
- } else {
- fprintf(stderr, "Duplicate NULL group in list - ignoring\n" );
- fflush(stderr);
- }
+ if (list_contains_entry(workptr, workstr_list)) {
+ if (*workptr)
+ fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr);
+ else
+ fprintf(stderr, "Duplicate NULL group in list - ignoring\n");
} else {
worklist = malloc(sizeof(*worklist));
if (!worklist)
@@ -218,7 +207,8 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc
return workstr_list;
}
-static struct lxc_list *get_list(char *input, char *delimiter) {
+static struct lxc_list *get_list(char *input, char *delimiter)
+{
char *workstr = NULL;
char *workptr = NULL;
char *sptr = NULL;
@@ -235,11 +225,10 @@ static struct lxc_list *get_list(char *input, char *delimiter) {
return NULL;
}
- for (workptr = workstr;;workptr = NULL) {
+ for (workptr = workstr;; workptr = NULL) {
token = strtok_r(workptr, delimiter, &sptr);
- if (!token) {
+ if (!token)
break;
- }
worklist = malloc(sizeof(*worklist));
if (!worklist)
@@ -259,16 +248,17 @@ static struct lxc_list *get_list(char *input, char *delimiter) {
return workstr_list;
}
-static struct lxc_list *get_config_list(struct lxc_container *c, char *key) {
+static struct lxc_list *get_config_list(struct lxc_container *c, char *key)
+{
int len = 0;
- char* value = NULL;
+ char *value = NULL;
struct lxc_list *config_list = NULL;
len = c->get_config_item(c, key, NULL, 0);
if (len < 0)
return NULL;
- value = (char*) malloc(sizeof(char)*len + 1);
+ value = (char *)malloc(sizeof(char) * len + 1);
if (value == NULL)
return NULL;
@@ -288,16 +278,16 @@ static struct lxc_list *get_config_list(struct lxc_container *c, char *key) {
return config_list;
}
-static int get_config_integer(struct lxc_container *c, char *key) {
- int len = 0;
- int ret = 0;
- char* value = NULL;
+static int get_config_integer(struct lxc_container *c, char *key)
+{
+ int len = 0, ret = 0;
+ char *value = NULL;
len = c->get_config_item(c, key, NULL, 0);
if (len < 0)
return 0;
- value = (char*) malloc(sizeof(char)*len + 1);
+ value = (char *)malloc(sizeof(char) * len + 1);
if (value == NULL)
return 0;
@@ -314,7 +304,8 @@ static int get_config_integer(struct lxc_container *c, char *key) {
return ret;
}
-static int cmporder(const void *p1, const void *p2) {
+static int cmporder(const void *p1, const void *p2)
+{
struct lxc_container *c1 = *(struct lxc_container **)p1;
struct lxc_container *c2 = *(struct lxc_container **)p2;
@@ -323,33 +314,33 @@ static int cmporder(const void *p1, const void *p2) {
if (c1_order == c2_order)
return strcmp(c1->name, c2->name);
- else
- return (c1_order - c2_order);
+
+ return (c1_order - c2_order);
}
-static int toss_list( struct lxc_list *c_groups_list ) {
+static int toss_list(struct lxc_list *c_groups_list)
+{
struct lxc_list *it, *next;
- if (c_groups_list) {
- lxc_list_for_each_safe(it, c_groups_list, next) {
- lxc_list_del(it);
- free(it->elem);
- free(it);
- }
- free(c_groups_list);
+ if (!c_groups_list)
+ return 1;
+
+ lxc_list_for_each_safe(it, c_groups_list, next) {
+ lxc_list_del(it);
+ free(it->elem);
+ free(it);
}
+ free(c_groups_list);
return 1;
}
int main(int argc, char *argv[])
{
- int count = 0;
- int i = 0;
- int ret = 0;
+ int count = 0, i = 0, ret = 0;
+ struct lxc_list *cmd_group;
struct lxc_container **containers = NULL;
struct lxc_list **c_groups_lists = NULL;
- struct lxc_list *cmd_group;
struct lxc_log log;
if (lxc_arguments_parse(&my_args, argc, argv))
@@ -374,36 +365,29 @@ int main(int argc, char *argv[])
if (count < 0)
exit(EXIT_FAILURE);
- if (!my_args.all) {
- /* Allocate an array for our container group lists */
+ /* Allocate an array for our container group lists */
+ if (!my_args.all)
c_groups_lists = calloc( count, sizeof( struct lxc_list * ) );
- }
qsort(&containers[0], count, sizeof(struct lxc_container *), cmporder);
- if (cmd_groups_list && my_args.all) {
+ if (cmd_groups_list && my_args.all)
fprintf(stderr, "Specifying -a (all) with -g (groups) doesn't make sense. All option overrides.\n");
- fflush(stderr);
- }
- if (!cmd_groups_list) {
- /*
- * We need a default cmd_groups_list even for the -a
- * case in order to force a pass through the loop for
- * the NULL group. This, someday, could be taken from
- * a config file somewhere...
- */
+ /* We need a default cmd_groups_list even for the -a
+ * case in order to force a pass through the loop for
+ * the NULL group. This, someday, could be taken from
+ * a config file somewhere...
+ */
+ if (!cmd_groups_list)
cmd_groups_list = accumulate_list( "" , ",", NULL );
- }
lxc_list_for_each(cmd_group, cmd_groups_list) {
-
- /*
- * Prograpmmers Note:
- * Because we may take several passes through the container list
- * We'll switch on if the container pointer is NULL and if we process a
- * container (run it or decide to ignore it) and call lxc_container_put
- * then we'll NULL it out and not check it again.
+ /* Because we may take several passes through the container list
+ * We'll switch on if the container pointer is NULL and if we
+ * process a container (run it or decide to ignore it) and call
+ * lxc_container_put then we'll NULL it out and not check it
+ * again.
*/
for (i = 0; i < count; i++) {
struct lxc_container *c = containers[i];
@@ -412,10 +396,9 @@ int main(int argc, char *argv[])
/* Skip - must have been already processed */
continue;
- /*
- * We haven't loaded the container groups yet so
- * these next two checks don't need to free them
- * if they fail. They'll fail on the first pass.
+ /* We haven't loaded the container groups yet so these
+ * next two checks don't need to free them if they fail.
+ * They'll fail on the first pass.
*/
if (!c->may_control(c)) {
/* We're done with this container */
@@ -442,8 +425,10 @@ int main(int argc, char *argv[])
ret = list_contains_entry(cmd_group->elem, c_groups_lists[i]);
if ( ret == 0 ) {
- /* Not in the target group this pass */
- /* Leave in the list for subsequent passes */
+ /* Not in the target group this pass so
+ * leave in the list for subsequent
+ * passes.
+ */
continue;
}
}
@@ -467,8 +452,7 @@ int main(int argc, char *argv[])
}
}
}
- }
- else if (my_args.hardstop) {
+ } else if (my_args.hardstop) {
/* Kill the container */
if (c->is_running(c)) {
if (my_args.list) {
@@ -482,8 +466,7 @@ int main(int argc, char *argv[])
}
}
}
- }
- else if (my_args.reboot) {
+ } else if (my_args.reboot) {
/* Reboot the container */
if (c->is_running(c)) {
if (my_args.list) {
@@ -500,8 +483,7 @@ int main(int argc, char *argv[])
sleep(get_config_integer(c, "lxc.start.delay"));
}
}
- }
- else {
+ } else {
/* Start the container */
if (!c->is_running(c)) {
if (my_args.list) {
@@ -525,9 +507,8 @@ int main(int argc, char *argv[])
* then we're done with this container... We can dump any
* c_groups_list and the container itself.
*/
- if ( lxc_container_put(c) > 0 ) {
+ if ( lxc_container_put(c) > 0 )
containers[i] = NULL;
- }
if ( c_groups_lists ) {
toss_list(c_groups_lists[i]);
c_groups_lists[i] = NULL;
@@ -538,12 +519,11 @@ int main(int argc, char *argv[])
/* clean up any lingering detritus */
for (i = 0; i < count; i++) {
- if ( containers[i] ) {
+ if (containers[i])
lxc_container_put(containers[i]);
- }
- if ( c_groups_lists && c_groups_lists[i] ) {
+
+ if (c_groups_lists && c_groups_lists[i])
toss_list(c_groups_lists[i]);
- }
}
free(c_groups_lists);
From 61c8f526d083cd2a368b7b19889c0852998b0160 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:32:04 +0100
Subject: [PATCH 03/30] tools: move lxc-autostart to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_autostart.c | 6 +-
src/lxc/tools/tool_list.h | 167 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 170 insertions(+), 3 deletions(-)
create mode 100644 src/lxc/tools/tool_list.h
diff --git a/src/lxc/tools/lxc_autostart.c b/src/lxc/tools/lxc_autostart.c
index b3823af2f..41d2e4b57 100644
--- a/src/lxc/tools/lxc_autostart.c
+++ b/src/lxc/tools/lxc_autostart.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,8 +27,8 @@
#include <lxc/lxccontainer.h>
#include "arguments.h"
-#include "log.h"
-#include "utils.h"
+#include "tool_list.h"
+#include "tool_utils.h"
static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list);
@@ -355,7 +356,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
diff --git a/src/lxc/tools/tool_list.h b/src/lxc/tools/tool_list.h
new file mode 100644
index 000000000..9858081ab
--- /dev/null
+++ b/src/lxc/tools/tool_list.h
@@ -0,0 +1,167 @@
+/*
+ * 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_LIST_H
+#define __LXC_LIST_H
+
+#include <stdio.h>
+
+struct lxc_list {
+ void *elem;
+ struct lxc_list *next;
+ struct lxc_list *prev;
+};
+
+#define lxc_init_list(l) \
+ { \
+ .next = l, .prev = l \
+ }
+
+/*
+ * Iterate through an lxc list. An example for an idiom would be:
+ *
+ * struct lxc_list *iterator;
+ * lxc_list_for_each(iterator, list) {
+ * type *tmp;
+ * tmp = iterator->elem;
+ * }
+ */
+#define lxc_list_for_each(__iterator, __list) \
+ for (__iterator = (__list)->next; __iterator != __list; \
+ __iterator = __iterator->next)
+
+/* Iterate safely through an lxc list. An example for an appropriate use case
+ * would be:
+ *
+ * struct lxc_list *cur, *next;
+ * lxc_list_for_each_safe(cur, list, next) {
+ * type *tmp;
+ * tmp = cur->elem;
+ * }
+ */
+#define lxc_list_for_each_safe(__iterator, __list, __next) \
+ for (__iterator = (__list)->next, __next = __iterator->next; \
+ __iterator != __list; __iterator = __next, __next = __next->next)
+
+/* Initalize list. */
+static inline void lxc_list_init(struct lxc_list *list)
+{
+ list->elem = NULL;
+ list->next = list->prev = list;
+}
+
+/* Add an element to a list. See lxc_list_add() and lxc_list_add_tail() for an
+ * idiom.
+ */
+static inline void lxc_list_add_elem(struct lxc_list *list, void *elem)
+{
+ list->elem = elem;
+}
+
+/* Retrieve first element of list. */
+static inline void *lxc_list_first_elem(struct lxc_list *list)
+{
+ return list->next->elem;
+}
+
+/* Retrieve last element of list. */
+static inline void *lxc_list_last_elem(struct lxc_list *list)
+{
+ return list->prev->elem;
+}
+
+/* Determine if list is empty. */
+static inline int lxc_list_empty(struct lxc_list *list)
+{
+ return list == list->next;
+}
+
+/* Workhorse to be called from lxc_list_add() and lxc_list_add_tail(). */
+static inline void __lxc_list_add(struct lxc_list *new, struct lxc_list *prev,
+ struct lxc_list *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/* Idiom to add an element to the beginning of an lxc list:
+ *
+ * struct lxc_list *tmp = malloc(sizeof(*tmp));
+ * if (tmp == NULL)
+ * return 1;
+ * lxc_list_add_elem(tmp, elem);
+ * lxc_list_add(list, tmp);
+ */
+static inline void lxc_list_add(struct lxc_list *head, struct lxc_list *list)
+{
+ __lxc_list_add(list, head, head->next);
+}
+
+/* Idiom to add an element to the end of an lxc list:
+ *
+ * struct lxc_list *tmp = malloc(sizeof(*tmp));
+ * if (tmp == NULL)
+ * return 1;
+ * lxc_list_add_elem(tmp, elem);
+ * lxc_list_add_tail(list, tmp);
+ */
+static inline void lxc_list_add_tail(struct lxc_list *head,
+ struct lxc_list *list)
+{
+ __lxc_list_add(list, head->prev, head);
+}
+
+/* Idiom to remove an element from a list:
+ * struct lxc_list *cur, *next;
+ * lxc_list_for_each_safe(cur, list, next) {
+ * lxc_list_del(cur);
+ * free(cur->elem);
+ * free(cur);
+ * }
+ */
+static inline void lxc_list_del(struct lxc_list *list)
+{
+ struct lxc_list *next, *prev;
+
+ next = list->next;
+ prev = list->prev;
+ next->prev = prev;
+ prev->next = next;
+}
+
+/* Return length of the list. */
+static inline size_t lxc_list_len(struct lxc_list *list)
+{
+ size_t i = 0;
+ struct lxc_list *iter;
+
+ lxc_list_for_each(iter, list) {
+ i++;
+ }
+
+ return i;
+}
+
+#endif /* __LXC_LIST_H */
From 87cf87aae59448d3e42a5a368849360de7c87915 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:36:12 +0100
Subject: [PATCH 04/30] tools: move lxc-cgroup to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/arguments.h | 1 +
src/lxc/tools/lxc_cgroup.c | 10 +++++-----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h
index 15941bcc3..bd491a32b 100644
--- a/src/lxc/tools/arguments.h
+++ b/src/lxc/tools/arguments.h
@@ -31,6 +31,7 @@
#include <sys/types.h>
#include <lxc/lxccontainer.h>
+#define TOOL_MAXPATHLEN 4096
struct lxc_arguments;
typedef int (*lxc_arguments_parser_t)(struct lxc_arguments *, int, char *);
diff --git a/src/lxc/tools/lxc_cgroup.c b/src/lxc/tools/lxc_cgroup.c
index cfd14bd8f..3624e80b7 100644
--- a/src/lxc/tools/lxc_cgroup.c
+++ b/src/lxc/tools/lxc_cgroup.c
@@ -21,17 +21,17 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define _GNU_SOURCE
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <lxc/lxccontainer.h>
#include "arguments.h"
-#include "log.h"
-#include "lxc.h"
static int my_checker(const struct lxc_arguments* args)
{
@@ -39,6 +39,7 @@ static int my_checker(const struct lxc_arguments* args)
lxc_error(args, "missing state object");
return -1;
}
+
return 0;
}
@@ -83,7 +84,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
@@ -130,8 +130,8 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
} else {
- char buffer[MAXPATHLEN];
- int ret = c->get_cgroup_item(c, state_object, buffer, MAXPATHLEN);
+ char buffer[TOOL_MAXPATHLEN];
+ int ret = c->get_cgroup_item(c, state_object, buffer, TOOL_MAXPATHLEN);
if (ret < 0) {
fprintf(stderr, "failed to retrieve value of '%s' for '%s:%s'\n",
state_object, my_args.lxcpath[0], my_args.name);
From 44f811f424051b942542df248132ad4d7e54f8fa Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:46:30 +0100
Subject: [PATCH 05/30] cmd: move lxc-lxc_usernsexec
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 4 +++-
src/lxc/{tools => cmd}/lxc_usernsexec.c | 0
2 files changed, 3 insertions(+), 1 deletion(-)
rename src/lxc/{tools => cmd}/lxc_usernsexec.c (100%)
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 75037a5fa..b2cc37a2d 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -290,11 +290,13 @@ lxc_unshare_SOURCES = tools/lxc_unshare.c tools/arguments.c
lxc_wait_SOURCES = tools/lxc_wait.c tools/arguments.c
lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c
lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c
-lxc_usernsexec_SOURCES = tools/lxc_usernsexec.c tools/arguments.c
lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c
lxc_user_nic_SOURCES = lxc_user_nic.c namespace.c network.c tools/arguments.c
lxc_monitord_SOURCES = lxc_monitord.c tools/arguments.c
+# Binaries shipping with liblxc
+lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c
+
if ENABLE_DEPRECATED
lxc_clone_SOURCES = tools/lxc_clone.c tools/arguments.c
endif
diff --git a/src/lxc/tools/lxc_usernsexec.c b/src/lxc/cmd/lxc_usernsexec.c
similarity index 100%
rename from src/lxc/tools/lxc_usernsexec.c
rename to src/lxc/cmd/lxc_usernsexec.c
From aefeb7f7e1b801e70019aea20d416fbb3c9b3853 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:48:07 +0100
Subject: [PATCH 06/30] cmd: move init.lxc{.static}
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 4 ++--
src/lxc/{ => cmd}/lxc_init.c | 0
2 files changed, 2 insertions(+), 2 deletions(-)
rename src/lxc/{ => cmd}/lxc_init.c (100%)
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index b2cc37a2d..46f94f010 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -278,7 +278,6 @@ lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c
lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c
lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c
lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c
-init_lxc_SOURCES = lxc_init.c
lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c
lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c
lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c
@@ -295,6 +294,7 @@ lxc_user_nic_SOURCES = lxc_user_nic.c namespace.c network.c tools/arguments.c
lxc_monitord_SOURCES = lxc_monitord.c tools/arguments.c
# Binaries shipping with liblxc
+init_lxc_SOURCES = cmd/lxc_init.c
lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c
if ENABLE_DEPRECATED
@@ -308,7 +308,7 @@ endif
if HAVE_STATIC_LIBCAP
sbin_PROGRAMS += init.lxc.static
-init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c parse.c namespace.c
+init_lxc_static_SOURCES = cmd/lxc_init.c error.c log.c initutils.c caps.c parse.c namespace.c
if !HAVE_GETLINE
if HAVE_FGETLN
diff --git a/src/lxc/lxc_init.c b/src/lxc/cmd/lxc_init.c
similarity index 100%
rename from src/lxc/lxc_init.c
rename to src/lxc/cmd/lxc_init.c
From a3b425a915ef48952f78d3e0942aaea0c0ff4b91 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:49:55 +0100
Subject: [PATCH 07/30] cmd: move lxc-checkconfig
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
configure.ac | 2 +-
src/lxc/Makefile.am | 2 +-
src/lxc/{tools => cmd}/lxc-checkconfig.in | 0
3 files changed, 2 insertions(+), 2 deletions(-)
rename src/lxc/{tools => cmd}/lxc-checkconfig.in (100%)
diff --git a/configure.ac b/configure.ac
index 0bcd75a28..a841f9b9f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -939,7 +939,7 @@ AC_CONFIG_FILES([
src/Makefile
src/lxc/Makefile
src/lxc/lxc.functions
- src/lxc/tools/lxc-checkconfig
+ src/lxc/cmd/lxc-checkconfig
src/lxc/tools/lxc-start-ephemeral
src/lxc/tools/lxc-update-config
src/lxc/version.h
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 46f94f010..c8c5bb910 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -216,7 +216,7 @@ liblxc_la_LIBADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS)
liblxc_la_CFLAGS += $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) $(NIH_DBUS_CFLAGS)
endif
-bin_SCRIPTS = tools/lxc-checkconfig \
+bin_SCRIPTS = cmd/lxc-checkconfig \
tools/lxc-update-config
EXTRA_DIST = \
diff --git a/src/lxc/tools/lxc-checkconfig.in b/src/lxc/cmd/lxc-checkconfig.in
similarity index 100%
rename from src/lxc/tools/lxc-checkconfig.in
rename to src/lxc/cmd/lxc-checkconfig.in
From b880b5f2fc722dd96e1f8247bf31e685e3e6b6d9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:53:10 +0100
Subject: [PATCH 08/30] cmd: move lxc-user-nic
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 2 +-
src/lxc/{ => cmd}/lxc_user_nic.c | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename src/lxc/{ => cmd}/lxc_user_nic.c (100%)
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index c8c5bb910..e1eaabf99 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -290,11 +290,11 @@ lxc_wait_SOURCES = tools/lxc_wait.c tools/arguments.c
lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c
lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c
lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c
-lxc_user_nic_SOURCES = lxc_user_nic.c namespace.c network.c tools/arguments.c
lxc_monitord_SOURCES = lxc_monitord.c tools/arguments.c
# Binaries shipping with liblxc
init_lxc_SOURCES = cmd/lxc_init.c
+lxc_user_nic_SOURCES = cmd/lxc_user_nic.c namespace.c network.c
lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c
if ENABLE_DEPRECATED
diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/cmd/lxc_user_nic.c
similarity index 100%
rename from src/lxc/lxc_user_nic.c
rename to src/lxc/cmd/lxc_user_nic.c
From e0eb8b38a1d54388ff4677a31d6310c1535f5b55 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:54:30 +0100
Subject: [PATCH 09/30] cmd: move lxc-monitord
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 2 +-
src/lxc/{ => cmd}/lxc_monitord.c | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename src/lxc/{ => cmd}/lxc_monitord.c (100%)
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index e1eaabf99..aa4e41c26 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -290,10 +290,10 @@ lxc_wait_SOURCES = tools/lxc_wait.c tools/arguments.c
lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c
lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c
lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c
-lxc_monitord_SOURCES = lxc_monitord.c tools/arguments.c
# Binaries shipping with liblxc
init_lxc_SOURCES = cmd/lxc_init.c
+lxc_monitord_SOURCES = cmd/lxc_monitord.c
lxc_user_nic_SOURCES = cmd/lxc_user_nic.c namespace.c network.c
lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c
diff --git a/src/lxc/lxc_monitord.c b/src/lxc/cmd/lxc_monitord.c
similarity index 100%
rename from src/lxc/lxc_monitord.c
rename to src/lxc/cmd/lxc_monitord.c
From 258d0a0026287269ce018fdb2eb0cec32d014826 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 13:56:37 +0100
Subject: [PATCH 10/30] cmd: move lxc-update-config
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
configure.ac | 2 +-
src/lxc/Makefile.am | 2 +-
src/lxc/{tools => cmd}/lxc-update-config.in | 0
3 files changed, 2 insertions(+), 2 deletions(-)
rename src/lxc/{tools => cmd}/lxc-update-config.in (100%)
diff --git a/configure.ac b/configure.ac
index a841f9b9f..6bfed1017 100644
--- a/configure.ac
+++ b/configure.ac
@@ -940,8 +940,8 @@ AC_CONFIG_FILES([
src/lxc/Makefile
src/lxc/lxc.functions
src/lxc/cmd/lxc-checkconfig
+ src/lxc/cmd/lxc-update-config
src/lxc/tools/lxc-start-ephemeral
- src/lxc/tools/lxc-update-config
src/lxc/version.h
src/python-lxc/Makefile
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index aa4e41c26..68dfb6cb9 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -217,7 +217,7 @@ liblxc_la_CFLAGS += $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) $(NIH_DBUS_
endif
bin_SCRIPTS = cmd/lxc-checkconfig \
- tools/lxc-update-config
+ cmd/lxc-update-config
EXTRA_DIST = \
tools/lxc-top.lua
diff --git a/src/lxc/tools/lxc-update-config.in b/src/lxc/cmd/lxc-update-config.in
similarity index 100%
rename from src/lxc/tools/lxc-update-config.in
rename to src/lxc/cmd/lxc-update-config.in
From 1d598589f1ad6d67e3d96478ecc69ba969a6cfaf Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 14:02:10 +0100
Subject: [PATCH 11/30] tools: move lxc-checkpoint to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_checkpoint.c | 12 ++++--------
src/lxc/tools/tool_utils.c | 18 ++++++++++++++++++
src/lxc/tools/tool_utils.h | 1 +
3 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/src/lxc/tools/lxc_checkpoint.c b/src/lxc/tools/lxc_checkpoint.c
index 8f93934b3..f3f9e7415 100644
--- a/src/lxc/tools/lxc_checkpoint.c
+++ b/src/lxc/tools/lxc_checkpoint.c
@@ -1,5 +1,4 @@
/*
- *
* Copyright © 2014 Tycho Andersen <tycho.andersen at canonical.com>.
* Copyright © 2014 Canonical Ltd.
*
@@ -17,19 +16,18 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <stdio.h>
+#define _GNU_SOURCE
#include <errno.h>
+#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <lxc/lxccontainer.h>
-#include "log.h"
-#include "config.h"
-#include "lxc.h"
#include "arguments.h"
-#include "utils.h"
+#include "tool_utils.h"
static char *checkpoint_dir = NULL;
static bool stop = false;
@@ -253,8 +251,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
-
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index 39b388161..4b4dad0b4 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -276,6 +276,24 @@ int lxc_caps_up(void)
#endif
+int wait_for_pid(pid_t pid)
+{
+ int status, ret;
+
+again:
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ if (errno == EINTR)
+ goto again;
+ return -1;
+ }
+ if (ret != pid)
+ goto again;
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ return -1;
+ return 0;
+}
+
int lxc_wait_for_pid_status(pid_t pid)
{
int status, ret;
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index 59479dfa0..976995103 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -49,6 +49,7 @@ static inline int lxc_caps_init(void) {
}
#endif
+extern int wait_for_pid(pid_t pid);
extern int lxc_wait_for_pid_status(pid_t pid);
extern int lxc_safe_int(const char *numstr, int *converted);
extern int lxc_safe_long(const char *numstr, long int *converted);
From 940d8166247ee73c3e5bc4eac58254bef6942ed0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 14:05:21 +0100
Subject: [PATCH 12/30] tools: move lxc-clone to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_clone.c | 124 ++++++++++++++++++++++++++++------------------
1 file changed, 77 insertions(+), 47 deletions(-)
diff --git a/src/lxc/tools/lxc_clone.c b/src/lxc/tools/lxc_clone.c
index 3aed40739..4dca80b7b 100644
--- a/src/lxc/tools/lxc_clone.c
+++ b/src/lxc/tools/lxc_clone.c
@@ -17,25 +17,19 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
#include <getopt.h>
#include <signal.h>
+#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <sys/types.h>
-#include <stdint.h>
#include <sys/wait.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
#include <lxc/lxccontainer.h>
-#include "log.h"
-#include "config.h"
-#include "lxc.h"
-#include "conf.h"
-#include "state.h"
-
/* we pass fssize in bytes */
static uint64_t get_fssize(char *s)
{
@@ -43,30 +37,33 @@ static uint64_t get_fssize(char *s)
char *end;
ret = strtoull(s, &end, 0);
- if (end == s)
- {
- fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s);
+ if (end == s) {
+ fprintf(stderr,
+ "Invalid blockdev size '%s', using default size\n", s);
return 0;
}
+
while (isblank(*end))
end++;
- if (*end == '\0')
+ if (*end == '\0') {
ret *= 1024ULL * 1024ULL; /* MB by default */
- else if (*end == 'b' || *end == 'B')
+ } else if (*end == 'b' || *end == 'B') {
ret *= 1ULL;
- else if (*end == 'k' || *end == 'K')
+ } else if (*end == 'k' || *end == 'K') {
ret *= 1024ULL;
- else if (*end == 'm' || *end == 'M')
+ } else if (*end == 'm' || *end == 'M') {
ret *= 1024ULL * 1024ULL;
- else if (*end == 'g' || *end == 'G')
+ } else if (*end == 'g' || *end == 'G') {
ret *= 1024ULL * 1024ULL * 1024ULL;
- else if (*end == 't' || *end == 'T')
+ } else if (*end == 't' || *end == 'T') {
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
- else
- {
- fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s);
+ } else {
+ fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', "
+ "using default size\n",
+ *end, s);
return 0;
}
+
return ret;
}
@@ -124,42 +121,76 @@ int main(int argc, char *argv[])
if (argc < 3)
usage(argv[0]);
- while (1) {
- c = getopt_long(argc, argv, "sB:L:o:n:v:KMHp:P:Rt:h", options, &option_index);
+ while (true) {
+ c = getopt_long(argc, argv, "sB:L:o:n:v:KMHp:P:Rt:h", options,
+ &option_index);
if (c == -1)
break;
switch (c) {
- case 's': snapshot = 1; break;
- case 'B': bdevtype = optarg; break;
- case 'L': newsize = get_fssize(optarg); break;
- case 'o': orig = optarg; break;
- case 'n': new = optarg; break;
- case 'v': vgname = optarg; break;
- case 'K': keepname = 1; break;
- case 'M': keepmac = 1; break;
- case 'p': lxcpath = optarg; break;
- case 'P': newpath = optarg; break;
- case 'R': rename = 1; break;
- case 't': fstype = optarg; break;
- case 'h': usage(argv[0]);
- default: break;
+ case 's':
+ snapshot = 1;
+ break;
+ case 'B':
+ bdevtype = optarg;
+ break;
+ case 'L':
+ newsize = get_fssize(optarg);
+ break;
+ case 'o':
+ orig = optarg;
+ break;
+ case 'n':
+ new = optarg;
+ break;
+ case 'v':
+ vgname = optarg;
+ break;
+ case 'K':
+ keepname = 1;
+ break;
+ case 'M':
+ keepmac = 1;
+ break;
+ case 'p':
+ lxcpath = optarg;
+ break;
+ case 'P':
+ newpath = optarg;
+ break;
+ case 'R':
+ rename = 1;
+ break;
+ case 't':
+ fstype = optarg;
+ break;
+ case 'h':
+ usage(argv[0]);
+ default:
+ break;
}
}
- if (optind < argc && !orig)
+
+ if (optind < argc && !orig)
orig = argv[optind++];
- if (optind < argc && !new)
+
+ if (optind < argc && !new)
new = argv[optind++];
+
+ /* arguments for the clone hook */
if (optind < argc)
- /* arguments for the clone hook */
args = &argv[optind];
+
if (!new || !orig) {
printf("Error: you must provide orig and new names\n");
usage(argv[0]);
}
- if (snapshot) flags |= LXC_CLONE_SNAPSHOT;
- if (keepname) flags |= LXC_CLONE_KEEPNAME;
- if (keepmac) flags |= LXC_CLONE_KEEPMACADDR;
+ if (snapshot)
+ flags |= LXC_CLONE_SNAPSHOT;
+ if (keepname)
+ flags |= LXC_CLONE_KEEPNAME;
+ if (keepmac)
+ flags |= LXC_CLONE_KEEPMACADDR;
/* vgname and fstype could be supported by sending them through the
* bdevdata. However, they currently are not yet. I'm not convinced
@@ -201,8 +232,7 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
} else {
- c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize,
- args);
+ c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize, args);
if (c2 == NULL) {
lxc_container_put(c1);
fprintf(stderr, "clone failed\n");
From ace4a05a58a91ec49288c917e2b4f57534d3f571 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 14:08:43 +0100
Subject: [PATCH 13/30] cmd: move lxc-config to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_config.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/lxc/tools/lxc_config.c b/src/lxc/tools/lxc_config.c
index 86187bd57..682257f3d 100644
--- a/src/lxc/tools/lxc_config.c
+++ b/src/lxc/tools/lxc_config.c
@@ -23,8 +23,6 @@
#include <lxc/lxccontainer.h>
-#include "config.h"
-
struct lxc_config_items {
char *name;
};
From fbea3cbdb31e2d596419c07a845eee9feb1497cd Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 14:11:21 +0100
Subject: [PATCH 14/30] cmd: move lxc-console to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_console.c | 8 +-------
src/lxc/tools/tool_utils.c | 28 ++++++++++++++++++++++++++++
src/lxc/tools/tool_utils.h | 1 +
3 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/src/lxc/tools/lxc_console.c b/src/lxc/tools/lxc_console.c
index 876cbce58..f847811cb 100644
--- a/src/lxc/tools/lxc_console.c
+++ b/src/lxc/tools/lxc_console.c
@@ -39,12 +39,7 @@
#include <lxc/lxccontainer.h>
#include "arguments.h"
-#include "commands.h"
-#include "error.h"
-#include "log.h"
-#include "lxc.h"
-#include "mainloop.h"
-#include "utils.h"
+#include "tool_utils.h"
static char etoc(const char *expr)
{
@@ -115,7 +110,6 @@ int main(int argc, char *argv[])
ret = lxc_log_init(&log);
if (ret)
return EXIT_FAILURE;
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index 4b4dad0b4..00181ab65 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -17,7 +17,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
+#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
@@ -310,6 +312,32 @@ int lxc_wait_for_pid_status(pid_t pid)
return status;
}
+int lxc_safe_uint(const char *numstr, unsigned int *converted)
+{
+ char *err = NULL;
+ unsigned long int uli;
+
+ while (isspace(*numstr))
+ numstr++;
+
+ if (*numstr == '-')
+ return -EINVAL;
+
+ errno = 0;
+ uli = strtoul(numstr, &err, 0);
+ if (errno == ERANGE && uli == ULONG_MAX)
+ return -ERANGE;
+
+ if (err == numstr || *err != '\0')
+ return -EINVAL;
+
+ if (uli > UINT_MAX)
+ return -ERANGE;
+
+ *converted = (unsigned int)uli;
+ return 0;
+}
+
int lxc_safe_int(const char *numstr, int *converted)
{
char *err = NULL;
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index 976995103..26633ae5c 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -51,6 +51,7 @@ static inline int lxc_caps_init(void) {
extern int wait_for_pid(pid_t pid);
extern int lxc_wait_for_pid_status(pid_t pid);
+extern int lxc_safe_uint(const char *numstr, unsigned int *converted);
extern int lxc_safe_int(const char *numstr, int *converted);
extern int lxc_safe_long(const char *numstr, long int *converted);
From ab17b3e1023aa51c5539a42a2e3f2b765da7e602 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 14:27:23 +0100
Subject: [PATCH 15/30] tools: move lxc-copy to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/include/getsubopt.c | 89 +++++++++++++++++++++
src/lxc/tools/include/getsubopt.h | 4 +
src/lxc/tools/lxc_copy.c | 62 ++++++---------
src/lxc/tools/tool_utils.c | 159 ++++++++++++++++++++++++++++++++++++++
src/lxc/tools/tool_utils.h | 12 +++
5 files changed, 288 insertions(+), 38 deletions(-)
create mode 100644 src/lxc/tools/include/getsubopt.c
create mode 100644 src/lxc/tools/include/getsubopt.h
diff --git a/src/lxc/tools/include/getsubopt.c b/src/lxc/tools/include/getsubopt.c
new file mode 100644
index 000000000..b75497b1a
--- /dev/null
+++ b/src/lxc/tools/include/getsubopt.c
@@ -0,0 +1,89 @@
+/*
+ * Android c-library does not have getsubopt,
+ * so code lifted from uClibc
+ * http://git.uclibc.org/uClibc/tree/libc/unistd/getsubopt.c
+ */
+
+/* Parse comma separate list into words.
+ Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper at cygnus.com>, 1996.
+ The GNU C 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.
+ The GNU C 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 the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+char *strchrnul(const char *s, int c)
+{
+ char *result;
+
+ result = strchr( s, c );
+
+ if( !result )
+ {
+ result = (char *)s + strlen( s );
+ }
+
+ return( result );
+}
+
+/* Parse comma separated suboption from *OPTIONP and match against
+ strings in TOKENS. If found return index and set *VALUEP to
+ optional value introduced by an equal sign. If the suboption is
+ not part of TOKENS return in *VALUEP beginning of unknown
+ suboption. On exit *OPTIONP is set to the beginning of the next
+ token or at the terminating NUL character. */
+int
+getsubopt (char **optionp, char *const *tokens, char **valuep)
+{
+ char *endp, *vstart;
+ int cnt;
+
+ if (**optionp == '\0')
+ return -1;
+
+ /* Find end of next token. */
+ endp = strchrnul (*optionp, ',');
+
+ /* Find start of value. */
+ vstart = memchr (*optionp, '=', endp - *optionp);
+ if (vstart == NULL)
+ vstart = endp;
+
+ /* Try to match the characters between *OPTIONP and VSTART against
+ one of the TOKENS. */
+ for (cnt = 0; tokens[cnt] != NULL; ++cnt)
+ if (strncmp (*optionp, tokens[cnt], vstart - *optionp) == 0
+ && tokens[cnt][vstart - *optionp] == '\0')
+ {
+ /* We found the current option in TOKENS. */
+ *valuep = vstart != endp ? vstart + 1 : NULL;
+
+ if (*endp != '\0')
+ *endp++ = '\0';
+ *optionp = endp;
+
+ return cnt;
+ }
+
+ /* The current suboption does not match any option. */
+ *valuep = *optionp;
+
+ if (*endp != '\0')
+ *endp++ = '\0';
+ *optionp = endp;
+
+ return -1;
+}
diff --git a/src/lxc/tools/include/getsubopt.h b/src/lxc/tools/include/getsubopt.h
new file mode 100644
index 000000000..e45cf66b0
--- /dev/null
+++ b/src/lxc/tools/include/getsubopt.h
@@ -0,0 +1,4 @@
+#ifndef _GETSUBOPT_H
+#define _GETSUBOPT_H
+int getsubopt (char **optionp, char *const *tokens, char **valuep);
+#endif
diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c
index 1718f84a7..ae8b81021 100644
--- a/src/lxc/tools/lxc_copy.c
+++ b/src/lxc/tools/lxc_copy.c
@@ -17,37 +17,29 @@
*/
#define _GNU_SOURCE
-#include "config.h"
-
-#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
-#include <stdio.h>
-#include <sys/types.h>
+#include <stdbool.h>
#include <stdint.h>
-#include <sys/wait.h>
+#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#include <string.h>
#include <time.h>
-#include <stdbool.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include <lxc/lxccontainer.h>
-#include "attach.h"
-#include "log.h"
-#include "confile.h"
#include "arguments.h"
-#include "lxc.h"
-#include "conf.h"
-#include "state.h"
-#include "storage.h"
-#include "utils.h"
+#include "tool_utils.h"
#ifndef HAVE_GETSUBOPT
-#include <../include/getsubopt.h>
+#include "include/getsubopt.h"
#endif
enum mnttype {
@@ -186,7 +178,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(ret);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
@@ -273,17 +264,17 @@ static struct mnts *add_mnt(struct mnts **mnts, unsigned int *num, enum mnttype
static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_arguments *arg)
{
- char upperdir[MAXPATHLEN];
- char workdir[MAXPATHLEN];
+ char upperdir[TOOL_MAXPATHLEN];
+ char workdir[TOOL_MAXPATHLEN];
unsigned int i;
int ret;
struct mnts *m = NULL;
for (i = 0, m = mnts; i < num; i++, m++) {
if ((m->mnt_type == LXC_MNT_OVL) || (m->mnt_type == LXC_MNT_AUFS)) {
- ret = snprintf(upperdir, MAXPATHLEN, "%s/%s/delta#XXXXXX",
+ ret = snprintf(upperdir, TOOL_MAXPATHLEN, "%s/%s/delta#XXXXXX",
arg->newpath, arg->newname);
- if (ret < 0 || ret >= MAXPATHLEN)
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return -1;
if (!mkdtemp(upperdir))
return -1;
@@ -293,9 +284,9 @@ static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_argu
}
if (m->mnt_type == LXC_MNT_OVL) {
- ret = snprintf(workdir, MAXPATHLEN, "%s/%s/work#XXXXXX",
+ ret = snprintf(workdir, TOOL_MAXPATHLEN, "%s/%s/work#XXXXXX",
arg->newpath, arg->newname);
- if (ret < 0 || ret >= MAXPATHLEN)
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return -1;
if (!mkdtemp(workdir))
return -1;
@@ -400,19 +391,19 @@ static int do_clone(struct lxc_container *c, char *newname, char *newpath,
static int do_clone_ephemeral(struct lxc_container *c,
struct lxc_arguments *arg, char **args, int flags)
{
- char *bdev;
char *premount;
- char randname[MAXPATHLEN];
+ char randname[TOOL_MAXPATHLEN];
unsigned int i;
int ret = 0;
bool bret = true, started = false;
+ char *tmp_buf = randname;
struct lxc_container *clone;
lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
attach_options.env_policy = LXC_ATTACH_CLEAR_ENV;
if (!arg->newname) {
- ret = snprintf(randname, MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ ret = snprintf(randname, TOOL_MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name);
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return -1;
if (!mkdtemp(randname))
return -1;
@@ -429,12 +420,6 @@ static int do_clone_ephemeral(struct lxc_container *c,
return -1;
if (arg->tmpfs) {
- bdev = c->lxc_conf->rootfs.bdev_type;
- if (bdev && strcmp(bdev, "dir")) {
- fprintf(stderr, "Cannot currently use tmpfs with %s storage backend.\n", bdev);
- goto destroy_and_put;
- }
-
premount = mount_tmpfs(arg->name, arg->newname, arg->newpath, arg);
if (!premount)
goto destroy_and_put;
@@ -501,7 +486,8 @@ static int do_clone_ephemeral(struct lxc_container *c,
destroy_and_put:
if (started)
clone->shutdown(clone, -1);
- if (!started || clone->lxc_conf->ephemeral != 1)
+ ret = clone->get_config_item(clone, "lxc.ephemeral", tmp_buf, TOOL_MAXPATHLEN);
+ if (ret > 0 && strcmp(tmp_buf, "0"))
clone->destroy(clone);
free_mnts();
lxc_container_put(clone);
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index 00181ab65..29adc6776 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <linux/sched.h>
#include <sys/prctl.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -380,3 +381,161 @@ int lxc_safe_long(const char *numstr, long int *converted)
*converted = sli;
return 0;
}
+
+void lxc_free_array(void **array, lxc_free_fn element_free_fn)
+{
+ void **p;
+ for (p = array; p && *p; p++)
+ element_free_fn(*p);
+ free((void*)array);
+}
+
+int lxc_grow_array(void ***array, size_t* capacity, size_t new_size, size_t capacity_increment)
+{
+ size_t new_capacity;
+ void **new_array;
+
+ /* first time around, catch some trivial mistakes of the user
+ * only initializing one of these */
+ if (!*array || !*capacity) {
+ *array = NULL;
+ *capacity = 0;
+ }
+
+ new_capacity = *capacity;
+ while (new_size + 1 > new_capacity)
+ new_capacity += capacity_increment;
+ if (new_capacity != *capacity) {
+ /* we have to reallocate */
+ new_array = realloc(*array, new_capacity * sizeof(void *));
+ if (!new_array)
+ return -1;
+ memset(&new_array[*capacity], 0, (new_capacity - (*capacity)) * sizeof(void *));
+ *array = new_array;
+ *capacity = new_capacity;
+ }
+
+ /* array has sufficient elements */
+ return 0;
+}
+
+char **lxc_string_split(const char *string, char _sep)
+{
+ char *token, *str, *saveptr = NULL;
+ char sep[2] = {_sep, '\0'};
+ char **tmp = NULL, **result = NULL;
+ size_t result_capacity = 0;
+ size_t result_count = 0;
+ int r, saved_errno;
+
+ if (!string)
+ return calloc(1, sizeof(char *));
+
+ str = alloca(strlen(string) + 1);
+ strcpy(str, string);
+ for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
+ r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
+ if (r < 0)
+ goto error_out;
+ result[result_count] = strdup(token);
+ if (!result[result_count])
+ goto error_out;
+ result_count++;
+ }
+
+ /* if we allocated too much, reduce it */
+ tmp = realloc(result, (result_count + 1) * sizeof(char *));
+ if (!tmp)
+ goto error_out;
+ result = tmp;
+ /* Make sure we don't return uninitialized memory. */
+ if (result_count == 0)
+ *result = NULL;
+ return result;
+error_out:
+ saved_errno = errno;
+ lxc_free_array((void **)result, free);
+ errno = saved_errno;
+ return NULL;
+}
+
+char **lxc_normalize_path(const char *path)
+{
+ char **components;
+ char **p;
+ size_t components_len = 0;
+ size_t pos = 0;
+
+ components = lxc_string_split(path, '/');
+ if (!components)
+ return NULL;
+ for (p = components; *p; p++)
+ components_len++;
+
+ /* resolve '.' and '..' */
+ for (pos = 0; pos < components_len; ) {
+ if (!strcmp(components[pos], ".") || (!strcmp(components[pos], "..") && pos == 0)) {
+ /* eat this element */
+ free(components[pos]);
+ memmove(&components[pos], &components[pos+1], sizeof(char *) * (components_len - pos));
+ components_len--;
+ } else if (!strcmp(components[pos], "..")) {
+ /* eat this and the previous element */
+ free(components[pos - 1]);
+ free(components[pos]);
+ memmove(&components[pos-1], &components[pos+1], sizeof(char *) * (components_len - pos));
+ components_len -= 2;
+ pos--;
+ } else {
+ pos++;
+ }
+ }
+
+ return components;
+}
+
+char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix)
+{
+ char *result;
+ char **p;
+ size_t sep_len = strlen(sep);
+ size_t result_len = use_as_prefix * sep_len;
+
+ /* calculate new string length */
+ for (p = (char **)parts; *p; p++)
+ result_len += (p > (char **)parts) * sep_len + strlen(*p);
+
+ result = calloc(result_len + 1, 1);
+ if (!result)
+ return NULL;
+
+ if (use_as_prefix)
+ strcpy(result, sep);
+ for (p = (char **)parts; *p; p++) {
+ if (p > (char **)parts)
+ strcat(result, sep);
+ strcat(result, *p);
+ }
+
+ return result;
+}
+
+int is_dir(const char *path)
+{
+ struct stat statbuf;
+ int ret = stat(path, &statbuf);
+ if (ret == 0 && S_ISDIR(statbuf.st_mode))
+ return 1;
+ return 0;
+}
+
+size_t lxc_array_len(void **array)
+{
+ void **p;
+ size_t result = 0;
+
+ for (p = array; p && *p; p++)
+ result++;
+
+ return result;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index 26633ae5c..12ef11819 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -55,4 +55,16 @@ extern int lxc_safe_uint(const char *numstr, unsigned int *converted);
extern int lxc_safe_int(const char *numstr, int *converted);
extern int lxc_safe_long(const char *numstr, long int *converted);
+typedef void (*lxc_free_fn)(void *);
+extern void lxc_free_array(void **array, lxc_free_fn element_free_fn);
+extern size_t lxc_array_len(void **array);
+extern int lxc_grow_array(void ***array, size_t *capacity, size_t new_size,
+ size_t capacity_increment);
+extern char **lxc_string_split(const char *string, char _sep);
+extern char **lxc_normalize_path(const char *path);
+extern char *lxc_string_join(const char *sep, const char **parts,
+ bool use_as_prefix);
+
+extern int is_dir(const char *path);
+
#endif /* __LXC_UTILS_H */
From d5ae8d2d13764a567878182f1c7431a3032c3fc6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 14:33:06 +0100
Subject: [PATCH 16/30] tools: move lxc-create to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_create.c | 30 +++++++++++++++++-------
src/lxc/tools/tool_utils.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++
src/lxc/tools/tool_utils.h | 3 +++
3 files changed, 82 insertions(+), 8 deletions(-)
diff --git a/src/lxc/tools/lxc_create.c b/src/lxc/tools/lxc_create.c
index f702c2ba7..9a4640316 100644
--- a/src/lxc/tools/lxc_create.c
+++ b/src/lxc/tools/lxc_create.c
@@ -22,16 +22,14 @@
#include <libgen.h>
#include <stdint.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
-#include <lxc/lxccontainer.h>
#include <sys/types.h>
+#include <lxc/lxccontainer.h>
+
#include "arguments.h"
-#include "log.h"
-#include "lxc.h"
-#include "storage.h"
-#include "storage_utils.h"
-#include "utils.h"
+#include "tool_utils.h"
static uint64_t get_fssize(char *s)
{
@@ -203,6 +201,23 @@ static bool validate_bdev_args(struct lxc_arguments *a)
return true;
}
+static bool is_valid_storage_type(const char *type)
+{
+ if (strcmp(type, "dir") == 0 ||
+ strcmp(type, "btrfs") == 0 ||
+ strcmp(type, "aufs") == 0 ||
+ strcmp(type, "loop") == 0 ||
+ strcmp(type, "lvm") == 0 ||
+ strcmp(type, "nbd") == 0 ||
+ strcmp(type, "overlay") == 0 ||
+ strcmp(type, "overlayfs") == 0 ||
+ strcmp(type, "rbd") == 0 ||
+ strcmp(type, "zfs") == 0)
+ return true;
+
+ return false;
+}
+
int main(int argc, char *argv[])
{
struct lxc_container *c;
@@ -225,7 +240,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
@@ -286,7 +300,7 @@ int main(int argc, char *argv[])
if (my_args.configfile)
c->load_config(c, my_args.configfile);
else
- c->load_config(c, lxc_global_config_value("lxc.default_config"));
+ c->load_config(c, lxc_get_global_config_item("lxc.default_config"));
if (my_args.fstype)
spec.fstype = my_args.fstype;
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index 29adc6776..94f118e63 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -539,3 +539,60 @@ size_t lxc_array_len(void **array)
return result;
}
+
+/*
+ * Given the '-t' template option to lxc-create, figure out what to
+ * do. If the template is a full executable path, use that. If it
+ * is something like 'sshd', then return $templatepath/lxc-sshd.
+ * On success return the template, on error return NULL.
+ */
+char *get_template_path(const char *t)
+{
+ int ret, len;
+ char *tpath;
+
+ if (t[0] == '/' && access(t, X_OK) == 0) {
+ tpath = strdup(t);
+ return tpath;
+ }
+
+ len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
+ tpath = malloc(len);
+ if (!tpath)
+ return NULL;
+ ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
+ if (ret < 0 || ret >= len) {
+ free(tpath);
+ return NULL;
+ }
+ if (access(tpath, X_OK) < 0) {
+ fprintf(stderr, "Bad template: %s\n", t);
+ free(tpath);
+ return NULL;
+ }
+
+ return tpath;
+}
+
+int mkdir_p(const char *dir, mode_t mode)
+{
+ const char *tmp = dir;
+ const char *orig = dir;
+ char *makeme;
+
+ do {
+ dir = tmp + strspn(tmp, "/");
+ tmp = dir + strcspn(dir, "/");
+ makeme = strndup(orig, dir - orig);
+ if (*makeme) {
+ if (mkdir(makeme, mode) && errno != EEXIST) {
+ fprintf(stderr, "Failed to create directory \"%s\"\n", makeme);
+ free(makeme);
+ return -1;
+ }
+ }
+ free(makeme);
+ } while(tmp != dir);
+
+ return 0;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index 12ef11819..258f4223c 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -65,6 +65,9 @@ extern char **lxc_normalize_path(const char *path);
extern char *lxc_string_join(const char *sep, const char **parts,
bool use_as_prefix);
+extern int mkdir_p(const char *dir, mode_t mode);
extern int is_dir(const char *path);
+extern char *get_template_path(const char *t);
+
#endif /* __LXC_UTILS_H */
From 442d6e6cfbb9cf7d8cbddacc3e6ed6e0aec16e1b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 14:39:21 +0100
Subject: [PATCH 17/30] tools: move lxc-destroy to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_destroy.c | 40 ++++++++++++++++++++++------------------
src/lxc/tools/tool_utils.c | 7 +++++++
src/lxc/tools/tool_utils.h | 1 +
3 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/src/lxc/tools/lxc_destroy.c b/src/lxc/tools/lxc_destroy.c
index 1c3f7dc50..48484a6be 100644
--- a/src/lxc/tools/lxc_destroy.c
+++ b/src/lxc/tools/lxc_destroy.c
@@ -18,19 +18,18 @@
*/
#define _GNU_SOURCE
-#include "config.h"
-
+#include <fcntl.h>
#include <libgen.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <lxc/lxccontainer.h>
#include "arguments.h"
-#include "log.h"
-#include "lxc.h"
-#include "utils.h"
+#include "tool_utils.h"
static int my_parser(struct lxc_arguments* args, int c, char* arg);
static bool quiet;
@@ -83,7 +82,7 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
+
if (my_args.quiet)
quiet = true;
@@ -155,11 +154,11 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
static bool do_destroy(struct lxc_container *c)
{
bool bret = true;
- char path[MAXPATHLEN];
+ char path[TOOL_MAXPATHLEN];
/* First check whether the container has dependent clones or snapshots. */
- int ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ int ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return false;
if (file_exists(path)) {
@@ -168,8 +167,8 @@ static bool do_destroy(struct lxc_container *c)
return false;
}
- ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return false;
if (rmdir(path) < 0 && errno != ENOENT) {
@@ -189,8 +188,13 @@ static bool do_destroy(struct lxc_container *c)
/* If the container was ephemeral we have already removed it when we
* stopped it. */
- if (c->is_defined(c) && !c->lxc_conf->ephemeral)
- bret = c->destroy(c);
+ if (c->is_defined(c)) {
+ char buf[256];
+ ret = c->get_config_item(c, "lxc.ephemeral", buf, 256);
+ if (ret > 0 && strcmp(buf, "0") == 0) {
+ bret = c->destroy(c);
+ }
+ }
if (!bret) {
if (!quiet)
@@ -206,7 +210,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
struct lxc_container *c1;
struct stat fbuf;
bool bret = false;
- char path[MAXPATHLEN];
+ char path[TOOL_MAXPATHLEN];
char *buf = NULL;
char *lxcpath = NULL;
char *lxcname = NULL;
@@ -216,8 +220,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
int counter = 0;
/* Destroy clones. */
- ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return false;
fd = open(path, O_RDONLY | O_CLOEXEC);
@@ -268,8 +272,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
}
/* Destroy snapshots located in the containers snap/ folder. */
- ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return false;
if (rmdir(path) < 0 && errno != ENOENT)
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index 94f118e63..e50f50273 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -596,3 +596,10 @@ int mkdir_p(const char *dir, mode_t mode)
return 0;
}
+
+bool file_exists(const char *f)
+{
+ struct stat statbuf;
+
+ return stat(f, &statbuf) == 0;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index 258f4223c..1ba18f6d9 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -66,6 +66,7 @@ extern char *lxc_string_join(const char *sep, const char **parts,
bool use_as_prefix);
extern int mkdir_p(const char *dir, mode_t mode);
+extern bool file_exists(const char *f);
extern int is_dir(const char *path);
extern char *get_template_path(const char *t);
From 39ab625671e21f135a6429a67e26b291f714cadc Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 14:46:46 +0100
Subject: [PATCH 18/30] tools: move lxc-device to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/arguments.h | 1 -
src/lxc/tools/include/ifaddrs.c | 599 ++++++++++++++++++++++++++++++++++++++++
src/lxc/tools/include/ifaddrs.h | 54 ++++
src/lxc/tools/lxc_cgroup.c | 1 +
src/lxc/tools/lxc_device.c | 16 +-
src/lxc/tools/tool_utils.c | 27 ++
src/lxc/tools/tool_utils.h | 4 +
7 files changed, 692 insertions(+), 10 deletions(-)
create mode 100644 src/lxc/tools/include/ifaddrs.c
create mode 100644 src/lxc/tools/include/ifaddrs.h
diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h
index bd491a32b..15941bcc3 100644
--- a/src/lxc/tools/arguments.h
+++ b/src/lxc/tools/arguments.h
@@ -31,7 +31,6 @@
#include <sys/types.h>
#include <lxc/lxccontainer.h>
-#define TOOL_MAXPATHLEN 4096
struct lxc_arguments;
typedef int (*lxc_arguments_parser_t)(struct lxc_arguments *, int, char *);
diff --git a/src/lxc/tools/include/ifaddrs.c b/src/lxc/tools/include/ifaddrs.c
new file mode 100644
index 000000000..1f954dd7d
--- /dev/null
+++ b/src/lxc/tools/include/ifaddrs.c
@@ -0,0 +1,599 @@
+/*
+Copyright (c) 2013, Kenneth MacKay
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "ifaddrs.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+typedef struct NetlinkList
+{
+ struct NetlinkList *m_next;
+ struct nlmsghdr *m_data;
+ unsigned int m_size;
+} NetlinkList;
+
+static int netlink_socket(void)
+{
+ int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if(l_socket < 0)
+ {
+ return -1;
+ }
+
+ struct sockaddr_nl l_addr;
+ memset(&l_addr, 0, sizeof(l_addr));
+ l_addr.nl_family = AF_NETLINK;
+ if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
+ {
+ close(l_socket);
+ return -1;
+ }
+
+ return l_socket;
+}
+
+static int netlink_send(int p_socket, int p_request)
+{
+ char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
+ memset(l_buffer, 0, sizeof(l_buffer));
+ struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer;
+ struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
+
+ l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
+ l_hdr->nlmsg_type = p_request;
+ l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+ l_hdr->nlmsg_pid = 0;
+ l_hdr->nlmsg_seq = p_socket;
+ l_msg->rtgen_family = AF_UNSPEC;
+
+ struct sockaddr_nl l_addr;
+ memset(&l_addr, 0, sizeof(l_addr));
+ l_addr.nl_family = AF_NETLINK;
+ return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
+}
+
+static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
+{
+ struct msghdr l_msg;
+ struct iovec l_iov = { p_buffer, p_len };
+ struct sockaddr_nl l_addr;
+
+ for(;;)
+ {
+ l_msg.msg_name = (void *)&l_addr;
+ l_msg.msg_namelen = sizeof(l_addr);
+ l_msg.msg_iov = &l_iov;
+ l_msg.msg_iovlen = 1;
+ l_msg.msg_control = NULL;
+ l_msg.msg_controllen = 0;
+ l_msg.msg_flags = 0;
+ int l_result = recvmsg(p_socket, &l_msg, 0);
+
+ if(l_result < 0)
+ {
+ if(errno == EINTR)
+ {
+ continue;
+ }
+ return -2;
+ }
+
+ if(l_msg.msg_flags & MSG_TRUNC)
+ { // buffer was too small
+ return -1;
+ }
+ return l_result;
+ }
+}
+
+static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
+{
+ size_t l_size = 4096;
+ void *l_buffer = NULL;
+
+ for(;;)
+ {
+ free(l_buffer);
+ l_buffer = malloc(l_size);
+
+ int l_read = netlink_recv(p_socket, l_buffer, l_size);
+ *p_size = l_read;
+ if(l_read == -2)
+ {
+ free(l_buffer);
+ return NULL;
+ }
+ if(l_read >= 0)
+ {
+ pid_t l_pid = getpid();
+ struct nlmsghdr *l_hdr;
+ for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
+ {
+ if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+ {
+ continue;
+ }
+
+ if(l_hdr->nlmsg_type == NLMSG_DONE)
+ {
+ *p_done = 1;
+ break;
+ }
+
+ if(l_hdr->nlmsg_type == NLMSG_ERROR)
+ {
+ free(l_buffer);
+ return NULL;
+ }
+ }
+ return l_buffer;
+ }
+
+ l_size *= 2;
+ }
+}
+
+static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
+{
+ NetlinkList *l_item = malloc(sizeof(NetlinkList));
+ l_item->m_next = NULL;
+ l_item->m_data = p_data;
+ l_item->m_size = p_size;
+ return l_item;
+}
+
+static void freeResultList(NetlinkList *p_list)
+{
+ NetlinkList *l_cur;
+ while(p_list)
+ {
+ l_cur = p_list;
+ p_list = p_list->m_next;
+ free(l_cur->m_data);
+ free(l_cur);
+ }
+}
+
+static NetlinkList *getResultList(int p_socket, int p_request)
+{
+ if(netlink_send(p_socket, p_request) < 0)
+ {
+ return NULL;
+ }
+
+ NetlinkList *l_list = NULL;
+ NetlinkList *l_end = NULL;
+ int l_size;
+ int l_done = 0;
+ while(!l_done)
+ {
+ struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
+ if(!l_hdr)
+ { // error
+ freeResultList(l_list);
+ return NULL;
+ }
+
+ NetlinkList *l_item = newListItem(l_hdr, l_size);
+ if(!l_list)
+ {
+ l_list = l_item;
+ }
+ else
+ {
+ l_end->m_next = l_item;
+ }
+ l_end = l_item;
+ }
+ return l_list;
+}
+
+static size_t maxSize(size_t a, size_t b)
+{
+ return (a > b ? a : b);
+}
+
+static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
+{
+ switch(p_family)
+ {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+ case AF_PACKET:
+ return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
+ default:
+ return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
+ }
+}
+
+static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
+{
+ switch(p_family)
+ {
+ case AF_INET:
+ memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
+ break;
+ case AF_INET6:
+ memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
+ break;
+ case AF_PACKET:
+ memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
+ ((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
+ break;
+ default:
+ memcpy(p_dest->sa_data, p_data, p_size);
+ break;
+ }
+ p_dest->sa_family = p_family;
+}
+
+static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
+{
+ if(!*p_resultList)
+ {
+ *p_resultList = p_entry;
+ }
+ else
+ {
+ struct ifaddrs *l_cur = *p_resultList;
+ while(l_cur->ifa_next)
+ {
+ l_cur = l_cur->ifa_next;
+ }
+ l_cur->ifa_next = p_entry;
+ }
+}
+
+static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
+{
+ struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
+
+ size_t l_nameSize = 0;
+ size_t l_addrSize = 0;
+ size_t l_dataSize = 0;
+
+ size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
+ struct rtattr *l_rta;
+ for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+ {
+ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
+ switch(l_rta->rta_type)
+ {
+ case IFLA_ADDRESS:
+ case IFLA_BROADCAST:
+ l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
+ break;
+ case IFLA_IFNAME:
+ l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
+ break;
+ case IFLA_STATS:
+ l_dataSize += NLMSG_ALIGN(l_rtaSize);
+ break;
+ default:
+ break;
+ }
+ }
+
+ struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize);
+ memset(l_entry, 0, sizeof(struct ifaddrs));
+ l_entry->ifa_name = "";
+
+ char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
+ char *l_addr = l_name + l_nameSize;
+ char *l_data = l_addr + l_addrSize;
+
+ l_entry->ifa_flags = l_info->ifi_flags;
+
+ l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
+ for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+ {
+ void *l_rtaData = RTA_DATA(l_rta);
+ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
+ switch(l_rta->rta_type)
+ {
+ case IFLA_ADDRESS:
+ case IFLA_BROADCAST:
+ {
+ size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
+ makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
+ ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
+ ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
+ if(l_rta->rta_type == IFLA_ADDRESS)
+ {
+ l_entry->ifa_addr = (struct sockaddr *)l_addr;
+ }
+ else
+ {
+ l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
+ }
+ l_addr += NLMSG_ALIGN(l_addrLen);
+ break;
+ }
+ case IFLA_IFNAME:
+ strncpy(l_name, l_rtaData, l_rtaDataSize);
+ l_name[l_rtaDataSize] = '\0';
+ l_entry->ifa_name = l_name;
+ break;
+ case IFLA_STATS:
+ memcpy(l_data, l_rtaData, l_rtaDataSize);
+ l_entry->ifa_data = l_data;
+ break;
+ default:
+ break;
+ }
+ }
+
+ addToEnd(p_resultList, l_entry);
+ p_links[l_info->ifi_index - 1] = l_entry;
+}
+
+static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
+{
+ struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
+
+ size_t l_nameSize = 0;
+ size_t l_addrSize = 0;
+
+ int l_addedNetmask = 0;
+
+ size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
+ struct rtattr *l_rta;
+ for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+ {
+ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
+ if(l_info->ifa_family == AF_PACKET)
+ {
+ continue;
+ }
+
+ switch(l_rta->rta_type)
+ {
+ case IFA_ADDRESS:
+ case IFA_LOCAL:
+ if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
+ { // make room for netmask
+ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
+ l_addedNetmask = 1;
+ }
+ case IFA_BROADCAST:
+ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
+ break;
+ case IFA_LABEL:
+ l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
+ memset(l_entry, 0, sizeof(struct ifaddrs));
+ l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name;
+
+ char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
+ char *l_addr = l_name + l_nameSize;
+
+ l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags;
+
+ l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
+ for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+ {
+ void *l_rtaData = RTA_DATA(l_rta);
+ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
+ switch(l_rta->rta_type)
+ {
+ case IFA_ADDRESS:
+ case IFA_BROADCAST:
+ case IFA_LOCAL:
+ {
+ size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
+ makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
+ if(l_info->ifa_family == AF_INET6)
+ {
+ if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
+ {
+ ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
+ }
+ }
+
+ if(l_rta->rta_type == IFA_ADDRESS)
+ { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
+ if(l_entry->ifa_addr)
+ {
+ l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
+ }
+ else
+ {
+ l_entry->ifa_addr = (struct sockaddr *)l_addr;
+ }
+ }
+ else if(l_rta->rta_type == IFA_LOCAL)
+ {
+ if(l_entry->ifa_addr)
+ {
+ l_entry->ifa_dstaddr = l_entry->ifa_addr;
+ }
+ l_entry->ifa_addr = (struct sockaddr *)l_addr;
+ }
+ else
+ {
+ l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
+ }
+ l_addr += NLMSG_ALIGN(l_addrLen);
+ break;
+ }
+ case IFA_LABEL:
+ strncpy(l_name, l_rtaData, l_rtaDataSize);
+ l_name[l_rtaDataSize] = '\0';
+ l_entry->ifa_name = l_name;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
+ {
+ unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
+ unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
+ char l_mask[16] = {0};
+ unsigned i;
+ for(i=0; i<(l_prefix/8); ++i)
+ {
+ l_mask[i] = 0xff;
+ }
+ if (l_prefix % 8) {
+ l_mask[i] = 0xff << (8 - (l_prefix % 8));
+ }
+
+ makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
+ l_entry->ifa_netmask = (struct sockaddr *)l_addr;
+ }
+
+ addToEnd(p_resultList, l_entry);
+}
+
+static void interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
+{
+ pid_t l_pid = getpid();
+ for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
+ {
+ unsigned int l_nlsize = p_netlinkList->m_size;
+ struct nlmsghdr *l_hdr;
+ for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
+ {
+ if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+ {
+ continue;
+ }
+
+ if(l_hdr->nlmsg_type == NLMSG_DONE)
+ {
+ break;
+ }
+
+ if(l_hdr->nlmsg_type == RTM_NEWLINK)
+ {
+ interpretLink(l_hdr, p_links, p_resultList);
+ }
+ else if(l_hdr->nlmsg_type == RTM_NEWADDR)
+ {
+ interpretAddr(l_hdr, p_links, p_resultList);
+ }
+ }
+ }
+}
+
+static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList)
+{
+ unsigned l_links = 0;
+ pid_t l_pid = getpid();
+ for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
+ {
+ unsigned int l_nlsize = p_netlinkList->m_size;
+ struct nlmsghdr *l_hdr;
+ for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
+ {
+ if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+ {
+ continue;
+ }
+
+ if(l_hdr->nlmsg_type == NLMSG_DONE)
+ {
+ break;
+ }
+
+ if(l_hdr->nlmsg_type == RTM_NEWLINK)
+ {
+ ++l_links;
+ }
+ }
+ }
+
+ return l_links;
+}
+
+int getifaddrs(struct ifaddrs **ifap)
+{
+ if(!ifap)
+ {
+ return -1;
+ }
+ *ifap = NULL;
+
+ int l_socket = netlink_socket();
+ if(l_socket < 0)
+ {
+ return -1;
+ }
+
+ NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
+ if(!l_linkResults)
+ {
+ close(l_socket);
+ return -1;
+ }
+
+ NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
+ if(!l_addrResults)
+ {
+ close(l_socket);
+ freeResultList(l_linkResults);
+ return -1;
+ }
+
+ unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
+ struct ifaddrs *l_links[l_numLinks];
+ memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
+
+ interpret(l_socket, l_linkResults, l_links, ifap);
+ interpret(l_socket, l_addrResults, l_links, ifap);
+
+ freeResultList(l_linkResults);
+ freeResultList(l_addrResults);
+ close(l_socket);
+ return 0;
+}
+
+void freeifaddrs(struct ifaddrs *ifa)
+{
+ struct ifaddrs *l_cur;
+ while(ifa)
+ {
+ l_cur = ifa;
+ ifa = ifa->ifa_next;
+ free(l_cur);
+ }
+}
diff --git a/src/lxc/tools/include/ifaddrs.h b/src/lxc/tools/include/ifaddrs.h
new file mode 100644
index 000000000..9cd19fec1
--- /dev/null
+++ b/src/lxc/tools/include/ifaddrs.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1995, 1999
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
+ */
+
+#ifndef _IFADDRS_H_
+#define _IFADDRS_H_
+
+struct ifaddrs {
+ struct ifaddrs *ifa_next;
+ char *ifa_name;
+ unsigned int ifa_flags;
+ struct sockaddr *ifa_addr;
+ struct sockaddr *ifa_netmask;
+ struct sockaddr *ifa_dstaddr;
+ void *ifa_data;
+};
+
+/*
+ * This may have been defined in <net/if.h>. Note that if <net/if.h> is
+ * to be included it must be included before this header file.
+ */
+#ifndef ifa_broadaddr
+#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
+#endif
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int getifaddrs(struct ifaddrs **ifap);
+extern void freeifaddrs(struct ifaddrs *ifa);
+__END_DECLS
+
+#endif
diff --git a/src/lxc/tools/lxc_cgroup.c b/src/lxc/tools/lxc_cgroup.c
index 3624e80b7..231cc7b7c 100644
--- a/src/lxc/tools/lxc_cgroup.c
+++ b/src/lxc/tools/lxc_cgroup.c
@@ -32,6 +32,7 @@
#include <lxc/lxccontainer.h>
#include "arguments.h"
+#include "tool_utils.h"
static int my_checker(const struct lxc_arguments* args)
{
diff --git a/src/lxc/tools/lxc_device.c b/src/lxc/tools/lxc_device.c
index f73e8c2cb..501bc99a0 100644
--- a/src/lxc/tools/lxc_device.c
+++ b/src/lxc/tools/lxc_device.c
@@ -18,25 +18,24 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#define _GNU_SOURCE
+#include <libgen.h>
+#include <limits.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#include <sys/types.h>
-#include <libgen.h>
-#include <string.h>
-#include <limits.h>
#include <lxc/lxccontainer.h>
-#include "utils.h"
-#include "lxc.h"
-#include "log.h"
-
#include "arguments.h"
+#include "tool_utils.h"
#if HAVE_IFADDRS_H
#include <ifaddrs.h>
#else
-#include <../include/ifaddrs.h>
+#include "include/ifaddrs.h"
#endif
static const struct option my_longopts[] = {
@@ -123,7 +122,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
goto err;
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index e50f50273..42be4d249 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -21,7 +21,9 @@
#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
+#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -603,3 +605,28 @@ bool file_exists(const char *f)
return stat(f, &statbuf) == 0;
}
+
+bool switch_to_ns(pid_t pid, const char *ns) {
+ int fd, ret;
+ char nspath[TOOL_MAXPATHLEN];
+
+ /* Switch to new ns */
+ ret = snprintf(nspath, TOOL_MAXPATHLEN, "/proc/%d/ns/%s", pid, ns);
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
+ return false;
+
+ fd = open(nspath, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s\n", nspath);
+ return false;
+ }
+
+ ret = setns(fd, 0);
+ if (ret) {
+ fprintf(stderr, "Failed to set process %d to %s of %d\n", pid, ns, fd);
+ close(fd);
+ return false;
+ }
+ close(fd);
+ return true;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index 1ba18f6d9..2ce2afd0a 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -29,6 +29,8 @@
#include <stdbool.h>
#include <unistd.h>
+#define TOOL_MAXPATHLEN 4096
+
extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
extern signed long lxc_config_parse_arch(const char *arch);
extern int lxc_namespace_2_cloneflag(const char *namespace);
@@ -71,4 +73,6 @@ extern int is_dir(const char *path);
extern char *get_template_path(const char *t);
+extern bool switch_to_ns(pid_t pid, const char *ns);
+
#endif /* __LXC_UTILS_H */
From 52cba15dc85f85390dc9b3297af89717e9e4a4c0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 15:31:03 +0100
Subject: [PATCH 19/30] tools: move lxc-execute to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 14 +--
src/lxc/tools/arguments.c | 7 +-
src/lxc/tools/lxc_execute.c | 76 +++++++++++-----
src/lxc/tools/tool_utils.c | 215 +++++++++++++++++++++++++++++++++++++++++---
src/lxc/tools/tool_utils.h | 29 ++++++
5 files changed, 296 insertions(+), 45 deletions(-)
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 68dfb6cb9..7194216ef 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -269,13 +269,13 @@ endif
LDADD=liblxc.la @CAP_LIBS@ @APPARMOR_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c tools/tool_utils.c
-lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c
-lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c
-lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c
-lxc_console_SOURCES = tools/lxc_console.c tools/arguments.c
-lxc_destroy_SOURCES = tools/lxc_destroy.c tools/arguments.c
-lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c
-lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c
+lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c tools/tool_utils.c
+lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c tools/tool_utils.c
+lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c tools/tool_utils.c
+lxc_console_SOURCES = tools/lxc_console.c tools/arguments.c tools/tool_utils.c
+lxc_destroy_SOURCES = tools/lxc_destroy.c tools/arguments.c tools/tool_utils.c
+lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c tools/tool_utils.c
+lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c tools/tool_utils.c
lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c
lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c
lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c
diff --git a/src/lxc/tools/arguments.c b/src/lxc/tools/arguments.c
index 7116dd6bc..889140984 100644
--- a/src/lxc/tools/arguments.c
+++ b/src/lxc/tools/arguments.c
@@ -22,6 +22,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <limits.h>
@@ -32,10 +33,10 @@
#include <sys/stat.h>
#include <sys/types.h>
+#include <lxc/version.h>
+
#include "arguments.h"
-#include "utils.h"
-#include "version.h"
-#include "namespace.h"
+#include "tool_utils.h"
static int build_shortopts(const struct option *a_options, char *a_shortopts,
size_t a_size)
diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c
index dc1f504e7..af418fe87 100644
--- a/src/lxc/tools/lxc_execute.c
+++ b/src/lxc/tools/lxc_execute.c
@@ -20,32 +20,30 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
#include <errno.h>
#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <lxc/lxccontainer.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <lxc/lxccontainer.h>
-#include "caps.h"
-#include "lxc.h"
-#include "log.h"
-#include "conf.h"
-#include "confile.h"
#include "arguments.h"
-#include "config.h"
-#include "start.h"
-#include "utils.h"
+#include "tool_list.h"
+#include "tool_utils.h"
static struct lxc_list defines;
static int my_parser(struct lxc_arguments* args, int c, char* arg)
{
+ int ret;
+
switch (c) {
case 'd':
args->daemonize = 1;
@@ -54,7 +52,9 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
args->rcfile = arg;
break;
case 's':
- return lxc_config_define_add(&defines, arg);
+ ret = lxc_config_define_add(&defines, arg);
+ if (ret < 0)
+ lxc_config_define_free(&defines);
break;
case 'u':
if (lxc_safe_uint(arg, &args->uid) < 0)
@@ -112,14 +112,17 @@ Options :\n\
.daemonize = 0,
};
-static bool set_argv(struct lxc_conf *conf, struct lxc_arguments *args)
+static bool set_argv(struct lxc_container *c, struct lxc_arguments *args)
{
+ int ret;
+ char buf[TOOL_MAXPATHLEN];
char **components, **p;
- if (!conf->execute_cmd)
+ ret = c->get_config_item(c, "lxc.execute.cmd", buf, TOOL_MAXPATHLEN);
+ if (ret < 0)
return false;
- components = lxc_string_split_quoted(conf->execute_cmd);
+ components = lxc_string_split_quoted(buf);
if (!components)
return false;
@@ -154,7 +157,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
@@ -187,24 +189,50 @@ int main(int argc, char *argv[])
}
if (my_args.argc == 0) {
- if (!set_argv(c->lxc_conf, &my_args)) {
+ if (!set_argv(c, &my_args)) {
fprintf(stderr, "missing command to execute!\n");
lxc_container_put(c);
exit(EXIT_FAILURE);
}
}
- ret = lxc_config_define_load(&defines, c->lxc_conf);
+ ret = lxc_config_define_load(&defines, c);
if (ret) {
lxc_container_put(c);
exit(EXIT_FAILURE);
}
- if (my_args.uid)
- c->lxc_conf->init_uid = my_args.uid;
+ if (my_args.uid) {
+ char buf[256];
- if (my_args.gid)
- c->lxc_conf->init_gid = my_args.gid;
+ ret = snprintf(buf, 256, "%d", my_args.uid);
+ if (ret < 0 || (size_t)ret >= 256) {
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+
+ ret = c->set_config_item(c, "lxc.init.uid", buf);
+ if (ret < 0) {
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (my_args.gid) {
+ char buf[256];
+
+ ret = snprintf(buf, 256, "%d", my_args.gid);
+ if (ret < 0 || (size_t)ret >= 256) {
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+
+ ret = c->set_config_item(c, "lxc.init.gid", buf);
+ if (ret < 0) {
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+ }
if (!lxc_setup_shared_ns(&my_args, c)) {
lxc_container_put(c);
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index 42be4d249..b1557a18e 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -131,17 +131,6 @@ signed long lxc_config_parse_arch(const char *arch)
return -1;
}
-enum {
- LXC_NS_USER,
- LXC_NS_MNT,
- LXC_NS_PID,
- LXC_NS_UTS,
- LXC_NS_IPC,
- LXC_NS_NET,
- LXC_NS_CGROUP,
- LXC_NS_MAX
-};
-
const static struct ns_info {
const char *proc_name;
int clone_flag;
@@ -630,3 +619,207 @@ bool switch_to_ns(pid_t pid, const char *ns) {
close(fd);
return true;
}
+
+static bool complete_word(char ***result, char *start, char *end, size_t *cap, size_t *cnt)
+{
+ int r;
+
+ r = lxc_grow_array((void ***)result, cap, 2 + *cnt, 16);
+ if (r < 0)
+ return false;
+ (*result)[*cnt] = strndup(start, end - start);
+ if (!(*result)[*cnt])
+ return false;
+ (*cnt)++;
+
+ return true;
+}
+
+/*
+ * Given a a string 'one two "three four"', split into three words,
+ * one, two, and "three four"
+ */
+char **lxc_string_split_quoted(char *string)
+{
+ char *nextword = string, *p, state;
+ char **result = NULL;
+ size_t result_capacity = 0;
+ size_t result_count = 0;
+
+ if (!string || !*string)
+ return calloc(1, sizeof(char *));
+
+ // TODO I'm *not* handling escaped quote
+ state = ' ';
+ for (p = string; *p; p++) {
+ switch(state) {
+ case ' ':
+ if (isspace(*p))
+ continue;
+ else if (*p == '"' || *p == '\'') {
+ nextword = p;
+ state = *p;
+ continue;
+ }
+ nextword = p;
+ state = 'a';
+ continue;
+ case 'a':
+ if (isspace(*p)) {
+ complete_word(&result, nextword, p, &result_capacity, &result_count);
+ state = ' ';
+ continue;
+ }
+ continue;
+ case '"':
+ case '\'':
+ if (*p == state) {
+ complete_word(&result, nextword+1, p, &result_capacity, &result_count);
+ state = ' ';
+ continue;
+ }
+ continue;
+ }
+ }
+
+ if (state == 'a')
+ complete_word(&result, nextword, p, &result_capacity, &result_count);
+
+ return realloc(result, (result_count + 1) * sizeof(char *));
+}
+
+int lxc_char_left_gc(const char *buffer, size_t len)
+{
+ size_t i;
+ for (i = 0; i < len; i++) {
+ if (buffer[i] == ' ' ||
+ buffer[i] == '\t')
+ continue;
+ return i;
+ }
+ return 0;
+}
+
+int lxc_char_right_gc(const char *buffer, size_t len)
+{
+ int i;
+ for (i = len - 1; i >= 0; i--) {
+ if (buffer[i] == ' ' ||
+ buffer[i] == '\t' ||
+ buffer[i] == '\n' ||
+ buffer[i] == '\0')
+ continue;
+ return i + 1;
+ }
+ return 0;
+}
+
+struct new_config_item *parse_line(char *buffer)
+{
+ char *dot, *key, *line, *linep, *value;
+ int ret = 0;
+ char *dup = buffer;
+ struct new_config_item *new = NULL;
+
+ linep = line = strdup(dup);
+ if (!line)
+ return NULL;
+
+ line += lxc_char_left_gc(line, strlen(line));
+
+ /* martian option - don't add it to the config itself */
+ if (strncmp(line, "lxc.", 4))
+ goto on_error;
+
+ ret = -1;
+ dot = strchr(line, '=');
+ if (!dot) {
+ fprintf(stderr, "Invalid configuration item: %s\n", line);
+ goto on_error;
+ }
+
+ *dot = '\0';
+ value = dot + 1;
+
+ key = line;
+ key[lxc_char_right_gc(key, strlen(key))] = '\0';
+
+ value += lxc_char_left_gc(value, strlen(value));
+ value[lxc_char_right_gc(value, strlen(value))] = '\0';
+
+ if (*value == '\'' || *value == '\"') {
+ size_t len;
+
+ len = strlen(value);
+ if (len > 1 && value[len - 1] == *value) {
+ value[len - 1] = '\0';
+ value++;
+ }
+ }
+
+ ret = -1;
+ new = malloc(sizeof(struct new_config_item));
+ if (!new)
+ goto on_error;
+
+ new->key = strdup(key);
+ new->val = strdup(value);
+ if (!new->val || !new->key)
+ goto on_error;
+ ret = 0;
+
+on_error:
+ free(linep);
+ if (ret < 0 && new) {
+ free(new->key);
+ free(new->val);
+ free(new);
+ new = NULL;
+ }
+
+ return new;
+}
+
+int lxc_config_define_add(struct lxc_list *defines, char *arg)
+{
+ struct lxc_list *dent;
+
+ dent = malloc(sizeof(struct lxc_list));
+ if (!dent)
+ return -1;
+
+ dent->elem = parse_line(arg);
+ if (!dent->elem)
+ return -1;
+ lxc_list_add_tail(defines, dent);
+ return 0;
+}
+
+int lxc_config_define_load(struct lxc_list *defines, struct lxc_container *c)
+{
+ struct lxc_list *it;
+ int ret = 0;
+
+ lxc_list_for_each(it, defines) {
+ struct new_config_item *new_item = it->elem;
+ ret = c->set_config_item(c, new_item->key, new_item->val);
+ if (ret < 0)
+ break;
+ }
+
+ lxc_config_define_free(defines);
+ return ret;
+}
+
+void lxc_config_define_free(struct lxc_list *defines)
+{
+ struct lxc_list *it, *next;
+
+ lxc_list_for_each_safe(it, defines, next) {
+ struct new_config_item *new_item = it->elem;
+ free(new_item->key);
+ free(new_item->val);
+ lxc_list_del(it);
+ free(it);
+ }
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index 2ce2afd0a..0184bd843 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -29,8 +29,23 @@
#include <stdbool.h>
#include <unistd.h>
+#include <lxc/lxccontainer.h>
+
+#include "tool_list.h"
+
#define TOOL_MAXPATHLEN 4096
+enum {
+ LXC_NS_USER,
+ LXC_NS_MNT,
+ LXC_NS_PID,
+ LXC_NS_UTS,
+ LXC_NS_IPC,
+ LXC_NS_NET,
+ LXC_NS_CGROUP,
+ LXC_NS_MAX
+};
+
extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
extern signed long lxc_config_parse_arch(const char *arch);
extern int lxc_namespace_2_cloneflag(const char *namespace);
@@ -66,6 +81,7 @@ extern char **lxc_string_split(const char *string, char _sep);
extern char **lxc_normalize_path(const char *path);
extern char *lxc_string_join(const char *sep, const char **parts,
bool use_as_prefix);
+extern char **lxc_string_split_quoted(char *string);
extern int mkdir_p(const char *dir, mode_t mode);
extern bool file_exists(const char *f);
@@ -75,4 +91,17 @@ extern char *get_template_path(const char *t);
extern bool switch_to_ns(pid_t pid, const char *ns);
+extern int lxc_config_define_add(struct lxc_list *defines, char *arg);
+extern int lxc_config_define_load(struct lxc_list *defines,
+ struct lxc_container *c);
+extern void lxc_config_define_free(struct lxc_list *defines);
+extern int lxc_char_left_gc(const char *buffer, size_t len);
+extern int lxc_char_right_gc(const char *buffer, size_t len);
+
+struct new_config_item {
+ char *key;
+ char *val;
+};
+extern struct new_config_item *parse_line(char *buffer);
+
#endif /* __LXC_UTILS_H */
From 0520a267fdc9a858798dbb20c646b6212dc49962 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 15:32:07 +0100
Subject: [PATCH 20/30] tools: move lxc-freeze to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_freeze.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/lxc/tools/lxc_freeze.c b/src/lxc/tools/lxc_freeze.c
index aab2b6fe3..09c21b30e 100644
--- a/src/lxc/tools/lxc_freeze.c
+++ b/src/lxc/tools/lxc_freeze.c
@@ -20,17 +20,17 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#define _GNU_SOURCE
+#include <libgen.h>
#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
-#include <libgen.h>
-#include <string.h>
#include <lxc/lxccontainer.h>
-#include "lxc.h"
-#include "log.h"
-
#include "arguments.h"
static const struct option my_longopts[] = {
@@ -72,7 +72,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
From d57e0fd36f69b838015d15ac6b0f4b105bef882a Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 15:36:15 +0100
Subject: [PATCH 21/30] tools: move lxc-info to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_info.c | 20 +++++++++-----------
src/lxc/tools/tool_utils.c | 27 +++++++++++++++++++++++++++
src/lxc/tools/tool_utils.h | 1 +
3 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/src/lxc/tools/lxc_info.c b/src/lxc/tools/lxc_info.c
index 3c7f6b398..de8f57463 100644
--- a/src/lxc/tools/lxc_info.c
+++ b/src/lxc/tools/lxc_info.c
@@ -21,21 +21,20 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <stdio.h>
+#define _GNU_SOURCE
+#include <libgen.h>
+#include <limits.h>
#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include <limits.h>
-#include <libgen.h>
#include <sys/types.h>
#include <lxc/lxccontainer.h>
-#include "lxc.h"
-#include "log.h"
-#include "utils.h"
-#include "commands.h"
#include "arguments.h"
+#include "tool_utils.h"
static bool ips;
static bool state;
@@ -205,7 +204,7 @@ static void print_stats(struct lxc_container *c)
char buf[4096];
ret = c->get_cgroup_item(c, "cpuacct.usage", buf, sizeof(buf));
- if (ret > 0 && ret < sizeof(buf)) {
+ if (ret > 0 && (size_t)ret < sizeof(buf)) {
str_chomp(buf);
if (humanize) {
float seconds = strtof(buf, NULL) / 1000000000.0;
@@ -217,7 +216,7 @@ static void print_stats(struct lxc_container *c)
}
ret = c->get_cgroup_item(c, "blkio.throttle.io_service_bytes", buf, sizeof(buf));
- if (ret > 0 && ret < sizeof(buf)) {
+ if (ret > 0 && (size_t)ret < sizeof(buf)) {
char *ch;
/* put ch on last "Total" line */
@@ -247,7 +246,7 @@ static void print_stats(struct lxc_container *c)
for (i = 0; lxstat[i].name; i++) {
ret = c->get_cgroup_item(c, lxstat[i].file, buf, sizeof(buf));
- if (ret > 0 && ret < sizeof(buf)) {
+ if (ret > 0 && (size_t)ret < sizeof(buf)) {
str_chomp(buf);
str_size_humanize(buf, sizeof(buf));
printf("%-15s %s\n", lxstat[i].name, buf);
@@ -409,7 +408,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(ret);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index b1557a18e..462a07a22 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -823,3 +823,30 @@ void lxc_config_define_free(struct lxc_list *defines)
free(it);
}
}
+
+int lxc_read_from_file(const char *filename, void* buf, size_t count)
+{
+ int fd = -1, saved_errno;
+ ssize_t ret;
+
+ fd = open(filename, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ return -1;
+
+ if (!buf || !count) {
+ char buf2[100];
+ size_t count2 = 0;
+ while ((ret = read(fd, buf2, 100)) > 0)
+ count2 += ret;
+ if (ret >= 0)
+ ret = count2;
+ } else {
+ memset(buf, 0, count);
+ ret = read(fd, buf, count);
+ }
+
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return ret;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index 0184bd843..ac4fb8a0b 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -86,6 +86,7 @@ extern char **lxc_string_split_quoted(char *string);
extern int mkdir_p(const char *dir, mode_t mode);
extern bool file_exists(const char *f);
extern int is_dir(const char *path);
+extern int lxc_read_from_file(const char *filename, void* buf, size_t count);
extern char *get_template_path(const char *t);
From 5f05387b3b97316a4876c29eac6a541bbe1515df Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 15:47:32 +0100
Subject: [PATCH 22/30] tools: move lxc-ls to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 28 ++---
src/lxc/tools/lxc_ls.c | 13 +--
src/lxc/tools/tool_utils.c | 281 +++++++++++++++++++++++++++++++++++++++++++++
src/lxc/tools/tool_utils.h | 14 +++
4 files changed, 313 insertions(+), 23 deletions(-)
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 7194216ef..02ae0e753 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -276,20 +276,20 @@ lxc_console_SOURCES = tools/lxc_console.c tools/arguments.c tools/tool_utils.c
lxc_destroy_SOURCES = tools/lxc_destroy.c tools/arguments.c tools/tool_utils.c
lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c tools/tool_utils.c
lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c tools/tool_utils.c
-lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c
-lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c
-lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c
-lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c
-lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c
-lxc_start_SOURCES = tools/lxc_start.c tools/arguments.c
-lxc_stop_SOURCES = tools/lxc_stop.c tools/arguments.c
-lxc_top_SOURCES = tools/lxc_top.c tools/arguments.c
-lxc_unfreeze_SOURCES = tools/lxc_unfreeze.c tools/arguments.c
-lxc_unshare_SOURCES = tools/lxc_unshare.c tools/arguments.c
-lxc_wait_SOURCES = tools/lxc_wait.c tools/arguments.c
-lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c
-lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c
-lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c
+lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c tools/tool_utils.c
+lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c tools/tool_utils.c
+lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c tools/tool_utils.c
+lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c tools/tool_utils.c
+lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c tools/tool_utils.c
+lxc_start_SOURCES = tools/lxc_start.c tools/arguments.c tools/tool_utils.c
+lxc_stop_SOURCES = tools/lxc_stop.c tools/arguments.c tools/tool_utils.c
+lxc_top_SOURCES = tools/lxc_top.c tools/arguments.c tools/tool_utils.c
+lxc_unfreeze_SOURCES = tools/lxc_unfreeze.c tools/arguments.c tools/tool_utils.c
+lxc_unshare_SOURCES = tools/lxc_unshare.c tools/arguments.c tools/tool_utils.c
+lxc_wait_SOURCES = tools/lxc_wait.c tools/arguments.c tools/tool_utils.c
+lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c tools/tool_utils.c
+lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c tools/tool_utils.c
+lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c tools/tool_utils.c
# Binaries shipping with liblxc
init_lxc_SOURCES = cmd/lxc_init.c
diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
index c7f25cbfe..9719f7832 100644
--- a/src/lxc/tools/lxc_ls.c
+++ b/src/lxc/tools/lxc_ls.c
@@ -16,9 +16,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "config.h"
-
+#define _GNU_SOURCE
#include <getopt.h>
+#include <limits.h>
#include <regex.h>
#include <stdbool.h>
#include <stdio.h>
@@ -35,11 +35,7 @@
#include <lxc/lxccontainer.h>
#include "arguments.h"
-#include "conf.h"
-#include "confile.h"
-#include "log.h"
-#include "lxc.h"
-#include "utils.h"
+#include "tool_utils.h"
/* Per default we only allow five levels of recursion to protect the stack at
* least a little bit. */
@@ -229,7 +225,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
@@ -1049,7 +1044,7 @@ static int ls_remove_lock(const char *path, const char *name,
if (check < 0 || (size_t)check >= *len_lockpath)
goto out;
- lxc_rmdir_onedev(*lockpath, NULL);
+ (void)rm_r(*lockpath);
ret = 0;
out:
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index 462a07a22..71b499659 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -20,6 +20,7 @@
#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
#include <ctype.h>
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -850,3 +851,283 @@ int lxc_read_from_file(const char *filename, void* buf, size_t count)
errno = saved_errno;
return ret;
}
+
+char **lxc_string_split_and_trim(const char *string, char _sep)
+{
+ char *token, *str, *saveptr = NULL;
+ char sep[2] = { _sep, '\0' };
+ char **result = NULL;
+ size_t result_capacity = 0;
+ size_t result_count = 0;
+ int r, saved_errno;
+ size_t i = 0;
+
+ if (!string)
+ return calloc(1, sizeof(char *));
+
+ str = alloca(strlen(string)+1);
+ strcpy(str, string);
+ for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
+ while (token[0] == ' ' || token[0] == '\t')
+ token++;
+ i = strlen(token);
+ while (i > 0 && (token[i - 1] == ' ' || token[i - 1] == '\t')) {
+ token[i - 1] = '\0';
+ i--;
+ }
+ r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
+ if (r < 0)
+ goto error_out;
+ result[result_count] = strdup(token);
+ if (!result[result_count])
+ goto error_out;
+ result_count++;
+ }
+
+ /* if we allocated too much, reduce it */
+ return realloc(result, (result_count + 1) * sizeof(char *));
+error_out:
+ saved_errno = errno;
+ lxc_free_array((void **)result, free);
+ errno = saved_errno;
+ return NULL;
+}
+
+char *lxc_append_paths(const char *first, const char *second)
+{
+ int ret;
+ size_t len;
+ char *result = NULL;
+ const char *pattern = "%s%s";
+
+ len = strlen(first) + strlen(second) + 1;
+ if (second[0] != '/') {
+ len += 1;
+ pattern = "%s/%s";
+ }
+
+ result = calloc(1, len);
+ if (!result)
+ return NULL;
+
+ ret = snprintf(result, len, pattern, first, second);
+ if (ret < 0 || (size_t)ret >= len) {
+ free(result);
+ return NULL;
+ }
+
+ return result;
+}
+
+bool dir_exists(const char *path)
+{
+ struct stat sb;
+ int ret;
+
+ ret = stat(path, &sb);
+ if (ret < 0)
+ /* Could be something other than eexist, just say "no". */
+ return false;
+ return S_ISDIR(sb.st_mode);
+}
+
+char *lxc_string_replace(const char *needle, const char *replacement,
+ const char *haystack)
+{
+ ssize_t len = -1, saved_len = -1;
+ char *result = NULL;
+ size_t replacement_len = strlen(replacement);
+ size_t needle_len = strlen(needle);
+
+ /* should be executed exactly twice */
+ while (len == -1 || result == NULL) {
+ char *p;
+ char *last_p;
+ ssize_t part_len;
+
+ if (len != -1) {
+ result = calloc(1, len + 1);
+ if (!result)
+ return NULL;
+ saved_len = len;
+ }
+
+ len = 0;
+
+ for (last_p = (char *)haystack, p = strstr(last_p, needle); p; last_p = p, p = strstr(last_p, needle)) {
+ part_len = (ssize_t)(p - last_p);
+ if (result && part_len > 0)
+ memcpy(&result[len], last_p, part_len);
+ len += part_len;
+ if (result && replacement_len > 0)
+ memcpy(&result[len], replacement, replacement_len);
+ len += replacement_len;
+ p += needle_len;
+ }
+ part_len = strlen(last_p);
+ if (result && part_len > 0)
+ memcpy(&result[len], last_p, part_len);
+ len += part_len;
+ }
+
+ /* make sure we did the same thing twice,
+ * once for calculating length, the other
+ * time for copying data */
+ if (saved_len != len) {
+ free(result);
+ return NULL;
+ }
+ /* make sure we didn't overwrite any buffer,
+ * due to calloc the string should be 0-terminated */
+ if (result[len] != '\0') {
+ free(result);
+ return NULL;
+ }
+
+ return result;
+}
+
+ssize_t lxc_write_nointr(int fd, const void* buf, size_t count)
+{
+ ssize_t ret;
+again:
+ ret = write(fd, buf, count);
+ if (ret < 0 && errno == EINTR)
+ goto again;
+ return ret;
+}
+
+char *get_rundir()
+{
+ char *rundir;
+ const char *homedir;
+
+ if (geteuid() == 0) {
+ rundir = strdup(RUNTIME_PATH);
+ return rundir;
+ }
+
+ rundir = getenv("XDG_RUNTIME_DIR");
+ if (rundir) {
+ rundir = strdup(rundir);
+ return rundir;
+ }
+
+ homedir = getenv("HOME");
+ if (!homedir)
+ return NULL;
+
+ rundir = malloc(sizeof(char) * (17 + strlen(homedir)));
+ sprintf(rundir, "%s/.cache/lxc/run/", homedir);
+
+ return rundir;
+}
+
+char *must_copy_string(const char *entry)
+{
+ char *ret;
+
+ if (!entry)
+ return NULL;
+ do {
+ ret = strdup(entry);
+ } while (!ret);
+
+ return ret;
+}
+
+
+void *must_realloc(void *orig, size_t sz)
+{
+ void *ret;
+
+ do {
+ ret = realloc(orig, sz);
+ } while (!ret);
+
+ return ret;
+}
+
+char *must_make_path(const char *first, ...)
+{
+ va_list args;
+ char *cur, *dest;
+ size_t full_len = strlen(first);
+
+ dest = must_copy_string(first);
+
+ va_start(args, first);
+ while ((cur = va_arg(args, char *)) != NULL) {
+ full_len += strlen(cur);
+ if (cur[0] != '/')
+ full_len++;
+ dest = must_realloc(dest, full_len + 1);
+ if (cur[0] != '/')
+ strcat(dest, "/");
+ strcat(dest, cur);
+ }
+ va_end(args);
+
+ return dest;
+}
+
+int rm_r(char *dirname)
+{
+ int ret;
+ struct dirent *direntp;
+ DIR *dir;
+ int r = 0;
+
+ dir = opendir(dirname);
+ if (!dir)
+ return -1;
+
+ while ((direntp = readdir(dir))) {
+ char *pathname;
+ struct stat mystat;
+
+ if (!direntp)
+ break;
+
+ if (!strcmp(direntp->d_name, ".") ||
+ !strcmp(direntp->d_name, ".."))
+ continue;
+
+ pathname = must_make_path(dirname, direntp->d_name, NULL);
+
+ ret = lstat(pathname, &mystat);
+ if (ret < 0) {
+ r = -1;
+ goto next;
+ }
+
+ if (!S_ISDIR(mystat.st_mode))
+ goto next;
+
+ ret = rm_r(pathname);
+ if (ret < 0)
+ r = -1;
+ next:
+ free(pathname);
+ }
+
+ ret = rmdir(dirname);
+ if (ret < 0)
+ r = -1;
+
+ ret = closedir(dir);
+ if (ret < 0)
+ r = -1;
+
+ return r;
+}
+
+ssize_t lxc_read_nointr(int fd, void* buf, size_t count)
+{
+ ssize_t ret;
+again:
+ ret = read(fd, buf, count);
+ if (ret < 0 && errno == EINTR)
+ goto again;
+ return ret;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index ac4fb8a0b..db43fa49d 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -82,9 +82,18 @@ extern char **lxc_normalize_path(const char *path);
extern char *lxc_string_join(const char *sep, const char **parts,
bool use_as_prefix);
extern char **lxc_string_split_quoted(char *string);
+extern char **lxc_string_split_and_trim(const char *string, char _sep);
+extern char *lxc_append_paths(const char *first, const char *second);
+extern char *lxc_string_replace(const char *needle, const char *replacement,
+ const char *haystack);
+extern char *must_copy_string(const char *entry);
+extern void *must_realloc(void *orig, size_t sz);
+extern char *must_make_path(const char *first, ...);
extern int mkdir_p(const char *dir, mode_t mode);
+extern int rm_r(char *dirname);
extern bool file_exists(const char *f);
+extern bool dir_exists(const char *path);
extern int is_dir(const char *path);
extern int lxc_read_from_file(const char *filename, void* buf, size_t count);
@@ -105,4 +114,9 @@ struct new_config_item {
};
extern struct new_config_item *parse_line(char *buffer);
+extern ssize_t lxc_read_nointr(int fd, void* buf, size_t count);
+extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count);
+
+extern char *get_rundir();
+
#endif /* __LXC_UTILS_H */
From c1fc010e48832a38dfc57b6aa9fb2b83bf94d2d9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 16:01:10 +0100
Subject: [PATCH 23/30] tools: move lxc-snapshot to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_snapshot.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/lxc/tools/lxc_snapshot.c b/src/lxc/tools/lxc_snapshot.c
index 0c0ea3ada..7c8255c2c 100644
--- a/src/lxc/tools/lxc_snapshot.c
+++ b/src/lxc/tools/lxc_snapshot.c
@@ -17,21 +17,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "confile.h"
-#include <stdio.h>
+#define _GNU_SOURCE
+#include <ctype.h>
+#include <fcntl.h>
#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include <ctype.h>
#include <sys/types.h>
-#include <fcntl.h>
#include <lxc/lxccontainer.h>
-#include "lxc.h"
-#include "log.h"
#include "arguments.h"
-#include "storage.h"
-#include "utils.h"
+#include "tool_utils.h"
static int my_parser(struct lxc_arguments *args, int c, char *arg);
@@ -97,7 +96,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
From 5962d017473debdc1c6aaeb61977b8b336bf712d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 16:04:28 +0100
Subject: [PATCH 24/30] tools: move lxc-start to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_start.c | 93 ++++++++++++++++++++++++++++-------------------
1 file changed, 55 insertions(+), 38 deletions(-)
diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index 5a422923f..31a7cd690 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -20,35 +20,30 @@
* 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 "config.h"
-#include <stdio.h>
-#include <libgen.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
+#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
+#include <libgen.h>
+#include <net/if.h>
#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
#include <sys/param.h>
-#include <sys/utsname.h>
-#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <net/if.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
#include <lxc/lxccontainer.h>
-#include "log.h"
-#include "caps.h"
-#include "lxc.h"
-#include "conf.h"
-#include "cgroup.h"
-#include "utils.h"
-#include "confile.h"
#include "arguments.h"
+#include "tool_list.h"
+#include "tool_utils.h"
static struct lxc_list defines;
@@ -82,21 +77,44 @@ static int ensure_path(char **confpath, const char *path)
return err;
}
-static int my_parser(struct lxc_arguments* args, int c, char* arg)
+static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
switch (c) {
- case 'c': args->console = arg; break;
- case 'L': args->console_log = arg; break;
- case 'd': args->daemonize = 1; break;
- case 'F': args->daemonize = 0; break;
- case 'f': args->rcfile = arg; break;
- case 'C': args->close_all_fds = 1; break;
- case 's': return lxc_config_define_add(&defines, arg);
- case 'p': args->pidfile = arg; break;
- case OPT_SHARE_NET: args->share_ns[LXC_NS_NET] = arg; break;
- case OPT_SHARE_IPC: args->share_ns[LXC_NS_IPC] = arg; break;
- case OPT_SHARE_UTS: args->share_ns[LXC_NS_UTS] = arg; break;
- case OPT_SHARE_PID: args->share_ns[LXC_NS_PID] = arg; break;
+ case 'c':
+ args->console = arg;
+ break;
+ case 'L':
+ args->console_log = arg;
+ break;
+ case 'd':
+ args->daemonize = 1;
+ break;
+ case 'F':
+ args->daemonize = 0;
+ break;
+ case 'f':
+ args->rcfile = arg;
+ break;
+ case 'C':
+ args->close_all_fds = 1;
+ break;
+ case 's':
+ return lxc_config_define_add(&defines, arg);
+ case 'p':
+ args->pidfile = arg;
+ break;
+ case OPT_SHARE_NET:
+ args->share_ns[LXC_NS_NET] = arg;
+ break;
+ case OPT_SHARE_IPC:
+ args->share_ns[LXC_NS_IPC] = arg;
+ break;
+ case OPT_SHARE_UTS:
+ args->share_ns[LXC_NS_UTS] = arg;
+ break;
+ case OPT_SHARE_PID:
+ args->share_ns[LXC_NS_PID] = arg;
+ break;
}
return 0;
}
@@ -147,11 +165,10 @@ Options :\n\
int main(int argc, char *argv[])
{
- struct lxc_conf *conf;
- struct lxc_log log;
const char *lxcpath;
char *const *args;
struct lxc_container *c;
+ struct lxc_log log;
int err = EXIT_FAILURE;
char *rcfile = NULL;
char *const default_args[] = {
@@ -181,7 +198,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(err);
- lxc_log_options_no_override();
lxcpath = my_args.lxcpath[0];
if (access(lxcpath, O_RDONLY) < 0) {
@@ -259,11 +275,12 @@ int main(int argc, char *argv[])
* We should use set_config_item() over &defines, which would handle
* unset c->lxc_conf for us and let us not use lxc_config_define_load()
*/
- if (!c->lxc_conf)
- c->lxc_conf = lxc_conf_init();
- conf = c->lxc_conf;
+ if (!c->lxc_conf) {
+ fprintf(stderr, "No container config specified\n");
+ goto out;
+ }
- if (lxc_config_define_load(&defines, conf))
+ if (lxc_config_define_load(&defines, c))
goto out;
if (!rcfile && !strcmp("/sbin/init", args[0])) {
From dd18b7d6ba9b45e7ac5eddb41e9cb335ab69cb32 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 16:17:46 +0100
Subject: [PATCH 25/30] tools: move lxc-stop to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_stop.c | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c
index 9d2ba6ed1..f133c9977 100644
--- a/src/lxc/tools/lxc_stop.c
+++ b/src/lxc/tools/lxc_stop.c
@@ -20,18 +20,18 @@
* 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 <stdio.h>
+
+#define _GNU_SOURCE
#include <libgen.h>
-#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/types.h>
+#include <unistd.h>
#include <lxc/lxccontainer.h>
-#include "lxc.h"
-#include "log.h"
#include "arguments.h"
-#include "commands.h"
-#include "utils.h"
+#include "tool_utils.h"
#define OPT_NO_LOCK OPT_USAGE + 1
#define OPT_NO_KILL OPT_USAGE + 2
@@ -113,7 +113,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(ret);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
@@ -155,13 +154,6 @@ int main(int argc, char *argv[])
exit(ret);
}
- /* shortcut - if locking is bogus, we should be able to kill
- * containers at least */
- if (my_args.nolock) {
- ret = lxc_cmd_stop(my_args.name, my_args.lxcpath[0]);
- exit(ret);
- }
-
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
fprintf(stderr, "Error opening container\n");
From cac8f6431b14832ea0395a52963b5b1f56944093 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 16:29:46 +0100
Subject: [PATCH 26/30] tools: move lxc-top to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_top.c | 172 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 146 insertions(+), 26 deletions(-)
diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c
index 5d5c08a25..868693866 100644
--- a/src/lxc/tools/lxc_top.c
+++ b/src/lxc/tools/lxc_top.c
@@ -21,25 +21,26 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
#include <errno.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
+#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
+
#include <lxc/lxccontainer.h>
#include "arguments.h"
-#include "log.h"
-#include "lxc.h"
-#include "mainloop.h"
-#include "utils.h"
+#include "tool_utils.h"
#define USER_HZ 100
#define ESC "\033"
@@ -181,24 +182,6 @@ static int stdin_tios_rows(void)
return 25;
}
-static int stdin_handler(int fd, uint32_t events, void *data,
- struct lxc_epoll_descr *descr)
-{
- char *in_char = data;
-
- if (events & EPOLLIN) {
- int rc;
-
- rc = read(fd, in_char, sizeof(*in_char));
- if (rc <= 0)
- *in_char = '\0';
- }
-
- if (events & EPOLLHUP)
- *in_char = 'q';
- return 1;
-}
-
static void sig_handler(int sig)
{
exit(EXIT_SUCCESS);
@@ -310,7 +293,7 @@ static void stat_get_blk_stats(struct lxc_container *c, const char *item,
char **lines, **cols;
len = c->get_cgroup_item(c, item, buf, sizeof(buf));
- if (len <= 0 || len >= sizeof(buf)) {
+ if (len <= 0 || (size_t)len >= sizeof(buf)) {
fprintf(stderr, "unable to read cgroup item %s\n", item);
return;
}
@@ -409,7 +392,7 @@ static void stats_print(const char *name, const struct stats *stats,
size_humanize(stats->mem_used, mem_used_str, sizeof(mem_used_str));
ret = snprintf(iosb_str, sizeof(iosb_str), "%s(%s/%s)", iosb_total_str, iosb_read_str, iosb_write_str);
- if (ret < 0 || ret >= sizeof(iosb_str))
+ if (ret < 0 || (size_t)ret >= sizeof(iosb_str))
printf("snprintf'd too many characters: %d\n", ret);
printf("%-18.18s %12.2f %12.2f %12.2f %36s %10s",
@@ -429,7 +412,7 @@ static void stats_print(const char *name, const struct stats *stats,
printf(" %10s", kmem_used_str);
}
} else {
- gettimeofday(&time_val, NULL);
+ (void)gettimeofday(&time_val, NULL);
time_ms = (unsigned long long) (time_val.tv_sec) * 1000 + (unsigned long long) (time_val.tv_usec) / 1000;
printf("%" PRIu64 ",%s,%" PRIu64 ",%" PRIu64 ",%" PRIu64
",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64,
@@ -554,6 +537,143 @@ static void ct_realloc(int active_cnt)
}
}
+#define LXC_MAINLOOP_CONTINUE 0
+#define LXC_MAINLOOP_CLOSE 1
+
+struct lxc_epoll_descr {
+ int epfd;
+ struct lxc_list handlers;
+};
+
+typedef int (*lxc_mainloop_callback_t)(int fd, uint32_t event, void *data,
+ struct lxc_epoll_descr *descr);
+
+struct mainloop_handler {
+ lxc_mainloop_callback_t callback;
+ int fd;
+ void *data;
+};
+
+#define MAX_EVENTS 10
+
+int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
+{
+ int i, nfds, ret;
+ struct mainloop_handler *handler;
+ struct epoll_event events[MAX_EVENTS];
+
+ for (;;) {
+ nfds = epoll_wait(descr->epfd, events, MAX_EVENTS, timeout_ms);
+ if (nfds < 0) {
+ if (errno == EINTR)
+ continue;
+
+ return -1;
+ }
+
+ for (i = 0; i < nfds; i++) {
+ handler = events[i].data.ptr;
+
+ /* If the handler returns a positive value, exit the
+ * mainloop.
+ */
+ ret = handler->callback(handler->fd, events[i].events,
+ handler->data, descr);
+ if (ret == LXC_MAINLOOP_CLOSE)
+ return 0;
+ }
+
+ if (nfds == 0)
+ return 0;
+
+ if (lxc_list_empty(&descr->handlers))
+ return 0;
+ }
+}
+
+int lxc_mainloop_open(struct lxc_epoll_descr *descr)
+{
+ /* hint value passed to epoll create */
+ descr->epfd = epoll_create1(EPOLL_CLOEXEC);
+ if (descr->epfd < 0)
+ return -1;
+
+ lxc_list_init(&descr->handlers);
+ return 0;
+}
+
+int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
+ lxc_mainloop_callback_t callback, void *data)
+{
+ struct epoll_event ev;
+ struct mainloop_handler *handler;
+ struct lxc_list *item;
+
+ handler = malloc(sizeof(*handler));
+ if (!handler)
+ return -1;
+
+ handler->callback = callback;
+ handler->fd = fd;
+ handler->data = data;
+
+ ev.events = EPOLLIN;
+ ev.data.ptr = handler;
+
+ if (epoll_ctl(descr->epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
+ goto out_free_handler;
+
+ item = malloc(sizeof(*item));
+ if (!item)
+ goto out_free_handler;
+
+ item->elem = handler;
+ lxc_list_add(&descr->handlers, item);
+ return 0;
+
+out_free_handler:
+ free(handler);
+ return -1;
+}
+
+int lxc_mainloop_close(struct lxc_epoll_descr *descr)
+{
+ struct lxc_list *iterator, *next;
+
+ iterator = descr->handlers.next;
+ while (iterator != &descr->handlers) {
+ next = iterator->next;
+
+ lxc_list_del(iterator);
+ free(iterator->elem);
+ free(iterator);
+ iterator = next;
+ }
+
+ if (descr->epfd >= 0)
+ return close(descr->epfd);
+
+ return 0;
+}
+
+static int stdin_handler(int fd, uint32_t events, void *data,
+ struct lxc_epoll_descr *descr)
+{
+ char *in_char = data;
+
+ if (events & EPOLLIN) {
+ int rc;
+
+ rc = read(fd, in_char, sizeof(*in_char));
+ if (rc <= 0)
+ *in_char = '\0';
+ }
+
+ if (events & EPOLLHUP)
+ *in_char = 'q';
+ return 1;
+}
+
int main(int argc, char *argv[])
{
struct lxc_epoll_descr descr;
From 69e7cb1628fc6297dedd18ae038936ff5d6eea0f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 16:30:38 +0100
Subject: [PATCH 27/30] tools: move lxc-unfreeze to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_unfreeze.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/lxc/tools/lxc_unfreeze.c b/src/lxc/tools/lxc_unfreeze.c
index 5027d28e6..f12b5d57a 100644
--- a/src/lxc/tools/lxc_unfreeze.c
+++ b/src/lxc/tools/lxc_unfreeze.c
@@ -20,16 +20,18 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#define _GNU_SOURCE
+#include <libgen.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
-#include <libgen.h>
#include <sys/types.h>
#include <lxc/lxccontainer.h>
-#include "lxc.h"
-#include "log.h"
#include "arguments.h"
+#include "tool_utils.h"
static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS
@@ -71,7 +73,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
From 10f47c300980f6bd06689e6401ad64292ee90194 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 16:36:12 +0100
Subject: [PATCH 28/30] tools: move lxc-wait to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_wait.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lxc/tools/lxc_wait.c b/src/lxc/tools/lxc_wait.c
index 62b7c01b5..6186bce05 100644
--- a/src/lxc/tools/lxc_wait.c
+++ b/src/lxc/tools/lxc_wait.c
@@ -20,6 +20,8 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <libgen.h>
@@ -30,9 +32,8 @@
#include <lxc/lxccontainer.h>
-#include "lxc.h"
-#include "log.h"
#include "arguments.h"
+#include "tool_utils.h"
static int my_checker(const struct lxc_arguments* args)
{
@@ -98,7 +99,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
From 7cc90ec4d7cf5480948ba1bf175252b996fd5a41 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 17:06:42 +0100
Subject: [PATCH 29/30] tools: move lxc-unshare to API symbols only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_unshare.c | 77 ++++++++++++++++++++++++++++++++++-----------
src/lxc/tools/tool_utils.c | 63 +++++++++++++++++++++++++++++++++++++
src/lxc/tools/tool_utils.h | 24 ++++++++++++++
3 files changed, 146 insertions(+), 18 deletions(-)
diff --git a/src/lxc/tools/lxc_unshare.c b/src/lxc/tools/lxc_unshare.c
index 9e062a0ca..98143d662 100644
--- a/src/lxc/tools/lxc_unshare.c
+++ b/src/lxc/tools/lxc_unshare.c
@@ -20,30 +20,27 @@
* 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 "config.h"
-#include <stdio.h>
+#define _GNU_SOURCE
#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
#include <libgen.h>
-#include <netinet/in.h>
#include <pwd.h>
+#include <sched.h>
#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <netinet/in.h>
+#include <unistd.h>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <unistd.h>
-#include "caps.h"
-#include "cgroup.h"
-#include "error.h"
-#include "log.h"
-#include "namespace.h"
-#include "network.h"
-#include "utils.h"
+#include "arguments.h"
+#include "tool_utils.h"
struct my_iflist
{
@@ -67,7 +64,7 @@ static void usage(char *cmd)
static bool lookup_user(const char *optarg, uid_t *uid)
{
- char name[MAXPATHLEN];
+ char name[TOOL_MAXPATHLEN];
struct passwd *pwent = NULL;
if (!optarg || (optarg[0] == '\0'))
@@ -147,11 +144,34 @@ static int do_start(void *arg)
return 1;
}
+int write_id_mapping(pid_t pid, const char *buf, size_t buf_size)
+{
+ char path[TOOL_MAXPATHLEN];
+ int fd, ret;
+
+
+ ret = snprintf(path, TOOL_MAXPATHLEN, "/proc/%d/uid_map", pid);
+ if (ret < 0 || ret >= TOOL_MAXPATHLEN)
+ return -E2BIG;
+
+ fd = open(path, O_WRONLY);
+ if (fd < 0)
+ return -1;
+
+ errno = 0;
+ ret = lxc_write_nointr(fd, buf, buf_size);
+ close(fd);
+ if (ret < 0 || (size_t)ret != buf_size)
+ return -1;
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
char *del;
char **it, **args;
- int opt, status;
+ int opt;
int ret;
char *namespaces = NULL;
int flags = 0, daemonize = 0;
@@ -284,7 +304,7 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- ret = write_id_mapping(ID_TYPE_UID, pid, umap, strlen(umap));
+ ret = write_id_mapping(pid, umap, strlen(umap));
if (ret < 0) {
close(start_arg.wait_fd);
fprintf(stderr, "uid mapping failed\n");
@@ -301,19 +321,40 @@ int main(int argc, char *argv[])
if (my_iflist) {
for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) {
- if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid, NULL) < 0)
- fprintf(stderr,"Could not move interface %s into container %d: %s\n", tmpif->mi_ifname, pid, strerror(errno));
+ pid_t pid;
+
+ pid = fork();
+ if (pid < 0)
+ fprintf(stderr, "Failed to move network device "
+ "\"%s\" to network namespace\n",
+ tmpif->mi_ifname);
+
+ if (pid == 0) {
+ char buf[256];
+
+ ret = snprintf(buf, 256, "%d", pid);
+ if (ret < 0 || ret >= 256)
+ exit(EXIT_FAILURE);
+
+ execlp("ip", "ip", "link", "set", "dev", tmpif->mi_ifname, "netns", buf, (char *)NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ if (wait_for_pid(pid) != 0)
+ fprintf(stderr, "Could not move interface %s "
+ "into container %d: %s\n",
+ tmpif->mi_ifname, pid, strerror(errno));
}
}
if (daemonize)
exit(EXIT_SUCCESS);
- if (waitpid(pid, &status, 0) < 0) {
+ if (wait_for_pid(pid) != 0) {
fprintf(stderr, "failed to wait for '%d'\n", pid);
exit(EXIT_FAILURE);
}
/* Call exit() directly on this function because it retuns an exit code. */
- exit(lxc_error_set_and_log(pid, status));
+ exit(EXIT_SUCCESS);
}
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
index 71b499659..7279b3d4c 100644
--- a/src/lxc/tools/tool_utils.c
+++ b/src/lxc/tools/tool_utils.c
@@ -31,6 +31,7 @@
#include <strings.h>
#include <unistd.h>
#include <linux/sched.h>
+#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -42,6 +43,7 @@
#include <lxc/lxccontainer.h>
+#include "arguments.h"
#include "tool_utils.h"
int lxc_fill_elevated_privileges(char *flaglist, int *flags)
@@ -1131,3 +1133,64 @@ ssize_t lxc_read_nointr(int fd, void* buf, size_t count)
goto again;
return ret;
}
+
+static int mount_fs(const char *source, const char *target, const char *type)
+{
+ /* the umount may fail */
+ if (umount(target) < 0)
+
+ if (mount(source, target, type, 0, NULL) < 0)
+ return -1;
+
+ return 0;
+}
+
+void lxc_setup_fs(void)
+{
+ (void)mount_fs("proc", "/proc", "proc");
+
+ /* if /dev has been populated by us, /dev/shm does not exist */
+ if (access("/dev/shm", F_OK))
+ (void)mkdir("/dev/shm", 0777);
+
+ /* if we can't mount /dev/shm, continue anyway */
+ (void)mount_fs("shmfs", "/dev/shm", "tmpfs");
+
+ /* 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))
+ (void)mkdir("/dev/mqueue", 0666);
+
+ /* continue even without posix message queue support */
+ (void)mount_fs("mqueue", "/dev/mqueue", "mqueue");
+}
+
+struct clone_arg {
+ int (*fn)(void *);
+ void *arg;
+};
+
+static int do_clone(void *arg)
+{
+ struct clone_arg *clone_arg = arg;
+ return clone_arg->fn(clone_arg->arg);
+}
+
+pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
+{
+ struct clone_arg clone_arg = {
+ .fn = fn,
+ .arg = arg,
+ };
+
+ size_t stack_size = lxc_getpagesize();
+ void *stack = alloca(stack_size);
+ pid_t ret;
+
+#ifdef __ia64__
+ ret = __clone2(do_clone, stack, stack_size, flags | SIGCHLD, &clone_arg);
+#else
+ ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg);
+#endif
+ return ret;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
index db43fa49d..5ebb4542c 100644
--- a/src/lxc/tools/tool_utils.h
+++ b/src/lxc/tools/tool_utils.h
@@ -119,4 +119,28 @@ extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count);
extern char *get_rundir();
+extern void lxc_setup_fs(void);
+
+static inline uint64_t lxc_getpagesize(void)
+{
+ int64_t pgsz;
+
+ pgsz = sysconf(_SC_PAGESIZE);
+ if (pgsz <= 0)
+ pgsz = 1 << 12;
+
+ return pgsz;
+}
+
+#if defined(__ia64__)
+int __clone2(int (*__fn) (void *__arg), void *__child_stack_base,
+ size_t __child_stack_size, int __flags, void *__arg, ...);
+#else
+int clone(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, ...
+ /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
+#endif
+
+extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
+
#endif /* __LXC_UTILS_H */
From 4daf1def0e032afc6ff1038b5e35c72d43d55ff8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 12 Jan 2018 17:29:01 +0100
Subject: [PATCH 30/30] tools: move lxc-monitor to API only
Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 2 +-
src/lxc/commands.c | 1 -
src/lxc/lxccontainer.c | 1 -
src/lxc/state.c | 1 -
src/lxc/tools/lxc_monitor.c | 21 +--
src/lxc/tools/tool_monitor.c | 392 +++++++++++++++++++++++++++++++++++++++++++
src/lxc/tools/tool_monitor.h | 115 +++++++++++++
7 files changed, 519 insertions(+), 14 deletions(-)
create mode 100644 src/lxc/tools/tool_monitor.c
create mode 100644 src/lxc/tools/tool_monitor.h
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 02ae0e753..95f9040c6 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -278,7 +278,7 @@ lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c tools/tool_utils.c
lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c tools/tool_utils.c
lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c tools/tool_utils.c
lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c tools/tool_utils.c
-lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c tools/tool_utils.c
+lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c tools/tool_utils.c tools/tool_monitor.c
lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c tools/tool_utils.c
lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c tools/tool_utils.c
lxc_start_SOURCES = tools/lxc_start.c tools/arguments.c tools/tool_utils.c
diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 8ce658363..f8c9d8c7c 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -47,7 +47,6 @@
#include "lxc.h"
#include "lxclock.h"
#include "mainloop.h"
-#include "monitor.h"
#include "start.h"
#include "utils.h"
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 2a4bb51f3..65acadd14 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -55,7 +55,6 @@
#include "lxc.h"
#include "lxccontainer.h"
#include "lxclock.h"
-#include "monitor.h"
#include "namespace.h"
#include "network.h"
#include "start.h"
diff --git a/src/lxc/state.c b/src/lxc/state.c
index 9c9bf8318..afe29e427 100644
--- a/src/lxc/state.c
+++ b/src/lxc/state.c
@@ -40,7 +40,6 @@
#include "config.h"
#include "log.h"
#include "lxc.h"
-#include "monitor.h"
#include "start.h"
lxc_log_define(lxc_state, lxc);
diff --git a/src/lxc/tools/lxc_monitor.c b/src/lxc/tools/lxc_monitor.c
index 0b094af11..75ce8c2b9 100644
--- a/src/lxc/tools/lxc_monitor.c
+++ b/src/lxc/tools/lxc_monitor.c
@@ -20,22 +20,24 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <libgen.h>
+#include <poll.h>
+#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <libgen.h>
#include <unistd.h>
-#include <regex.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <errno.h>
-#include <poll.h>
-#include "lxc.h"
-#include "log.h"
-#include "monitor.h"
+#include <lxc/lxccontainer.h>
+
#include "arguments.h"
-#include "lxccontainer.h"
+#include "tool_utils.h"
+#include "tool_monitor.h"
static bool quit_monitord;
@@ -109,7 +111,6 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(rc_main);
- lxc_log_options_no_override();
/* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
@@ -160,7 +161,7 @@ int main(int argc, char *argv[])
}
nfds = my_args.lxcpath_cnt;
- for (i = 0; i < nfds; i++) {
+ for (i = 0; (unsigned long)i < nfds; i++) {
int fd;
lxc_monitord_spawn(my_args.lxcpath[i]);
diff --git a/src/lxc/tools/tool_monitor.c b/src/lxc/tools/tool_monitor.c
new file mode 100644
index 000000000..6dcdd340d
--- /dev/null
+++ b/src/lxc/tools/tool_monitor.c
@@ -0,0 +1,392 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <daniel.lezcano at free.fr>
+ * Dwight Engen <dwight.engen at oracle.com>
+ *
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "config.h"
+#include "af_unix.h"
+#include "error.h"
+#include "log.h"
+#include "lxclock.h"
+#include "monitor.h"
+#include "state.h"
+#include "utils.h"
+
+lxc_log_define(lxc_monitor, lxc);
+
+/* routines used by monitor publishers (containers) */
+int lxc_monitor_fifo_name(const char *lxcpath, char *fifo_path, size_t fifo_path_sz,
+ int do_mkdirp)
+{
+ int ret;
+ char *rundir;
+
+ rundir = get_rundir();
+ if (!rundir)
+ return -1;
+
+ if (do_mkdirp) {
+ ret = snprintf(fifo_path, fifo_path_sz, "%s/lxc/%s", rundir, lxcpath);
+ if (ret < 0 || (size_t)ret >= fifo_path_sz) {
+ ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo.", rundir, lxcpath);
+ free(rundir);
+ return -1;
+ }
+ ret = mkdir_p(fifo_path, 0755);
+ if (ret < 0) {
+ ERROR("Unable to create monitor fifo directory %s.", fifo_path);
+ free(rundir);
+ return ret;
+ }
+ }
+ ret = snprintf(fifo_path, fifo_path_sz, "%s/lxc/%s/monitor-fifo", rundir, lxcpath);
+ if (ret < 0 || (size_t)ret >= fifo_path_sz) {
+ ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo.", rundir, lxcpath);
+ free(rundir);
+ return -1;
+ }
+ free(rundir);
+ return 0;
+}
+
+static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath)
+{
+ int fd,ret;
+ char fifo_path[PATH_MAX];
+
+ BUILD_BUG_ON(sizeof(*msg) > PIPE_BUF); /* write not guaranteed atomic */
+
+ ret = lxc_monitor_fifo_name(lxcpath, fifo_path, sizeof(fifo_path), 0);
+ if (ret < 0)
+ return;
+
+ /* Open the fifo nonblock in case the monitor is dead, we don't want the
+ * open to wait for a reader since it may never come.
+ */
+ fd = open(fifo_path, O_WRONLY | O_NONBLOCK);
+ if (fd < 0) {
+ /* It is normal for this open() to fail with ENXIO when there is
+ * no monitor running, so we don't log it.
+ */
+ if (errno == ENXIO || errno == ENOENT)
+ return;
+
+ WARN("%s - Failed to open fifo to send message", strerror(errno));
+ return;
+ }
+
+ if (fcntl(fd, F_SETFL, O_WRONLY) < 0) {
+ close(fd);
+ return;
+ }
+
+ ret = write(fd, msg, sizeof(*msg));
+ if (ret != sizeof(*msg)) {
+ close(fd);
+ SYSERROR("Failed to write to monitor fifo \"%s\".", fifo_path);
+ return;
+ }
+
+ close(fd);
+}
+
+void lxc_monitor_send_state(const char *name, lxc_state_t state,
+ const char *lxcpath)
+{
+ struct lxc_msg msg = {.type = lxc_msg_state, .value = state};
+ strncpy(msg.name, name, sizeof(msg.name));
+ msg.name[sizeof(msg.name) - 1] = 0;
+
+ lxc_monitor_fifo_send(&msg, lxcpath);
+}
+
+void lxc_monitor_send_exit_code(const char *name, int exit_code,
+ const char *lxcpath)
+{
+ struct lxc_msg msg = {.type = lxc_msg_exit_code, .value = exit_code};
+ strncpy(msg.name, name, sizeof(msg.name));
+ msg.name[sizeof(msg.name) - 1] = 0;
+
+ lxc_monitor_fifo_send(&msg, lxcpath);
+}
+
+/* routines used by monitor subscribers (lxc-monitor) */
+int lxc_monitor_close(int fd)
+{
+ return close(fd);
+}
+
+/* Enforces \0-termination for the abstract unix socket. This is not required
+ * but allows us to print it out.
+ *
+ * Older version of liblxc only allowed for 105 bytes to be used for the
+ * abstract unix domain socket name because the code for our abstract unix
+ * socket handling performed invalid checks. Since we \0-terminate we could now
+ * have a maximum of 106 chars. But to not break backwards compatibility we keep
+ * the limit at 105.
+ */
+int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr) {
+ size_t len;
+ int ret;
+ char *path;
+ uint64_t hash;
+
+ /* addr.sun_path is only 108 bytes, so we hash the full name and
+ * then append as much of the name as we can fit.
+ */
+ memset(addr, 0, sizeof(*addr));
+ addr->sun_family = AF_UNIX;
+
+ /* strlen("lxc/") + strlen("/monitor-sock") + 1 = 18 */
+ len = strlen(lxcpath) + 18;
+ path = alloca(len);
+ ret = snprintf(path, len, "lxc/%s/monitor-sock", lxcpath);
+ if (ret < 0 || (size_t)ret >= len) {
+ ERROR("failed to create name for monitor socket");
+ return -1;
+ }
+
+ /* Note: snprintf() will \0-terminate addr->sun_path on the 106th byte
+ * and so the abstract socket name has 105 "meaningful" characters. This
+ * is absolutely intentional. For further info read the comment for this
+ * function above!
+ */
+ len = sizeof(addr->sun_path) - 1;
+ hash = fnv_64a_buf(path, ret, FNV1A_64_INIT);
+ ret = snprintf(addr->sun_path, len, "@lxc/%016" PRIx64 "/%s", hash, lxcpath);
+ if (ret < 0) {
+ ERROR("failed to create hashed name for monitor socket");
+ return -1;
+ }
+
+ /* replace @ with \0 */
+ addr->sun_path[0] = '\0';
+ INFO("using monitor socket name \"%s\" (length of socket name %zu must be <= %zu)", &addr->sun_path[1], strlen(&addr->sun_path[1]), sizeof(addr->sun_path) - 3);
+
+ return 0;
+}
+
+int lxc_monitor_open(const char *lxcpath)
+{
+ struct sockaddr_un addr;
+ int fd;
+ size_t retry;
+ size_t len;
+ int ret = -1;
+ int backoff_ms[] = {10, 50, 100};
+
+ if (lxc_monitor_sock_name(lxcpath, &addr) < 0)
+ return -1;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ ERROR("Failed to create socket: %s.", strerror(errno));
+ return -errno;
+ }
+
+ len = strlen(&addr.sun_path[1]);
+ DEBUG("opening monitor socket %s with len %zu", &addr.sun_path[1], len);
+ if (len >= sizeof(addr.sun_path) - 1) {
+ errno = ENAMETOOLONG;
+ ret = -errno;
+ ERROR("name of monitor socket too long (%zu bytes): %s", len, strerror(errno));
+ goto on_error;
+ }
+
+ for (retry = 0; retry < sizeof(backoff_ms) / sizeof(backoff_ms[0]); retry++) {
+ fd = lxc_abstract_unix_connect(addr.sun_path);
+ if (fd != -1 || errno != ECONNREFUSED)
+ break;
+ ERROR("Failed to connect to monitor socket. Retrying in %d ms: %s", backoff_ms[retry], strerror(errno));
+ usleep(backoff_ms[retry] * 1000);
+ }
+
+ if (fd < 0) {
+ ret = -errno;
+ ERROR("Failed to connect to monitor socket: %s.", strerror(errno));
+ goto on_error;
+ }
+
+ return fd;
+
+on_error:
+ close(fd);
+ return ret;
+}
+
+int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds, struct lxc_msg *msg,
+ int timeout)
+{
+ long i;
+ int ret;
+
+ ret = poll(fds, nfds, timeout * 1000);
+ if (ret == -1)
+ return -1;
+ else if (ret == 0)
+ return -2; /* timed out */
+
+ /* Only read from the first ready fd, the others will remain ready for
+ * when this routine is called again.
+ */
+ for (i = 0; i < nfds; i++) {
+ if (fds[i].revents != 0) {
+ fds[i].revents = 0;
+ ret = recv(fds[i].fd, msg, sizeof(*msg), 0);
+ if (ret <= 0) {
+ SYSERROR("Failed to receive message. Did monitord die?: %s.", strerror(errno));
+ return -1;
+ }
+ return ret;
+ }
+ }
+
+ SYSERROR("No ready fd found.");
+
+ return -1;
+}
+
+int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout)
+{
+ struct pollfd fds;
+
+ fds.fd = fd;
+ fds.events = POLLIN | POLLPRI;
+ fds.revents = 0;
+
+ return lxc_monitor_read_fdset(&fds, 1, msg, timeout);
+}
+
+int lxc_monitor_read(int fd, struct lxc_msg *msg)
+{
+ return lxc_monitor_read_timeout(fd, msg, -1);
+}
+
+#define LXC_MONITORD_PATH LIBEXECDIR "/lxc/lxc-monitord"
+
+/* Used to spawn a monitord either on startup of a daemon container, or when
+ * lxc-monitor starts.
+ */
+int lxc_monitord_spawn(const char *lxcpath)
+{
+ int ret;
+ int pipefd[2];
+ char pipefd_str[LXC_NUMSTRLEN64];
+ pid_t pid1, pid2;
+
+ char *const args[] = {
+ LXC_MONITORD_PATH,
+ (char *)lxcpath,
+ pipefd_str,
+ NULL,
+ };
+
+ /* double fork to avoid zombies when monitord exits */
+ pid1 = fork();
+ if (pid1 < 0) {
+ SYSERROR("Failed to fork().");
+ return -1;
+ }
+
+ if (pid1) {
+ DEBUG("Going to wait for pid %d.", pid1);
+ if (waitpid(pid1, NULL, 0) != pid1)
+ return -1;
+ DEBUG("Finished waiting on pid %d.", pid1);
+ return 0;
+ }
+
+ if (pipe(pipefd) < 0) {
+ SYSERROR("Failed to create pipe.");
+ exit(EXIT_FAILURE);
+ }
+
+ pid2 = fork();
+ if (pid2 < 0) {
+ SYSERROR("Failed to fork().");
+ exit(EXIT_FAILURE);
+ }
+
+ if (pid2) {
+ DEBUG("Trying to sync with child process.");
+ char c;
+ /* Wait for daemon to create socket. */
+ close(pipefd[1]);
+
+ /* Sync with child, we're ignoring the return from read
+ * because regardless if it works or not, either way we've
+ * synced with the child process. the if-empty-statement
+ * construct is to quiet the warn-unused-result warning.
+ */
+ if (read(pipefd[0], &c, 1))
+ ;
+
+ close(pipefd[0]);
+
+ DEBUG("Successfully synced with child process.");
+ exit(EXIT_SUCCESS);
+ }
+
+ if (setsid() < 0) {
+ SYSERROR("Failed to setsid().");
+ exit(EXIT_FAILURE);
+ }
+
+ lxc_check_inherited(NULL, true, &pipefd[1], 1);
+ if (null_stdfds() < 0) {
+ SYSERROR("Failed to dup2() standard file descriptors to /dev/null.");
+ exit(EXIT_FAILURE);
+ }
+
+ close(pipefd[0]);
+
+ ret = snprintf(pipefd_str, LXC_NUMSTRLEN64, "%d", pipefd[1]);
+ if (ret < 0 || ret >= LXC_NUMSTRLEN64) {
+ ERROR("Failed to create pid argument to pass to monitord.");
+ exit(EXIT_FAILURE);
+ }
+
+ DEBUG("Using pipe file descriptor %d for monitord.", pipefd[1]);
+
+ execvp(args[0], args);
+ SYSERROR("failed to exec lxc-monitord");
+
+ exit(EXIT_FAILURE);
+}
diff --git a/src/lxc/tools/tool_monitor.h b/src/lxc/tools/tool_monitor.h
new file mode 100644
index 000000000..33c3a345a
--- /dev/null
+++ b/src/lxc/tools/tool_monitor.h
@@ -0,0 +1,115 @@
+/*
+ * 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_MONITOR_H
+#define __LXC_MONITOR_H
+
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/un.h>
+#include <poll.h>
+
+typedef enum {
+ lxc_msg_state,
+ lxc_msg_priority,
+ lxc_msg_exit_code,
+} lxc_msg_type_t;
+
+struct lxc_msg {
+ lxc_msg_type_t type;
+ char name[NAME_MAX+1];
+ int value;
+};
+
+typedef enum {
+ STOPPED,
+ STARTING,
+ RUNNING,
+ STOPPING,
+ ABORTING,
+ FREEZING,
+ FROZEN,
+ THAWED,
+ MAX_STATE,
+} lxc_state_t;
+
+const char *const strstate[] = {
+ "STOPPED", "STARTING", "RUNNING", "STOPPING",
+ "ABORTING", "FREEZING", "FROZEN", "THAWED",
+};
+
+static inline const char *lxc_state2str(lxc_state_t state)
+{
+ if (state < STOPPED || state > MAX_STATE - 1)
+ return NULL;
+ return strstate[state];
+}
+
+extern int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr);
+extern int lxc_monitor_fifo_name(const char *lxcpath, char *fifo_path,
+ size_t fifo_path_sz, int do_mkdirp);
+extern void lxc_monitor_send_state(const char *name, lxc_state_t state,
+ const char *lxcpath);
+extern void lxc_monitor_send_exit_code(const char *name, int exit_code,
+ const char *lxcpath);
+extern int lxc_monitord_spawn(const char *lxcpath);
+
+/*
+ * Open the monitoring mechanism for a specific container
+ * The function will return an fd corresponding to the events
+ * Returns a file descriptor on success, < 0 otherwise
+ */
+extern int lxc_monitor_open(const char *lxcpath);
+
+/*
+ * Blocking read for the next container state change
+ * @fd : the file descriptor provided by lxc_monitor_open
+ * @msg : the variable which will be filled with the state
+ * Returns 0 if the monitored container has exited, > 0 if
+ * data was read, < 0 otherwise
+ */
+extern int lxc_monitor_read(int fd, struct lxc_msg *msg);
+
+/*
+ * Blocking read for the next container state change with timeout
+ * @fd : the file descriptor provided by lxc_monitor_open
+ * @msg : the variable which will be filled with the state
+ * @timeout : the timeout in seconds to wait for a state change
+ * Returns 0 if the monitored container has exited, > 0 if
+ * data was read, < 0 otherwise
+ */
+extern int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout);
+
+/*
+ * Blocking read from multiple monitors for the next container state
+ * change with timeout
+ * @fds : struct pollfd descripting the fds to use
+ * @nfds : the number of entries in fds
+ * @msg : the variable which will be filled with the state
+ * @timeout : the timeout in seconds to wait for a state change
+ * Returns 0 if the monitored container has exited, > 0 if
+ * data was read, < 0 otherwise
+ */
+extern int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds, struct lxc_msg *msg,
+ int timeout);
+
+#endif
More information about the lxc-devel
mailing list