Unverified Commit 2d876a97 by Christian Brauner Committed by GitHub

Merge pull request #2437 from 2xsec/bugfix

tools: share internal API symbols
parents bb9f9ced 1b087dab
...@@ -17,8 +17,6 @@ noinst_HEADERS = \ ...@@ -17,8 +17,6 @@ noinst_HEADERS = \
storage/zfs.h \ storage/zfs.h \
storage/storage_utils.h \ storage/storage_utils.h \
tools/arguments.h \ tools/arguments.h \
tools/tool_utils.h \
tools/tool_list.h \
cgroups/cgroup.h \ cgroups/cgroup.h \
cgroups/cgroup_utils.h \ cgroups/cgroup_utils.h \
caps.h \ caps.h \
...@@ -265,28 +263,28 @@ endif ...@@ -265,28 +263,28 @@ endif
LDADD=liblxc.la @CAP_LIBS@ @GNUTLS_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@ LDADD=liblxc.la @CAP_LIBS@ @GNUTLS_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
if ENABLE_TOOLS if ENABLE_TOOLS
lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c tools/tool_utils.c lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c
lxc_autostart_SOURCES = tools/lxc_autostart.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 tools/tool_utils.c lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c
lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c tools/tool_utils.c lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c
lxc_console_SOURCES = tools/lxc_console.c tools/arguments.c tools/tool_utils.c lxc_console_SOURCES = tools/lxc_console.c tools/arguments.c
lxc_destroy_SOURCES = tools/lxc_destroy.c tools/arguments.c tools/tool_utils.c lxc_destroy_SOURCES = tools/lxc_destroy.c tools/arguments.c
lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c tools/tool_utils.c lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c
lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c tools/tool_utils.c lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c
lxc_freeze_SOURCES = tools/lxc_freeze.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 tools/tool_utils.c lxc_info_SOURCES = tools/lxc_info.c tools/arguments.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
lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c tools/tool_utils.c lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c
lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c tools/tool_utils.c lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c
lxc_start_SOURCES = tools/lxc_start.c tools/arguments.c tools/tool_utils.c lxc_start_SOURCES = tools/lxc_start.c tools/arguments.c
lxc_stop_SOURCES = tools/lxc_stop.c tools/arguments.c tools/tool_utils.c lxc_stop_SOURCES = tools/lxc_stop.c tools/arguments.c
lxc_top_SOURCES = tools/lxc_top.c tools/arguments.c tools/tool_utils.c lxc_top_SOURCES = tools/lxc_top.c tools/arguments.c
lxc_unfreeze_SOURCES = tools/lxc_unfreeze.c tools/arguments.c tools/tool_utils.c lxc_unfreeze_SOURCES = tools/lxc_unfreeze.c tools/arguments.c
lxc_unshare_SOURCES = tools/lxc_unshare.c tools/arguments.c tools/tool_utils.c lxc_unshare_SOURCES = tools/lxc_unshare.c tools/arguments.c
lxc_wait_SOURCES = tools/lxc_wait.c tools/arguments.c tools/tool_utils.c lxc_wait_SOURCES = tools/lxc_wait.c tools/arguments.c
lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c tools/tool_utils.c lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c
lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c tools/tool_utils.c lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c
lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c tools/tool_utils.c lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c
endif endif
if ENABLE_COMMANDS if ENABLE_COMMANDS
......
...@@ -2388,14 +2388,72 @@ on_error: ...@@ -2388,14 +2388,72 @@ on_error:
return ret; return ret;
} }
static int lxc_config_readline(char *buffer, struct lxc_conf *conf) static struct new_config_item *parse_new_conf_line(char *buffer)
{ {
struct parse_line_conf c; char *dot, *key, *line, *linep, *value;
int ret = 0;
char *dup = buffer;
struct new_config_item *new = NULL;
c.conf = conf; linep = line = strdup(dup);
c.from_include = false; 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.", strlen(line)))
goto on_error;
ret = -1;
dot = strchr(line, '=');
if (!dot) {
ERROR("Invalid configuration item: %s", 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;
return parse_line(buffer, &c); 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_read(const char *file, struct lxc_conf *conf, bool from_include) int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
...@@ -2425,28 +2483,43 @@ int lxc_config_define_add(struct lxc_list *defines, char *arg) ...@@ -2425,28 +2483,43 @@ int lxc_config_define_add(struct lxc_list *defines, char *arg)
if (!dent) if (!dent)
return -1; return -1;
dent->elem = arg; dent->elem = parse_new_conf_line(arg);
if (!dent->elem) {
free(dent);
return -1;
}
lxc_list_add_tail(defines, dent); lxc_list_add_tail(defines, dent);
return 0; return 0;
} }
int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf) bool lxc_config_define_load(struct lxc_list *defines, struct lxc_container *c)
{ {
struct lxc_list *it, *next; struct lxc_list *it;
int ret = 0; bool bret = true;
lxc_list_for_each(it, defines) { lxc_list_for_each(it, defines) {
ret = lxc_config_readline(it->elem, conf); struct new_config_item *new_item = it->elem;
if (ret) bret = c->set_config_item(c, new_item->key, new_item->val);
if (!bret)
break; break;
} }
lxc_config_define_free(defines);
return bret;
}
void lxc_config_define_free(struct lxc_list *defines)
{
struct lxc_list *it, *next;
lxc_list_for_each_safe(it, defines, 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); lxc_list_del(it);
free(it); free(it);
} }
return ret;
} }
signed long lxc_config_parse_arch(const char *arch) signed long lxc_config_parse_arch(const char *arch)
...@@ -2494,6 +2567,49 @@ signed long lxc_config_parse_arch(const char *arch) ...@@ -2494,6 +2567,49 @@ signed long lxc_config_parse_arch(const char *arch)
return -1; 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. */ /* Write out a configuration file. */
int write_config(int fd, const struct lxc_conf *conf) int write_config(int fd, const struct lxc_conf *conf)
{ {
......
...@@ -58,6 +58,11 @@ struct lxc_config_t { ...@@ -58,6 +58,11 @@ struct lxc_config_t {
config_clr_cb clr; config_clr_cb clr;
}; };
struct new_config_item {
char *key;
char *val;
};
/* Get the jump table entry for the given configuration key. */ /* Get the jump table entry for the given configuration key. */
extern struct lxc_config_t *lxc_get_config(const char *key); extern struct lxc_config_t *lxc_get_config(const char *key);
...@@ -85,12 +90,16 @@ extern int append_unexp_config_line(const char *line, struct lxc_conf *conf); ...@@ -85,12 +90,16 @@ extern int append_unexp_config_line(const char *line, struct lxc_conf *conf);
extern int lxc_config_define_add(struct lxc_list *defines, char* arg); extern int lxc_config_define_add(struct lxc_list *defines, char* arg);
extern int lxc_config_define_load(struct lxc_list *defines, extern bool lxc_config_define_load(struct lxc_list *defines,
struct lxc_conf *conf); struct lxc_container *c);
extern void lxc_config_define_free(struct lxc_list *defines);
/* needed for lxc-attach */ /* needed for lxc-attach */
extern signed long lxc_config_parse_arch(const char *arch); 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 int lxc_clear_config_item(struct lxc_conf *c, const char *key);
extern int write_config(int fd, const struct lxc_conf *conf); extern int write_config(int fd, const struct lxc_conf *conf);
......
...@@ -68,7 +68,6 @@ struct prctl_mm_map { ...@@ -68,7 +68,6 @@ struct prctl_mm_map {
}; };
#endif #endif
extern void lxc_setup_fs(void);
extern const char *lxc_global_config_value(const char *option_name); extern const char *lxc_global_config_value(const char *option_name);
/* open a file with O_CLOEXEC */ /* open a file with O_CLOEXEC */
......
...@@ -303,10 +303,10 @@ int lxc_monitord_spawn(const char *lxcpath) ...@@ -303,10 +303,10 @@ int lxc_monitord_spawn(const char *lxcpath)
pid_t pid1, pid2; pid_t pid1, pid2;
char *const args[] = { char *const args[] = {
LXC_MONITORD_PATH, LXC_MONITORD_PATH,
(char *)lxcpath, (char *)lxcpath,
pipefd_str, pipefd_str,
NULL, NULL,
}; };
/* double fork to avoid zombies when monitord exits */ /* double fork to avoid zombies when monitord exits */
...@@ -318,8 +318,10 @@ int lxc_monitord_spawn(const char *lxcpath) ...@@ -318,8 +318,10 @@ int lxc_monitord_spawn(const char *lxcpath)
if (pid1) { if (pid1) {
DEBUG("Going to wait for pid %d.", pid1); DEBUG("Going to wait for pid %d.", pid1);
if (waitpid(pid1, NULL, 0) != pid1) if (waitpid(pid1, NULL, 0) != pid1)
return -1; return -1;
DEBUG("Finished waiting on pid %d.", pid1); DEBUG("Finished waiting on pid %d.", pid1);
return 0; return 0;
} }
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <lxc/version.h> #include <lxc/version.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "namespace.h"
static int build_shortopts(const struct option *a_options, char *a_shortopts, static int build_shortopts(const struct option *a_options, char *a_shortopts,
size_t a_size) size_t a_size)
......
...@@ -174,25 +174,6 @@ extern int lxc_arguments_str_to_int(struct lxc_arguments *args, ...@@ -174,25 +174,6 @@ extern int lxc_arguments_str_to_int(struct lxc_arguments *args,
extern bool lxc_setup_shared_ns(struct lxc_arguments *args, struct lxc_container *c); extern bool lxc_setup_shared_ns(struct lxc_arguments *args, struct lxc_container *c);
/* Helper macro to define errno string. */
#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined(_GNU_SOURCE) || IS_BIONIC
#define lxc_log_strerror_r \
char errno_buf[MAXPATHLEN / 2] = {"Failed to get errno string"}; \
char *ptr = errno_buf; \
{ \
(void)strerror_r(errno, errno_buf, sizeof(errno_buf)); \
}
#else
#define lxc_log_strerror_r \
char errno_buf[MAXPATHLEN / 2] = {"Failed to get errno string"}; \
char *ptr; \
{ \
ptr = strerror_r(errno, errno_buf, sizeof(errno_buf)); \
if (!ptr) \
ptr = errno_buf; \
}
#endif
#define lxc_info(arg, fmt, args...) \ #define lxc_info(arg, fmt, args...) \
do { \ do { \
if (!(arg)->quiet) { \ if (!(arg)->quiet) { \
...@@ -210,8 +191,7 @@ extern bool lxc_setup_shared_ns(struct lxc_arguments *args, struct lxc_container ...@@ -210,8 +191,7 @@ extern bool lxc_setup_shared_ns(struct lxc_arguments *args, struct lxc_container
#define lxc_sys_error(arg, fmt, args...) \ #define lxc_sys_error(arg, fmt, args...) \
do { \ do { \
if (!(arg)->quiet) { \ if (!(arg)->quiet) { \
lxc_log_strerror_r \ fprintf(stderr, "%s: " fmt "\n", (arg)->progname, ##args); \
fprintf(stderr, "%s: %s - " fmt "\n", (arg)->progname, ptr, ##args); \
} \ } \
} while (0) } while (0)
......
...@@ -37,7 +37,13 @@ ...@@ -37,7 +37,13 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "attach.h"
#include "caps.h"
#include "confile.h"
#include "log.h"
#include "utils.h"
lxc_log_define(lxc_attach, lxc);
static const struct option my_longopts[] = { static const struct option my_longopts[] = {
{"elevated-privileges", optional_argument, 0, 'e'}, {"elevated-privileges", optional_argument, 0, 'e'},
...@@ -108,7 +114,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) ...@@ -108,7 +114,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
case 'a': case 'a':
new_personality = lxc_config_parse_arch(arg); new_personality = lxc_config_parse_arch(arg);
if (new_personality < 0) { if (new_personality < 0) {
lxc_error(args, "invalid architecture specified: %s", arg); ERROR("Invalid architecture specified: %s", arg);
return -1; return -1;
} }
break; break;
...@@ -153,14 +159,14 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) ...@@ -153,14 +159,14 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
case 502: /* keep-var */ case 502: /* keep-var */
ret = add_to_simple_array(&extra_keep, &extra_keep_size, arg); ret = add_to_simple_array(&extra_keep, &extra_keep_size, arg);
if (ret < 0) { if (ret < 0) {
lxc_error(args, "memory allocation error"); ERROR("Failed to alloc memory");
return -1; return -1;
} }
break; break;
case 'v': case 'v':
ret = add_to_simple_array(&extra_env, &extra_env_size, arg); ret = add_to_simple_array(&extra_env, &extra_env_size, arg);
if (ret < 0) { if (ret < 0) {
lxc_error(args, "memory allocation error"); ERROR("Failed to alloc memory");
return -1; return -1;
} }
break; break;
...@@ -246,7 +252,7 @@ static int lxc_attach_create_log_file(const char *log_file) ...@@ -246,7 +252,7 @@ static int lxc_attach_create_log_file(const char *log_file)
fd = open(log_file, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600); fd = open(log_file, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600);
if (fd < 0) { if (fd < 0) {
lxc_error(&my_args, "Failed to open log file \"%s\"", log_file); ERROR("Failed to open log file \"%s\"", log_file);
return -1; return -1;
} }
...@@ -285,7 +291,7 @@ int main(int argc, char *argv[]) ...@@ -285,7 +291,7 @@ int main(int argc, char *argv[])
if (geteuid()) { if (geteuid()) {
if (access(my_args.lxcpath[0], O_RDONLY) < 0) { if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
lxc_error(&my_args, "You lack access to %s", my_args.lxcpath[0]); ERROR("You lack access to %s", my_args.lxcpath[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -297,21 +303,21 @@ int main(int argc, char *argv[]) ...@@ -297,21 +303,21 @@ int main(int argc, char *argv[])
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
lxc_error(&my_args, "Failed to load rcfile"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
lxc_error(&my_args, "Out of memory setting new config filename"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
lxc_error(&my_args, "Insufficent privileges to control %s", c->name); ERROR("Insufficent privileges to control %s", c->name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -355,6 +361,7 @@ int main(int argc, char *argv[]) ...@@ -355,6 +361,7 @@ int main(int argc, char *argv[])
if (WIFEXITED(ret)) if (WIFEXITED(ret))
wexit = WEXITSTATUS(ret); wexit = WEXITSTATUS(ret);
out: out:
lxc_container_put(c); lxc_container_put(c);
if (ret >= 0) if (ret >= 0)
......
...@@ -27,14 +27,17 @@ ...@@ -27,14 +27,17 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_list.h" #include "list.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
lxc_log_define(lxc_autostart, lxc);
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);
struct lxc_list *cmd_groups_list = NULL; struct lxc_list *cmd_groups_list = NULL;
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) { switch (c) {
case 'k': case 'k':
...@@ -101,52 +104,27 @@ Options:\n\ ...@@ -101,52 +104,27 @@ Options:\n\
.timeout = 60, .timeout = 60,
}; };
int list_contains_entry( char *str_ptr, struct lxc_list *p1 ) { static int list_contains_entry(char *str_ptr, struct lxc_list *p1) {
struct lxc_list *it1; struct lxc_list *it1;
/* /*
* If the entry is NULL or the empty string and the list * If the entry is NULL or the empty string and the list
* is NULL, we have a match * is NULL, we have a match
*/ */
if (! p1 && ! str_ptr) if (!p1 && (!str_ptr || !*str_ptr))
return 1;
if (! p1 && ! *str_ptr)
return 1; return 1;
if (!p1) if (!p1)
return 0; return 0;
lxc_list_for_each(it1, p1) { lxc_list_for_each(it1, p1) {
if (strcmp(it1->elem, str_ptr) == 0) if (strncmp(it1->elem, str_ptr, strlen(it1->elem)) == 0)
return 1; return 1;
} }
return 0; return 0;
} }
int lists_contain_common_entry(struct lxc_list *p1, struct lxc_list *p2) {
struct lxc_list *it1;
struct lxc_list *it2;
if (!p1 && !p2)
return 1;
if (!p1)
return 0;
if (!p2)
return 0;
lxc_list_for_each(it1, p1) {
lxc_list_for_each(it2, p2) {
if (strcmp(it1->elem, it2->elem) == 0)
return 1;
}
}
return 0;
}
/* This is a variation of get_list below it. This version allows two additional /* 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 * 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. * entries (i.e. "group1,,group2") generating and empty list entry.
...@@ -167,6 +145,11 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter, ...@@ -167,6 +145,11 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter,
workstr_list = str_list; workstr_list = str_list;
if (!workstr_list) { if (!workstr_list) {
workstr_list = malloc(sizeof(*workstr_list)); workstr_list = malloc(sizeof(*workstr_list));
if (!workstr_list) {
free(workstr);
return NULL;
}
lxc_list_init(workstr_list); lxc_list_init(workstr_list);
} }
...@@ -185,9 +168,9 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter, ...@@ -185,9 +168,9 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter,
*/ */
if (list_contains_entry(workptr, workstr_list)) { if (list_contains_entry(workptr, workstr_list)) {
if (*workptr) if (*workptr)
fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr); ERROR("Duplicate group \"%s\" in list - ignoring", workptr);
else else
fprintf(stderr, "Duplicate NULL group in list - ignoring\n"); ERROR("Duplicate NULL group in list - ignoring");
} else { } else {
worklist = malloc(sizeof(*worklist)); worklist = malloc(sizeof(*worklist));
if (!worklist) if (!worklist)
...@@ -218,6 +201,9 @@ static struct lxc_list *get_list(char *input, char *delimiter) ...@@ -218,6 +201,9 @@ static struct lxc_list *get_list(char *input, char *delimiter)
struct lxc_list *workstr_list; struct lxc_list *workstr_list;
workstr_list = malloc(sizeof(*workstr_list)); workstr_list = malloc(sizeof(*workstr_list));
if (!workstr_list)
return NULL;
lxc_list_init(workstr_list); lxc_list_init(workstr_list);
workstr = strdup(input); workstr = strdup(input);
...@@ -260,7 +246,7 @@ static struct lxc_list *get_config_list(struct lxc_container *c, char *key) ...@@ -260,7 +246,7 @@ static struct lxc_list *get_config_list(struct lxc_container *c, char *key)
return NULL; return NULL;
value = (char *)malloc(sizeof(char) * len + 1); value = (char *)malloc(sizeof(char) * len + 1);
if (value == NULL) if (!value)
return NULL; return NULL;
if (c->get_config_item(c, key, value, len + 1) != len) { if (c->get_config_item(c, key, value, len + 1) != len) {
...@@ -289,7 +275,7 @@ static int get_config_integer(struct lxc_container *c, char *key) ...@@ -289,7 +275,7 @@ static int get_config_integer(struct lxc_container *c, char *key)
return 0; return 0;
value = (char *)malloc(sizeof(char) * len + 1); value = (char *)malloc(sizeof(char) * len + 1);
if (value == NULL) if (!value)
return 0; return 0;
if (c->get_config_item(c, key, value, len + 1) != len) { if (c->get_config_item(c, key, value, len + 1) != len) {
...@@ -314,7 +300,7 @@ static int cmporder(const void *p1, const void *p2) ...@@ -314,7 +300,7 @@ static int cmporder(const void *p1, const void *p2)
int c2_order = get_config_integer(c2, "lxc.start.order"); int c2_order = get_config_integer(c2, "lxc.start.order");
if (c1_order == c2_order) if (c1_order == c2_order)
return strcmp(c1->name, c2->name); return strncmp(c1->name, c2->name, strlen(c1->name));
return (c1_order - c2_order); return (c1_order - c2_order);
} }
...@@ -372,7 +358,7 @@ int main(int argc, char *argv[]) ...@@ -372,7 +358,7 @@ int main(int argc, char *argv[])
qsort(&containers[0], count, sizeof(struct lxc_container *), cmporder); 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"); ERROR("Specifying -a (all) with -g (groups) doesn't make sense. All option overrides");
/* We need a default cmd_groups_list even for the -a /* We need a default cmd_groups_list even for the -a
* case in order to force a pass through the loop for * case in order to force a pass through the loop for
...@@ -402,29 +388,30 @@ int main(int argc, char *argv[]) ...@@ -402,29 +388,30 @@ int main(int argc, char *argv[])
*/ */
if (!c->may_control(c)) { if (!c->may_control(c)) {
/* We're done with this container */ /* We're done with this container */
if ( lxc_container_put(c) > 0 ) if (lxc_container_put(c) > 0)
containers[i] = NULL; containers[i] = NULL;
continue; continue;
} }
if (!my_args.ignore_auto && if (!my_args.ignore_auto &&
get_config_integer(c, "lxc.start.auto") != 1) { get_config_integer(c, "lxc.start.auto") != 1) {
/* We're done with this container */ /* We're done with this container */
if ( lxc_container_put(c) > 0 ) if (lxc_container_put(c) > 0)
containers[i] = NULL; containers[i] = NULL;
continue; continue;
} }
if (!my_args.all) { if (!my_args.all) {
/* Filter by group */ /* Filter by group */
if( ! c_groups_lists[i] ) { if (!c_groups_lists[i]) {
/* Now we're loading up a container's groups */ /* Now we're loading up a container's groups */
c_groups_lists[i] = get_config_list(c, "lxc.group"); c_groups_lists[i] = get_config_list(c, "lxc.group");
} }
ret = list_contains_entry(cmd_group->elem, c_groups_lists[i]); ret = list_contains_entry(cmd_group->elem, c_groups_lists[i]);
if (ret == 0) {
if ( ret == 0 ) {
/* Not in the target group this pass so /* Not in the target group this pass so
* leave in the list for subsequent * leave in the list for subsequent
* passes. * passes.
...@@ -445,10 +432,8 @@ int main(int argc, char *argv[]) ...@@ -445,10 +432,8 @@ int main(int argc, char *argv[])
} }
else { else {
if (!c->shutdown(c, my_args.timeout)) { if (!c->shutdown(c, my_args.timeout)) {
if (!c->stop(c)) { if (!c->stop(c))
fprintf(stderr, "Error shutting down container: %s\n", c->name); ERROR("Error shutting down container: %s", c->name);
fflush(stderr);
}
} }
} }
} }
...@@ -460,10 +445,8 @@ int main(int argc, char *argv[]) ...@@ -460,10 +445,8 @@ int main(int argc, char *argv[])
fflush(stdout); fflush(stdout);
} }
else { else {
if (!c->stop(c)) { if (!c->stop(c))
fprintf(stderr, "Error killing container: %s\n", c->name); ERROR("Error killing container: %s", c->name);
fflush(stderr);
}
} }
} }
} else if (my_args.reboot) { } else if (my_args.reboot) {
...@@ -475,10 +458,8 @@ int main(int argc, char *argv[]) ...@@ -475,10 +458,8 @@ int main(int argc, char *argv[])
fflush(stdout); fflush(stdout);
} }
else { else {
if (!c->reboot(c)) { if (!c->reboot(c))
fprintf(stderr, "Error rebooting container: %s\n", c->name); ERROR("Error rebooting container: %s", c->name);
fflush(stderr);
}
else else
sleep(get_config_integer(c, "lxc.start.delay")); sleep(get_config_integer(c, "lxc.start.delay"));
} }
...@@ -492,10 +473,8 @@ int main(int argc, char *argv[]) ...@@ -492,10 +473,8 @@ int main(int argc, char *argv[])
fflush(stdout); fflush(stdout);
} }
else { else {
if (!c->start(c, 0, NULL)) { if (!c->start(c, 0, NULL))
fprintf(stderr, "Error starting container: %s\n", c->name); ERROR("Error starting container: %s", c->name);
fflush(stderr);
}
else else
sleep(get_config_integer(c, "lxc.start.delay")); sleep(get_config_integer(c, "lxc.start.delay"));
} }
...@@ -507,9 +486,10 @@ int main(int argc, char *argv[]) ...@@ -507,9 +486,10 @@ int main(int argc, char *argv[])
* then we're done with this container... We can dump any * then we're done with this container... We can dump any
* c_groups_list and the container itself. * c_groups_list and the container itself.
*/ */
if ( lxc_container_put(c) > 0 ) if (lxc_container_put(c) > 0)
containers[i] = NULL; containers[i] = NULL;
if ( c_groups_lists ) {
if (c_groups_lists) {
toss_list(c_groups_lists[i]); toss_list(c_groups_lists[i]);
c_groups_lists[i] = NULL; c_groups_lists[i] = NULL;
} }
...@@ -527,7 +507,7 @@ int main(int argc, char *argv[]) ...@@ -527,7 +507,7 @@ int main(int argc, char *argv[])
} }
free(c_groups_lists); free(c_groups_lists);
toss_list( cmd_groups_list ); toss_list(cmd_groups_list);
free(containers); free(containers);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
......
...@@ -32,12 +32,14 @@ ...@@ -32,12 +32,14 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
lxc_log_define(lxc_cgroup, lxc);
static int my_checker(const struct lxc_arguments* args) static int my_checker(const struct lxc_arguments* args)
{ {
if (!args->argc) { if (!args->argc) {
lxc_error(args, "Missing state object"); ERROR("Missing state object");
return -1; return -1;
} }
...@@ -94,28 +96,29 @@ int main(int argc, char *argv[]) ...@@ -94,28 +96,29 @@ int main(int argc, char *argv[])
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
lxc_error(&my_args, "Failed to load rcfile"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
lxc_error(&my_args, "Out of memory setting new config filename"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
lxc_error(&my_args, "Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name); ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!c->is_running(c)) { if (!c->is_running(c)) {
lxc_error(&my_args, "'%s:%s' is not running", my_args.lxcpath[0], my_args.name); ERROR("'%s:%s' is not running", my_args.lxcpath[0], my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -124,25 +127,26 @@ int main(int argc, char *argv[]) ...@@ -124,25 +127,26 @@ int main(int argc, char *argv[])
value = my_args.argv[1]; value = my_args.argv[1];
if (!c->set_cgroup_item(c, state_object, value)) { if (!c->set_cgroup_item(c, state_object, value)) {
lxc_error(&my_args, "Failed to assign '%s' value to '%s' for '%s'", ERROR("Failed to assign '%s' value to '%s' for '%s'",
value, state_object, my_args.name); value, state_object, my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} else { } else {
char buffer[TOOL_MAXPATHLEN]; char buffer[MAXPATHLEN];
int ret; int ret;
ret = c->get_cgroup_item(c, state_object, buffer, TOOL_MAXPATHLEN); ret = c->get_cgroup_item(c, state_object, buffer, MAXPATHLEN);
if (ret < 0) { if (ret < 0) {
lxc_error(&my_args, "Failed to retrieve value of '%s' for '%s:%s'", ERROR("Failed to retrieve value of '%s' for '%s:%s'",
state_object, my_args.lxcpath[0], my_args.name); state_object, my_args.lxcpath[0], my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
printf("%*s", ret, buffer); INFO("%*s", ret, buffer);
} }
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
static char *checkpoint_dir = NULL; static char *checkpoint_dir = NULL;
static bool stop = false; static bool stop = false;
...@@ -53,24 +54,26 @@ static const struct option my_longopts[] = { ...@@ -53,24 +54,26 @@ static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS LXC_COMMON_OPTIONS
}; };
lxc_log_define(lxc_checkpoint, lxc);
static int my_checker(const struct lxc_arguments *args) static int my_checker(const struct lxc_arguments *args)
{ {
if (do_restore && stop) { if (do_restore && stop) {
lxc_error(args, "-s not compatible with -r."); ERROR("-s not compatible with -r");
return -1; return -1;
} else if (!do_restore && daemonize_set) { } else if (!do_restore && daemonize_set) {
lxc_error(args, "-d/-F not compatible with -r."); ERROR("-d/-F not compatible with -r");
return -1; return -1;
} }
if (checkpoint_dir == NULL) { if (!checkpoint_dir) {
lxc_error(args, "-D is required."); ERROR("-D is required");
return -1; return -1;
} }
if (pre_dump && do_restore) { if (pre_dump && do_restore) {
lxc_error(args, "-p not compatible with -r."); ERROR("-p not compatible with -r");
return -1; return -1;
} }
...@@ -116,6 +119,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) ...@@ -116,6 +119,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
return -1; return -1;
break; break;
} }
return 0; return 0;
} }
...@@ -158,7 +162,7 @@ static bool checkpoint(struct lxc_container *c) ...@@ -158,7 +162,7 @@ static bool checkpoint(struct lxc_container *c)
int mode; int mode;
if (!c->is_running(c)) { if (!c->is_running(c)) {
fprintf(stderr, "%s not running, not checkpointing.\n", my_args.name); ERROR("%s not running, not checkpointing", my_args.name);
lxc_container_put(c); lxc_container_put(c);
return false; return false;
} }
...@@ -182,7 +186,7 @@ static bool checkpoint(struct lxc_container *c) ...@@ -182,7 +186,7 @@ static bool checkpoint(struct lxc_container *c)
/* the migrate() API does not negate the return code like /* the migrate() API does not negate the return code like
* checkpoint() and restore() does. */ * checkpoint() and restore() does. */
if (ret) { if (ret) {
fprintf(stderr, "Checkpointing %s failed.\n", my_args.name); ERROR("Checkpointing %s failed", my_args.name);
return false; return false;
} }
...@@ -200,9 +204,10 @@ static bool restore_finalize(struct lxc_container *c) ...@@ -200,9 +204,10 @@ static bool restore_finalize(struct lxc_container *c)
opts.verbose = verbose; opts.verbose = verbose;
opts.stop = stop; opts.stop = stop;
opts.action_script = actionscript_path; opts.action_script = actionscript_path;
ret = c->migrate(c, MIGRATE_RESTORE, &opts, sizeof(opts)); ret = c->migrate(c, MIGRATE_RESTORE, &opts, sizeof(opts));
if (ret) { if (ret) {
fprintf(stderr, "Restoring %s failed.\n", my_args.name); ERROR("Restoring %s failed", my_args.name);
return false; return false;
} }
...@@ -213,7 +218,7 @@ static bool restore_finalize(struct lxc_container *c) ...@@ -213,7 +218,7 @@ static bool restore_finalize(struct lxc_container *c)
static bool restore(struct lxc_container *c) static bool restore(struct lxc_container *c)
{ {
if (c->is_running(c)) { if (c->is_running(c)) {
fprintf(stderr, "%s is running, not restoring.\n", my_args.name); ERROR("%s is running, not restoring", my_args.name);
lxc_container_put(c); lxc_container_put(c);
return false; return false;
} }
...@@ -223,7 +228,7 @@ static bool restore(struct lxc_container *c) ...@@ -223,7 +228,7 @@ static bool restore(struct lxc_container *c)
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
perror("fork"); SYSERROR("Failed to fork");
return false; return false;
} }
...@@ -231,7 +236,7 @@ static bool restore(struct lxc_container *c) ...@@ -231,7 +236,7 @@ static bool restore(struct lxc_container *c)
close(0); close(0);
close(1); close(1);
exit(!restore_finalize(c)); _exit(!restore_finalize(c));
} else { } else {
return wait_for_pid(pid) == 0; return wait_for_pid(pid) == 0;
} }
...@@ -272,33 +277,35 @@ int main(int argc, char *argv[]) ...@@ -272,33 +277,35 @@ int main(int argc, char *argv[])
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
fprintf(stderr, "System error loading %s\n", my_args.name); ERROR("System error loading %s", my_args.name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
fprintf(stderr, "Failed to load rcfile\n"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
fprintf(stderr, "Out of memory setting new config filename\n"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); ERROR("Insufficent privileges to control %s", my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!c->is_defined(c)) { if (!c->is_defined(c)) {
fprintf(stderr, "%s is not defined\n", my_args.name); ERROR("%s is not defined", my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -308,6 +315,7 @@ int main(int argc, char *argv[]) ...@@ -308,6 +315,7 @@ int main(int argc, char *argv[])
ret = restore(c); ret = restore(c);
else else
ret = checkpoint(c); ret = checkpoint(c);
free(actionscript_path); free(actionscript_path);
free(checkpoint_dir); free(checkpoint_dir);
free(predump_dir); free(predump_dir);
......
...@@ -52,6 +52,7 @@ static void list_config_items(void) ...@@ -52,6 +52,7 @@ static void list_config_items(void)
for (i = &items[0]; i->name; i++) for (i = &items[0]; i->name; i++)
printf("%s\n", i->name); printf("%s\n", i->name);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
...@@ -60,21 +61,25 @@ int main(int argc, char *argv[]) ...@@ -60,21 +61,25 @@ int main(int argc, char *argv[])
struct lxc_config_items *i; struct lxc_config_items *i;
const char *value; const char *value;
if (argc < 2 || strcmp(argv[1], "-h") == 0 || if (argc < 2 || strncmp(argv[1], "-h", strlen(argv[1])) == 0 ||
strcmp(argv[1], "--help") == 0) strncmp(argv[1], "--help", strlen(argv[1])) == 0)
usage(argv[0]); usage(argv[0]);
if (strcmp(argv[1], "-l") == 0)
if (strncmp(argv[1], "-l", strlen(argv[1])) == 0)
list_config_items(); list_config_items();
for (i = &items[0]; i->name; i++) { for (i = &items[0]; i->name; i++) {
if (strcmp(argv[1], i->name) == 0) { if (strncmp(argv[1], i->name, strlen(argv[1])) == 0) {
value = lxc_get_global_config_item(i->name); value = lxc_get_global_config_item(i->name);
if (value) if (value)
printf("%s\n", value); printf("%s\n", value);
else else
printf("%s is not set.\n", argv[1]); printf("%s is not set.\n", argv[1]);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
} }
printf("Unknown configuration item: %s\n", argv[1]); printf("Unknown configuration item: %s\n", argv[1]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -39,16 +39,20 @@ ...@@ -39,16 +39,20 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
lxc_log_define(lxc_console, lxc);
static char etoc(const char *expr) static char etoc(const char *expr)
{ {
/* returns "control code" of given expression */ /* returns "control code" of given expression */
char c = expr[0] == '^' ? expr[1] : expr[0]; char c = expr[0] == '^' ? expr[1] : expr[0];
return 1 + ((c > 'Z') ? (c - 'a') : (c - 'Z')); return 1 + ((c > 'Z') ? (c - 'a') : (c - 'Z'));
} }
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) { switch (c) {
case 't': case 't':
...@@ -59,6 +63,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg) ...@@ -59,6 +63,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
args->escape = etoc(arg); args->escape = etoc(arg);
break; break;
} }
return 0; return 0;
} }
...@@ -95,7 +100,7 @@ int main(int argc, char *argv[]) ...@@ -95,7 +100,7 @@ int main(int argc, char *argv[])
ret = lxc_arguments_parse(&my_args, argc, argv); ret = lxc_arguments_parse(&my_args, argc, argv);
if (ret) if (ret)
return EXIT_FAILURE; exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */ /* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) { if (my_args.log_file || my_args.log_priority) {
...@@ -112,33 +117,35 @@ int main(int argc, char *argv[]) ...@@ -112,33 +117,35 @@ int main(int argc, char *argv[])
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
fprintf(stderr, "System error loading container\n"); ERROR("System error loading container");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
fprintf(stderr, "Failed to load rcfile\n"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
fprintf(stderr, "Out of memory setting new config filename\n"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); ERROR("Insufficent privileges to control %s", my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!c->is_running(c)) { if (!c->is_running(c)) {
fprintf(stderr, "%s is not running\n", my_args.name); ERROR("%s is not running", my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -148,6 +155,7 @@ int main(int argc, char *argv[]) ...@@ -148,6 +155,7 @@ int main(int argc, char *argv[])
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
...@@ -36,12 +36,15 @@ ...@@ -36,12 +36,15 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
#ifndef HAVE_GETSUBOPT #ifndef HAVE_GETSUBOPT
#include "include/getsubopt.h" #include "include/getsubopt.h"
#endif #endif
lxc_log_define(lxc_copy, lxc);
enum mnttype { enum mnttype {
LXC_MNT_BIND, LXC_MNT_BIND,
LXC_MNT_OVL, LXC_MNT_OVL,
...@@ -178,22 +181,22 @@ int main(int argc, char *argv[]) ...@@ -178,22 +181,22 @@ int main(int argc, char *argv[])
if (geteuid()) { if (geteuid()) {
if (access(my_args.lxcpath[0], O_RDONLY) < 0) { if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
if (!my_args.quiet) ERROR("You lack access to %s", my_args.lxcpath[0]);
fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
exit(ret); exit(ret);
} }
} }
if (!my_args.newname && !(my_args.task == DESTROY)) { if (!my_args.newname && !(my_args.task == DESTROY)) {
if (!my_args.quiet) ERROR("You must provide a NEWNAME for the clone");
printf("Error: You must provide a NEWNAME for the clone.\n");
exit(ret); exit(ret);
} }
if (my_args.task == SNAP || my_args.task == DESTROY) if (my_args.task == SNAP || my_args.task == DESTROY)
flags |= LXC_CLONE_SNAPSHOT; flags |= LXC_CLONE_SNAPSHOT;
if (my_args.keepname) if (my_args.keepname)
flags |= LXC_CLONE_KEEPNAME; flags |= LXC_CLONE_KEEPNAME;
if (my_args.keepmac) if (my_args.keepmac)
flags |= LXC_CLONE_KEEPMACADDR; flags |= LXC_CLONE_KEEPMACADDR;
...@@ -206,26 +209,26 @@ int main(int argc, char *argv[]) ...@@ -206,26 +209,26 @@ int main(int argc, char *argv[])
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
fprintf(stderr, "Failed to load rcfile\n"); ERROR("Failed to load rcfile");
goto out; goto out;
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
fprintf(stderr, "Out of memory setting new config filename\n"); ERROR("Out of memory setting new config filename");
goto out; goto out;
} }
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
if (!my_args.quiet) ERROR("Insufficent privileges to control %s", c->name);
fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
goto out; goto out;
} }
if (!c->is_defined(c)) { if (!c->is_defined(c)) {
if (!my_args.quiet) ERROR("Container %s is not defined", c->name);
fprintf(stderr, "Error: container %s is not defined\n", c->name);
goto out; goto out;
} }
...@@ -258,32 +261,36 @@ static struct mnts *add_mnt(struct mnts **mnts, unsigned int *num, enum mnttype ...@@ -258,32 +261,36 @@ 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) static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_arguments *arg)
{ {
char upperdir[TOOL_MAXPATHLEN]; char upperdir[MAXPATHLEN];
char workdir[TOOL_MAXPATHLEN]; char workdir[MAXPATHLEN];
unsigned int i; unsigned int i;
int ret; int ret;
struct mnts *m = NULL; struct mnts *m = NULL;
for (i = 0, m = mnts; i < num; i++, m++) { for (i = 0, m = mnts; i < num; i++, m++) {
if (m->mnt_type == LXC_MNT_OVL) { if (m->mnt_type == LXC_MNT_OVL) {
ret = snprintf(upperdir, TOOL_MAXPATHLEN, "%s/%s/delta#XXXXXX", ret = snprintf(upperdir, MAXPATHLEN, "%s/%s/delta#XXXXXX",
arg->newpath, arg->newname); arg->newpath, arg->newname);
if (ret < 0 || ret >= TOOL_MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return -1; return -1;
if (!mkdtemp(upperdir)) if (!mkdtemp(upperdir))
return -1; return -1;
m->upper = strdup(upperdir); m->upper = strdup(upperdir);
if (!m->upper) if (!m->upper)
return -1; return -1;
} }
if (m->mnt_type == LXC_MNT_OVL) { if (m->mnt_type == LXC_MNT_OVL) {
ret = snprintf(workdir, TOOL_MAXPATHLEN, "%s/%s/work#XXXXXX", ret = snprintf(workdir, MAXPATHLEN, "%s/%s/work#XXXXXX",
arg->newpath, arg->newname); arg->newpath, arg->newname);
if (ret < 0 || ret >= TOOL_MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return -1; return -1;
if (!mkdtemp(workdir)) if (!mkdtemp(workdir))
return -1; return -1;
m->workdir = strdup(workdir); m->workdir = strdup(workdir);
if (!m->workdir) if (!m->workdir)
return -1; return -1;
...@@ -359,8 +366,7 @@ static int do_clone(struct lxc_container *c, char *newname, char *newpath, ...@@ -359,8 +366,7 @@ static int do_clone(struct lxc_container *c, char *newname, char *newpath,
clone = c->clone(c, newname, newpath, flags, bdevtype, NULL, fssize, clone = c->clone(c, newname, newpath, flags, bdevtype, NULL, fssize,
args); args);
if (!clone) { if (!clone) {
if (!my_args.quiet) ERROR("Failed to clone");
fprintf(stderr, "clone failed\n");
return -1; return -1;
} }
...@@ -373,7 +379,7 @@ static int do_clone_ephemeral(struct lxc_container *c, ...@@ -373,7 +379,7 @@ static int do_clone_ephemeral(struct lxc_container *c,
struct lxc_arguments *arg, char **args, int flags) struct lxc_arguments *arg, char **args, int flags)
{ {
char *premount; char *premount;
char randname[TOOL_MAXPATHLEN]; char randname[MAXPATHLEN];
unsigned int i; unsigned int i;
int ret = 0; int ret = 0;
bool bret = true, started = false; bool bret = true, started = false;
...@@ -383,15 +389,18 @@ static int do_clone_ephemeral(struct lxc_container *c, ...@@ -383,15 +389,18 @@ static int do_clone_ephemeral(struct lxc_container *c,
attach_options.env_policy = LXC_ATTACH_CLEAR_ENV; attach_options.env_policy = LXC_ATTACH_CLEAR_ENV;
if (!arg->newname) { if (!arg->newname) {
ret = snprintf(randname, TOOL_MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name); ret = snprintf(randname, MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name);
if (ret < 0 || ret >= TOOL_MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return -1; return -1;
if (!mkdtemp(randname)) if (!mkdtemp(randname))
return -1; return -1;
if (chmod(randname, 0770) < 0) { if (chmod(randname, 0770) < 0) {
(void)remove(randname); (void)remove(randname);
return -1; return -1;
} }
arg->newname = randname + strlen(arg->newpath) + 1; arg->newname = randname + strlen(arg->newpath) + 1;
} }
...@@ -423,9 +432,11 @@ static int do_clone_ephemeral(struct lxc_container *c, ...@@ -423,9 +432,11 @@ static int do_clone_ephemeral(struct lxc_container *c,
struct mnts *n = NULL; struct mnts *n = NULL;
for (i = 0, n = mnt_table; i < mnt_table_size; i++, n++) { for (i = 0, n = mnt_table; i < mnt_table_size; i++, n++) {
char *mntentry = NULL; char *mntentry = NULL;
mntentry = set_mnt_entry(n); mntentry = set_mnt_entry(n);
if (!mntentry) if (!mntentry)
goto destroy_and_put; goto destroy_and_put;
bret = clone->set_config_item(clone, "lxc.mount.entry", mntentry); bret = clone->set_config_item(clone, "lxc.mount.entry", mntentry);
free(mntentry); free(mntentry);
if (!bret) if (!bret)
...@@ -467,9 +478,11 @@ static int do_clone_ephemeral(struct lxc_container *c, ...@@ -467,9 +478,11 @@ static int do_clone_ephemeral(struct lxc_container *c,
destroy_and_put: destroy_and_put:
if (started) if (started)
clone->shutdown(clone, -1); clone->shutdown(clone, -1);
ret = clone->get_config_item(clone, "lxc.ephemeral", tmp_buf, TOOL_MAXPATHLEN);
ret = clone->get_config_item(clone, "lxc.ephemeral", tmp_buf, MAXPATHLEN);
if (ret > 0 && strcmp(tmp_buf, "0")) if (ret > 0 && strcmp(tmp_buf, "0"))
clone->destroy(clone); clone->destroy(clone);
free_mnts(); free_mnts();
lxc_container_put(clone); lxc_container_put(clone);
return -1; return -1;
...@@ -478,7 +491,7 @@ destroy_and_put: ...@@ -478,7 +491,7 @@ destroy_and_put:
static int do_clone_rename(struct lxc_container *c, char *newname) static int do_clone_rename(struct lxc_container *c, char *newname)
{ {
if (!c->rename(c, newname)) { if (!c->rename(c, newname)) {
fprintf(stderr, "Error: Renaming container %s to %s failed\n", c->name, newname); ERROR("Renaming container %s to %s failed", c->name, newname);
return -1; return -1;
} }
...@@ -519,6 +532,7 @@ static void free_mnts() ...@@ -519,6 +532,7 @@ static void free_mnts()
free(n->upper); free(n->upper);
free(n->workdir); free(n->workdir);
} }
free(mnt_table); free(mnt_table);
mnt_table = NULL; mnt_table = NULL;
mnt_table_size = 0; mnt_table_size = 0;
...@@ -532,8 +546,7 @@ static uint64_t get_fssize(char *s) ...@@ -532,8 +546,7 @@ static uint64_t get_fssize(char *s)
ret = strtoull(s, &end, 0); ret = strtoull(s, &end, 0);
if (end == s) { if (end == s) {
if (!my_args.quiet) ERROR("Invalid blockdev size '%s', using default size", s);
fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s);
return 0; return 0;
} }
while (isblank(*end)) while (isblank(*end))
...@@ -551,8 +564,7 @@ static uint64_t get_fssize(char *s) ...@@ -551,8 +564,7 @@ static uint64_t get_fssize(char *s)
} else if (*end == 't' || *end == 'T') { } else if (*end == 't' || *end == 'T') {
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
} else { } else {
if (!my_args.quiet) ERROR("Invalid blockdev unit size '%c' in '%s', " "using default size", *end, s);
fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', " "using default size\n", *end, s);
return 0; return 0;
} }
...@@ -591,7 +603,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) ...@@ -591,7 +603,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
return -1; return -1;
break; break;
case 'B': case 'B':
if (strcmp(arg, "overlay") == 0) if (strncmp(arg, "overlay", strlen(arg)) == 0)
arg = "overlayfs"; arg = "overlayfs";
args->bdevtype = arg; args->bdevtype = arg;
break; break;
...@@ -660,8 +672,8 @@ static int parse_bind_mnt(char *mntstring, enum mnttype type) ...@@ -660,8 +672,8 @@ static int parse_bind_mnt(char *mntstring, enum mnttype type)
if (!m->options) if (!m->options)
m->options = strdup("rw"); m->options = strdup("rw");
if (!m->options || (strncmp(m->options, "rw", strlen(m->options)) && if (!m->options || (strncmp(m->options, "rw", strlen(m->options)) != 0 &&
strncmp(m->options, "ro", strlen(m->options)))) strncmp(m->options, "ro", strlen(m->options)) != 0))
goto err; goto err;
lxc_free_array((void **)mntarray, free); lxc_free_array((void **)mntarray, free);
...@@ -689,6 +701,7 @@ static int parse_mntsubopts(char *subopts, char *const *keys, char *mntparameter ...@@ -689,6 +701,7 @@ static int parse_mntsubopts(char *subopts, char *const *keys, char *mntparameter
break; break;
} }
} }
return 0; return 0;
} }
...@@ -749,19 +762,19 @@ static char *mount_tmpfs(const char *oldname, const char *newname, ...@@ -749,19 +762,19 @@ static char *mount_tmpfs(const char *oldname, const char *newname,
FILE *fp = NULL; FILE *fp = NULL;
if (arg->tmpfs && arg->keepdata) { if (arg->tmpfs && arg->keepdata) {
fprintf(stderr, "%s\n", ERROR("%s",
"A container can only be placed on a tmpfs when the " "A container can only be placed on a tmpfs when the "
"overlay storage driver is used"); "overlay storage driver is used");
goto err_free; goto err_free;
} }
if (arg->tmpfs && !arg->bdevtype) { if (arg->tmpfs && !arg->bdevtype) {
arg->bdevtype = "overlayfs"; arg->bdevtype = "overlayfs";
} else if (arg->tmpfs && arg->bdevtype && } else if (arg->tmpfs && arg->bdevtype &&
strcmp(arg->bdevtype, "overlayfs") != 0) { strncmp(arg->bdevtype, "overlayfs", strlen(arg->bdevtype)) != 0) {
fprintf(stderr, "%s\n", ERROR("%s",
"A container can only be placed on a tmpfs when the " "A container can only be placed on a tmpfs when the "
"overlay storage driver is used"); "overlay storage driver is used");
goto err_free; goto err_free;
} }
...@@ -781,7 +794,7 @@ static char *mount_tmpfs(const char *oldname, const char *newname, ...@@ -781,7 +794,7 @@ static char *mount_tmpfs(const char *oldname, const char *newname,
goto err_free; goto err_free;
if (fcntl(fd, F_SETFD, FD_CLOEXEC)) { if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
fprintf(stderr, "Failed to set close-on-exec on file descriptor.\n"); ERROR("Failed to set close-on-exec on file descriptor");
goto err_close; goto err_close;
} }
...@@ -815,6 +828,7 @@ err_close: ...@@ -815,6 +828,7 @@ err_close:
close(fd); close(fd);
else if (fp) else if (fp)
fclose(fp); fclose(fp);
err_free: err_free:
free(premount); free(premount);
return NULL; return NULL;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#define _GNU_SOURCE
#include <ctype.h> #include <ctype.h>
#include <fcntl.h> #include <fcntl.h>
#include <libgen.h> #include <libgen.h>
...@@ -29,7 +30,10 @@ ...@@ -29,7 +30,10 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
lxc_log_define(lxc_create, lxc);
static uint64_t get_fssize(char *s) static uint64_t get_fssize(char *s)
{ {
...@@ -39,11 +43,13 @@ static uint64_t get_fssize(char *s) ...@@ -39,11 +43,13 @@ static uint64_t get_fssize(char *s)
ret = strtoull(s, &end, 0); ret = strtoull(s, &end, 0);
if (end == s) if (end == s)
{ {
fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s); ERROR("Invalid blockdev size '%s', using default size", s);
return 0; return 0;
} }
while (isblank(*end)) while (isblank(*end))
end++; end++;
if (*end == '\0') if (*end == '\0')
ret *= 1024ULL * 1024ULL; /* MB by default */ ret *= 1024ULL * 1024ULL; /* MB by default */
else if (*end == 'b' || *end == 'B') else if (*end == 'b' || *end == 'B')
...@@ -58,13 +64,14 @@ static uint64_t get_fssize(char *s) ...@@ -58,13 +64,14 @@ static uint64_t get_fssize(char *s)
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
else else
{ {
fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s); ERROR("Invalid blockdev unit size '%c' in '%s', using default size", *end, s);
return 0; return 0;
} }
return ret; return ret;
} }
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) { switch (c) {
case 'B': args->bdevtype = arg; break; case 'B': args->bdevtype = arg; break;
...@@ -120,8 +127,8 @@ static void create_helpfn(const struct lxc_arguments *args) ...@@ -120,8 +127,8 @@ static void create_helpfn(const struct lxc_arguments *args)
argv[2] = NULL; argv[2] = NULL;
execv(path, argv); execv(path, argv);
fprintf(stderr, "Error executing %s -h\n", path); ERROR("Error executing %s -h", path);
exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
static struct lxc_arguments my_args = { static struct lxc_arguments my_args = {
...@@ -170,34 +177,38 @@ Options :\n\ ...@@ -170,34 +177,38 @@ Options :\n\
static bool validate_bdev_args(struct lxc_arguments *a) static bool validate_bdev_args(struct lxc_arguments *a)
{ {
if (strcmp(a->bdevtype, "best") != 0) { if (strncmp(a->bdevtype, "best", strlen(a->bdevtype)) != 0) {
if (a->fstype || a->fssize) { if (a->fstype || a->fssize) {
if (strcmp(a->bdevtype, "lvm") != 0 && if (strncmp(a->bdevtype, "lvm", strlen(a->bdevtype)) != 0 &&
strcmp(a->bdevtype, "loop") != 0 && strncmp(a->bdevtype, "loop", strlen(a->bdevtype)) != 0 &&
strcmp(a->bdevtype, "rbd") != 0) { strncmp(a->bdevtype, "rbd", strlen(a->bdevtype)) != 0) {
fprintf(stderr, "filesystem type and size are only valid with block devices\n"); ERROR("Filesystem type and size are only valid with block devices");
return false; return false;
} }
} }
if (strcmp(a->bdevtype, "lvm") != 0) {
if (strncmp(a->bdevtype, "lvm", strlen(a->bdevtype)) != 0) {
if (a->lvname || a->vgname || a->thinpool) { if (a->lvname || a->vgname || a->thinpool) {
fprintf(stderr, "--lvname, --vgname and --thinpool are only valid with -B lvm\n"); ERROR("--lvname, --vgname and --thinpool are only valid with -B lvm");
return false; return false;
} }
} }
if (strcmp(a->bdevtype, "rbd") != 0) {
if (strncmp(a->bdevtype, "rbd", strlen(a->bdevtype)) != 0) {
if (a->rbdname || a->rbdpool) { if (a->rbdname || a->rbdpool) {
fprintf(stderr, "--rbdname and --rbdpool are only valid with -B rbd\n"); ERROR("--rbdname and --rbdpool are only valid with -B rbd");
return false; return false;
} }
} }
if (strcmp(a->bdevtype, "zfs") != 0) {
if (strncmp(a->bdevtype, "zfs", strlen(a->bdevtype)) != 0) {
if (a->zfsroot) { if (a->zfsroot) {
fprintf(stderr, "zfsroot is only valid with -B zfs\n"); ERROR("zfsroot is only valid with -B zfs");
return false; return false;
} }
} }
} }
return true; return true;
} }
...@@ -244,33 +255,31 @@ int main(int argc, char *argv[]) ...@@ -244,33 +255,31 @@ int main(int argc, char *argv[])
} }
if (!my_args.template) { if (!my_args.template) {
fprintf(stderr, "A template must be specified.\n"); ERROR("A template must be specified");
fprintf(stderr, "Use \"none\" if you really want a container without a rootfs.\n"); ERROR("Use \"none\" if you really want a container without a rootfs");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (strcmp(my_args.template, "none") == 0) if (strncmp(my_args.template, "none", strlen(my_args.template)) == 0)
my_args.template = NULL; my_args.template = NULL;
memset(&spec, 0, sizeof(spec));
if (!my_args.bdevtype) if (!my_args.bdevtype)
my_args.bdevtype = "_unset"; my_args.bdevtype = "_unset";
if (!validate_bdev_args(&my_args)) if (!validate_bdev_args(&my_args))
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
if (strcmp(my_args.bdevtype, "none") == 0) if (strncmp(my_args.bdevtype, "none", strlen(my_args.bdevtype)) == 0)
my_args.bdevtype = "dir"; my_args.bdevtype = "dir";
/* Final check whether the user gave use a valid bdev type. */ /* Final check whether the user gave use a valid bdev type. */
if (strcmp(my_args.bdevtype, "best") && if (strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) != 0 &&
strcmp(my_args.bdevtype, "_unset") && strncmp(my_args.bdevtype, "_unset", strlen(my_args.bdevtype)) != 0 &&
!is_valid_storage_type(my_args.bdevtype)) { !is_valid_storage_type(my_args.bdevtype)) {
fprintf(stderr, "%s is not a valid backing storage type.\n", my_args.bdevtype); ERROR("%s is not a valid backing storage type", my_args.bdevtype);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!my_args.lxcpath[0]) if (!my_args.lxcpath[0])
my_args.lxcpath[0] = lxc_get_global_config_item("lxc.lxcpath"); my_args.lxcpath[0] = lxc_get_global_config_item("lxc.lxcpath");
...@@ -279,48 +288,58 @@ int main(int argc, char *argv[]) ...@@ -279,48 +288,58 @@ int main(int argc, char *argv[])
if (geteuid()) if (geteuid())
if (access(my_args.lxcpath[0], O_RDONLY) < 0) { if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
fprintf(stderr, "You lack access to %s\n", ERROR("You lack access to %s", my_args.lxcpath[0]);
my_args.lxcpath[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
fprintf(stderr, "Failed to create lxc container.\n"); ERROR("Failed to create lxc container");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (c->is_defined(c)) { if (c->is_defined(c)) {
lxc_container_put(c); lxc_container_put(c);
fprintf(stderr, "Container already exists\n"); ERROR("Container already exists");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (my_args.configfile) if (my_args.configfile)
c->load_config(c, my_args.configfile); c->load_config(c, my_args.configfile);
else else
c->load_config(c, lxc_get_global_config_item("lxc.default_config")); c->load_config(c, lxc_get_global_config_item("lxc.default_config"));
memset(&spec, 0, sizeof(spec));
if (my_args.fstype) if (my_args.fstype)
spec.fstype = my_args.fstype; spec.fstype = my_args.fstype;
if (my_args.fssize) if (my_args.fssize)
spec.fssize = my_args.fssize; spec.fssize = my_args.fssize;
if ((strcmp(my_args.bdevtype, "zfs") == 0) || (strcmp(my_args.bdevtype, "best") == 0)) { if ((strncmp(my_args.bdevtype, "zfs", strlen(my_args.bdevtype)) == 0) ||
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
if (my_args.zfsroot) if (my_args.zfsroot)
spec.zfs.zfsroot = my_args.zfsroot; spec.zfs.zfsroot = my_args.zfsroot;
} }
if ((strcmp(my_args.bdevtype, "lvm") == 0) || (strcmp(my_args.bdevtype, "best") == 0)) { if ((strncmp(my_args.bdevtype, "lvm", strlen(my_args.bdevtype)) == 0) ||
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
if (my_args.lvname) if (my_args.lvname)
spec.lvm.lv = my_args.lvname; spec.lvm.lv = my_args.lvname;
if (my_args.vgname) if (my_args.vgname)
spec.lvm.vg = my_args.vgname; spec.lvm.vg = my_args.vgname;
if (my_args.thinpool) if (my_args.thinpool)
spec.lvm.thinpool = my_args.thinpool; spec.lvm.thinpool = my_args.thinpool;
} }
if ((strcmp(my_args.bdevtype, "rbd") == 0) || (strcmp(my_args.bdevtype, "best") == 0)) { if ((strncmp(my_args.bdevtype, "rbd", strlen(my_args.bdevtype)) == 0) ||
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
if (my_args.rbdname) if (my_args.rbdname)
spec.rbd.rbdname = my_args.rbdname; spec.rbd.rbdname = my_args.rbdname;
if (my_args.rbdpool) if (my_args.rbdpool)
spec.rbd.rbdpool = my_args.rbdpool; spec.rbd.rbdpool = my_args.rbdpool;
} }
...@@ -328,7 +347,7 @@ int main(int argc, char *argv[]) ...@@ -328,7 +347,7 @@ int main(int argc, char *argv[])
if (my_args.dir) if (my_args.dir)
spec.dir = my_args.dir; spec.dir = my_args.dir;
if (strcmp(my_args.bdevtype, "_unset") == 0) if (strncmp(my_args.bdevtype, "_unset", strlen(my_args.bdevtype)) == 0)
my_args.bdevtype = NULL; my_args.bdevtype = NULL;
if (my_args.quiet) if (my_args.quiet)
......
...@@ -29,10 +29,12 @@ ...@@ -29,10 +29,12 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
static int my_parser(struct lxc_arguments* args, int c, char* arg); lxc_log_define(lxc_destroy, lxc);
static bool quiet;
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static const struct option my_longopts[] = { static const struct option my_longopts[] = {
{"force", no_argument, 0, 'f'}, {"force", no_argument, 0, 'f'},
...@@ -83,59 +85,56 @@ int main(int argc, char *argv[]) ...@@ -83,59 +85,56 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (my_args.quiet)
quiet = true;
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
if (!quiet) ERROR("System error loading container");
fprintf(stderr, "System error loading container\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
fprintf(stderr, "Failed to load rcfile\n"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
fprintf(stderr, "Out of memory setting new config filename\n"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
if (!quiet) ERROR("Insufficent privileges to control %s", my_args.name);
fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!c->is_defined(c)) { if (!c->is_defined(c)) {
if (!quiet) ERROR("Container is not defined");
fprintf(stderr, "Container is not defined\n");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (my_args.task == SNAP) { if (my_args.task == SNAP) {
bret = do_destroy_with_snapshots(c); bret = do_destroy_with_snapshots(c);
if (bret && !quiet) if (bret)
printf("Destroyed container %s including snapshots \n", my_args.name); ERROR("Destroyed container %s including snapshots", my_args.name);
} else { } else {
bret = do_destroy(c); bret = do_destroy(c);
if (bret && !quiet) if (bret)
printf("Destroyed container %s\n", my_args.name); ERROR("Destroyed container %s", my_args.name);
} }
lxc_container_put(c); lxc_container_put(c);
if (bret) if (bret)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -151,34 +150,33 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) ...@@ -151,34 +150,33 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
static bool do_destroy(struct lxc_container *c) static bool do_destroy(struct lxc_container *c)
{ {
bool bret = true; bool bret = true;
char path[TOOL_MAXPATHLEN]; char path[MAXPATHLEN];
/* First check whether the container has dependent clones or snapshots. */ /* First check whether the container has dependent clones or snapshots. */
int ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name); int ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
if (ret < 0 || ret >= TOOL_MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return false; return false;
if (file_exists(path)) { if (file_exists(path)) {
if (!quiet) ERROR("Destroying %s failed: %s has clones", c->name, c->name);
fprintf(stdout, "Destroying %s failed: %s has clones.\n", c->name, c->name);
return false; return false;
} }
ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name); ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
if (ret < 0 || ret >= TOOL_MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return false; return false;
if (rmdir(path) < 0 && errno != ENOENT) { if (rmdir(path) < 0 && errno != ENOENT) {
if (!quiet) ERROR("Destroying %s failed: %s has snapshots", c->name, c->name);
fprintf(stdout, "Destroying %s failed: %s has snapshots.\n", c->name, c->name);
return false; return false;
} }
if (c->is_running(c)) { if (c->is_running(c)) {
if (!my_args.force && !quiet) { if (!my_args.force) {
fprintf(stderr, "%s is running\n", my_args.name); ERROR("%s is running", my_args.name);
return false; return false;
} }
/* If the container was ephemeral it will be removed on shutdown. */ /* If the container was ephemeral it will be removed on shutdown. */
c->stop(c); c->stop(c);
} }
...@@ -187,6 +185,7 @@ static bool do_destroy(struct lxc_container *c) ...@@ -187,6 +185,7 @@ static bool do_destroy(struct lxc_container *c)
* stopped it. */ * stopped it. */
if (c->is_defined(c)) { if (c->is_defined(c)) {
char buf[256]; char buf[256];
ret = c->get_config_item(c, "lxc.ephemeral", buf, 256); ret = c->get_config_item(c, "lxc.ephemeral", buf, 256);
if (ret > 0 && strcmp(buf, "0") == 0) { if (ret > 0 && strcmp(buf, "0") == 0) {
bret = c->destroy(c); bret = c->destroy(c);
...@@ -194,8 +193,7 @@ static bool do_destroy(struct lxc_container *c) ...@@ -194,8 +193,7 @@ static bool do_destroy(struct lxc_container *c)
} }
if (!bret) { if (!bret) {
if (!quiet) ERROR("Destroying %s failed", my_args.name);
fprintf(stderr, "Destroying %s failed\n", my_args.name);
return false; return false;
} }
...@@ -207,7 +205,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c) ...@@ -207,7 +205,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
struct lxc_container *c1; struct lxc_container *c1;
struct stat fbuf; struct stat fbuf;
bool bret = false; bool bret = false;
char path[TOOL_MAXPATHLEN]; char path[MAXPATHLEN];
char *buf = NULL; char *buf = NULL;
char *lxcpath = NULL; char *lxcpath = NULL;
char *lxcname = NULL; char *lxcname = NULL;
...@@ -217,8 +215,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c) ...@@ -217,8 +215,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
int counter = 0; int counter = 0;
/* Destroy clones. */ /* Destroy clones. */
ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name); ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
if (ret < 0 || ret >= TOOL_MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return false; return false;
fd = open(path, O_RDONLY | O_CLOEXEC); fd = open(path, O_RDONLY | O_CLOEXEC);
...@@ -232,14 +230,14 @@ static bool do_destroy_with_snapshots(struct lxc_container *c) ...@@ -232,14 +230,14 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
/* Make sure that the string is \0 terminated. */ /* Make sure that the string is \0 terminated. */
buf = calloc(fbuf.st_size + 1, sizeof(char)); buf = calloc(fbuf.st_size + 1, sizeof(char));
if (!buf) { if (!buf) {
fprintf(stderr, "failed to allocate memory\n"); ERROR("Failed to allocate memory");
close(fd); close(fd);
return false; return false;
} }
ret = read(fd, buf, fbuf.st_size); ret = read(fd, buf, fbuf.st_size);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "could not read %s\n", path); ERROR("Could not read %s", path);
close(fd); close(fd);
free(buf); free(buf);
return false; return false;
...@@ -249,11 +247,13 @@ static bool do_destroy_with_snapshots(struct lxc_container *c) ...@@ -249,11 +247,13 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
while ((lxcpath = strtok_r(!counter ? buf : NULL, "\n", &scratch))) { while ((lxcpath = strtok_r(!counter ? buf : NULL, "\n", &scratch))) {
if (!(lxcname = strtok_r(NULL, "\n", &scratch))) if (!(lxcname = strtok_r(NULL, "\n", &scratch)))
break; break;
c1 = lxc_container_new(lxcname, lxcpath); c1 = lxc_container_new(lxcname, lxcpath);
if (!c1) { if (!c1) {
counter++; counter++;
continue; continue;
} }
/* We do not destroy recursively. If a clone of a clone /* We do not destroy recursively. If a clone of a clone
* has clones or snapshots the user should remove it * has clones or snapshots the user should remove it
* explicitly. */ * explicitly. */
...@@ -262,6 +262,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c) ...@@ -262,6 +262,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
free(buf); free(buf);
return false; return false;
} }
lxc_container_put(c1); lxc_container_put(c1);
counter++; counter++;
} }
...@@ -269,8 +270,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c) ...@@ -269,8 +270,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
} }
/* Destroy snapshots located in the containers snap/ folder. */ /* Destroy snapshots located in the containers snap/ folder. */
ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name); ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
if (ret < 0 || ret >= TOOL_MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return false; return false;
if (rmdir(path) < 0 && errno != ENOENT) if (rmdir(path) < 0 && errno != ENOENT)
......
...@@ -30,7 +30,10 @@ ...@@ -30,7 +30,10 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
lxc_log_define(lxc_device, lxc);
#if HAVE_IFADDRS_H #if HAVE_IFADDRS_H
#include <ifaddrs.h> #include <ifaddrs.h>
...@@ -57,12 +60,11 @@ Options :\n\ ...@@ -57,12 +60,11 @@ Options :\n\
.checker = NULL, .checker = NULL,
}; };
static bool is_interface(const char* dev_name, pid_t pid) static bool is_interface(const char *dev_name, pid_t pid)
{ {
pid_t p = fork(); pid_t p = fork();
if (p < 0) { if (p < 0) {
fprintf(stderr, "failed to fork task.\n"); ERROR("Failed to fork task");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -70,28 +72,28 @@ static bool is_interface(const char* dev_name, pid_t pid) ...@@ -70,28 +72,28 @@ static bool is_interface(const char* dev_name, pid_t pid)
struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL; struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
if (!switch_to_ns(pid, "net")) { if (!switch_to_ns(pid, "net")) {
fprintf(stderr, "failed to enter netns of container.\n"); ERROR("Failed to enter netns of container");
exit(-1); _exit(-1);
} }
/* Grab the list of interfaces */ /* Grab the list of interfaces */
if (getifaddrs(&interfaceArray)) { if (getifaddrs(&interfaceArray)) {
fprintf(stderr, "failed to get interfaces list\n"); ERROR("Failed to get interfaces list");
exit(-1); _exit(-1);
} }
/* Iterate through the interfaces */ /* Iterate through the interfaces */
for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) { for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) {
if (strcmp(tempIfAddr->ifa_name, dev_name) == 0) { if (strncmp(tempIfAddr->ifa_name, dev_name, strlen(tempIfAddr->ifa_name)) == 0)
exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
}
} }
exit(EXIT_FAILURE);
_exit(EXIT_FAILURE);
} }
if (wait_for_pid(p) == 0) { if (wait_for_pid(p) == 0)
return true; return true;
}
return false; return false;
} }
...@@ -103,7 +105,7 @@ int main(int argc, char *argv[]) ...@@ -103,7 +105,7 @@ int main(int argc, char *argv[])
bool ret = false; bool ret = false;
if (geteuid() != 0) { if (geteuid() != 0) {
fprintf(stderr, "%s must be run as root\n", argv[0]); ERROR("%s must be run as root", argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -125,30 +127,32 @@ int main(int argc, char *argv[]) ...@@ -125,30 +127,32 @@ int main(int argc, char *argv[])
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
fprintf(stderr, "%s doesn't exist\n", my_args.name); ERROR("%s doesn't exist", my_args.name);
goto err; goto err;
} }
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
fprintf(stderr, "Failed to load rcfile\n"); ERROR("Failed to load rcfile");
goto err1; goto err1;
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
fprintf(stderr, "Out of memory setting new config filename\n"); ERROR("Out of memory setting new config filename");
goto err1; goto err1;
} }
} }
if (!c->is_running(c)) { if (!c->is_running(c)) {
fprintf(stderr, "Container %s is not running.\n", c->name); ERROR("Container %s is not running", c->name);
goto err1; goto err1;
} }
if (my_args.argc < 2) { if (my_args.argc < 2) {
fprintf(stderr, "Error: no command given (Please see --help output)\n"); ERROR("Error: no command given (Please see --help output)");
goto err1; goto err1;
} }
...@@ -159,33 +163,38 @@ int main(int argc, char *argv[]) ...@@ -159,33 +163,38 @@ int main(int argc, char *argv[])
else else
dst_name = my_args.argv[2]; dst_name = my_args.argv[2];
if (strcmp(cmd, "add") == 0) { if (strncmp(cmd, "add", strlen(cmd)) == 0) {
if (is_interface(dev_name, 1)) { if (is_interface(dev_name, 1)) {
ret = c->attach_interface(c, dev_name, dst_name); ret = c->attach_interface(c, dev_name, dst_name);
} else { } else {
ret = c->add_device_node(c, dev_name, dst_name); ret = c->add_device_node(c, dev_name, dst_name);
} }
if (ret != true) { if (ret != true) {
fprintf(stderr, "Failed to add %s to %s.\n", dev_name, c->name); ERROR("Failed to add %s to %s", dev_name, c->name);
goto err1; goto err1;
} }
} else if (strcmp(cmd, "del") == 0) { } else if (strncmp(cmd, "del", strlen(cmd)) == 0) {
if (is_interface(dev_name, c->init_pid(c))) { if (is_interface(dev_name, c->init_pid(c))) {
ret = c->detach_interface(c, dev_name, dst_name); ret = c->detach_interface(c, dev_name, dst_name);
} else { } else {
ret = c->remove_device_node(c, dev_name, dst_name); ret = c->remove_device_node(c, dev_name, dst_name);
} }
if (ret != true) { if (ret != true) {
fprintf(stderr, "Failed to del %s from %s.\n", dev_name, c->name); ERROR("Failed to del %s from %s", dev_name, c->name);
goto err1; goto err1;
} }
} else { } else {
fprintf(stderr, "Error: Please use add or del (Please see --help output)\n"); ERROR("Error: Please use add or del (Please see --help output)");
goto err1; goto err1;
} }
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
err1: err1:
lxc_container_put(c); lxc_container_put(c);
err: err:
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -36,12 +36,16 @@ ...@@ -36,12 +36,16 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_list.h" #include "caps.h"
#include "tool_utils.h" #include "confile.h"
#include "log.h"
#include "utils.h"
lxc_log_define(lxc_execute, lxc);
static struct lxc_list defines; static struct lxc_list defines;
static int my_parser(struct lxc_arguments* args, int c, char* arg) static int my_parser(struct lxc_arguments *args, int c, char *arg)
{ {
int ret; int ret;
...@@ -78,6 +82,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg) ...@@ -78,6 +82,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
args->share_ns[LXC_NS_PID] = arg; args->share_ns[LXC_NS_PID] = arg;
break; break;
} }
return 0; return 0;
} }
...@@ -117,10 +122,10 @@ Options :\n\ ...@@ -117,10 +122,10 @@ Options :\n\
static bool set_argv(struct lxc_container *c, struct lxc_arguments *args) static bool set_argv(struct lxc_container *c, struct lxc_arguments *args)
{ {
int ret; int ret;
char buf[TOOL_MAXPATHLEN]; char buf[MAXPATHLEN];
char **components, **p; char **components, **p;
ret = c->get_config_item(c, "lxc.execute.cmd", buf, TOOL_MAXPATHLEN); ret = c->get_config_item(c, "lxc.execute.cmd", buf, MAXPATHLEN);
if (ret < 0) if (ret < 0)
return false; return false;
...@@ -166,31 +171,33 @@ int main(int argc, char *argv[]) ...@@ -166,31 +171,33 @@ int main(int argc, char *argv[])
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
fprintf(stderr, "Failed to create lxc_container\n"); ERROR("Failed to create lxc_container");
exit(err); exit(err);
} }
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
fprintf(stderr, "Failed to load rcfile\n"); ERROR("Failed to load rcfile");
goto out; goto out;
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
fprintf(stderr, "Out of memory setting new config filename\n"); ERROR("Out of memory setting new config filename");
goto out; goto out;
} }
} }
if (!c->lxc_conf) { if (!c->lxc_conf) {
fprintf(stderr, "Executing a container with no configuration file may crash the host\n"); ERROR("Executing a container with no configuration file may crash the host");
goto out; goto out;
} }
if (my_args.argc == 0) { if (my_args.argc == 0) {
if (!set_argv(c, &my_args)) { if (!set_argv(c, &my_args)) {
fprintf(stderr, "missing command to execute!\n"); ERROR("Missing command to execute!");
goto out; goto out;
} }
} }
...@@ -227,11 +234,13 @@ int main(int argc, char *argv[]) ...@@ -227,11 +234,13 @@ int main(int argc, char *argv[])
goto out; goto out;
c->daemonize = my_args.daemonize == 1; c->daemonize = my_args.daemonize == 1;
bret = c->start(c, 1, my_args.argv); bret = c->start(c, 1, my_args.argv);
if (!bret) { if (!bret) {
fprintf(stderr, "Failed run an application inside container\n"); ERROR("Failed run an application inside container");
goto out; goto out;
} }
if (c->daemonize) { if (c->daemonize) {
err = EXIT_SUCCESS; err = EXIT_SUCCESS;
} else { } else {
...@@ -243,7 +252,6 @@ int main(int argc, char *argv[]) ...@@ -243,7 +252,6 @@ int main(int argc, char *argv[])
} }
} }
out: out:
lxc_container_put(c); lxc_container_put(c);
exit(err); exit(err);
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "log.h"
lxc_log_define(lxc_freeze, lxc);
static const struct option my_longopts[] = { static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS LXC_COMMON_OPTIONS
...@@ -75,33 +78,35 @@ int main(int argc, char *argv[]) ...@@ -75,33 +78,35 @@ int main(int argc, char *argv[])
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
lxc_error(&my_args, "No such container: %s:%s", my_args.lxcpath[0], my_args.name); ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
lxc_error(&my_args, "Failed to load rcfile"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
lxc_error(&my_args, "Out of memory setting new config filename"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
lxc_error(&my_args, "Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name); ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!c->freeze(c)) { if (!c->freeze(c)) {
lxc_error(&my_args, "Failed to freeze %s:%s", my_args.lxcpath[0], my_args.name); ERROR("Failed to freeze %s:%s", my_args.lxcpath[0], my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
......
...@@ -34,7 +34,10 @@ ...@@ -34,7 +34,10 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
lxc_log_define(lxc_info, lxc);
static bool ips; static bool ips;
static bool state; static bool state;
...@@ -45,14 +48,16 @@ static char **key = NULL; ...@@ -45,14 +48,16 @@ static char **key = NULL;
static int keys = 0; static int keys = 0;
static int filter_count = 0; static int filter_count = 0;
static int my_parser(struct lxc_arguments* args, int c, char* arg) static int my_parser(struct lxc_arguments *args, int c, char *arg)
{ {
char **newk; char **newk;
switch (c) { switch (c) {
case 'c': case 'c':
newk = realloc(key, (keys + 1) * sizeof(key[0])); newk = realloc(key, (keys + 1) * sizeof(key[0]));
if (!newk) if (!newk)
return -1; return -1;
key = newk; key = newk;
key[keys] = arg; key[keys] = arg;
keys++; keys++;
...@@ -153,6 +158,7 @@ static void print_net_stats(struct lxc_container *c) ...@@ -153,6 +158,7 @@ static void print_net_stats(struct lxc_container *c)
for(netnr = 0; ;netnr++) { for(netnr = 0; ;netnr++) {
sprintf(buf, "lxc.net.%d.type", netnr); sprintf(buf, "lxc.net.%d.type", netnr);
type = c->get_running_config_item(c, buf); type = c->get_running_config_item(c, buf);
if (!type) if (!type)
break; break;
...@@ -163,9 +169,11 @@ static void print_net_stats(struct lxc_container *c) ...@@ -163,9 +169,11 @@ static void print_net_stats(struct lxc_container *c)
sprintf(buf, "lxc.net.%d.link", netnr); sprintf(buf, "lxc.net.%d.link", netnr);
} }
free(type); free(type);
ifname = c->get_running_config_item(c, buf); ifname = c->get_running_config_item(c, buf);
if (!ifname) if (!ifname)
return; return;
printf("%-15s %s\n", "Link:", ifname); printf("%-15s %s\n", "Link:", ifname);
fflush(stdout); fflush(stdout);
...@@ -303,11 +311,13 @@ static int print_info(const char *name, const char *lxcpath) ...@@ -303,11 +311,13 @@ static int print_info(const char *name, const char *lxcpath)
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
fprintf(stderr, "Failed to load rcfile\n"); fprintf(stderr, "Failed to load rcfile\n");
lxc_container_put(c); lxc_container_put(c);
return -1; return -1;
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
fprintf(stderr, "Out of memory setting new config filename\n"); fprintf(stderr, "Out of memory setting new config filename\n");
...@@ -333,9 +343,8 @@ static int print_info(const char *name, const char *lxcpath) ...@@ -333,9 +343,8 @@ static int print_info(const char *name, const char *lxcpath)
print_info_msg_str("Name:", c->name); print_info_msg_str("Name:", c->name);
} }
if (state) { if (state)
print_info_msg_str("State:", c->state(c)); print_info_msg_str("State:", c->state(c));
}
if (c->is_running(c)) { if (c->is_running(c)) {
if (pid) { if (pid) {
...@@ -348,10 +357,12 @@ static int print_info(const char *name, const char *lxcpath) ...@@ -348,10 +357,12 @@ static int print_info(const char *name, const char *lxcpath)
if (ips) { if (ips) {
fflush(stdout); fflush(stdout);
char **addresses = c->get_ips(c, NULL, NULL, 0); char **addresses = c->get_ips(c, NULL, NULL, 0);
if (addresses) { if (addresses) {
char *address; char *address;
i = 0; i = 0;
while (addresses[i]) { while (addresses[i]) {
address = addresses[i]; address = addresses[i];
print_info_msg_str("IP:", address); print_info_msg_str("IP:", address);
...@@ -380,6 +391,7 @@ static int print_info(const char *name, const char *lxcpath) ...@@ -380,6 +391,7 @@ static int print_info(const char *name, const char *lxcpath)
else else
printf("%s = %s\n", key[i], val); printf("%s = %s\n", key[i], val);
} }
free(val); free(val);
} else if (len == 0) { } else if (len == 0) {
if (!humanize && keys == 1) if (!humanize && keys == 1)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include <dirent.h>
#include <getopt.h> #include <getopt.h>
#include <limits.h> #include <limits.h>
#include <regex.h> #include <regex.h>
...@@ -35,7 +36,10 @@ ...@@ -35,7 +36,10 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
lxc_log_define(lxc_ls, lxc);
/* Per default we only allow five levels of recursion to protect the stack at /* Per default we only allow five levels of recursion to protect the stack at
* least a little bit. */ * least a little bit. */
...@@ -156,6 +160,8 @@ static int ls_remove_lock(const char *path, const char *name, ...@@ -156,6 +160,8 @@ static int ls_remove_lock(const char *path, const char *name,
static int ls_serialize(int wpipefd, struct ls *n); static int ls_serialize(int wpipefd, struct ls *n);
static int my_parser(struct lxc_arguments *args, int c, char *arg); static int my_parser(struct lxc_arguments *args, int c, char *arg);
static int rm_r(char *dirname);
static const struct option my_longopts[] = { static const struct option my_longopts[] = {
{"line", no_argument, 0, '1'}, {"line", no_argument, 0, '1'},
{"fancy", no_argument, 0, 'f'}, {"fancy", no_argument, 0, 'f'},
...@@ -203,6 +209,7 @@ int main(int argc, char *argv[]) ...@@ -203,6 +209,7 @@ int main(int argc, char *argv[])
{ {
int ret = EXIT_FAILURE; int ret = EXIT_FAILURE;
struct lxc_log log; struct lxc_log log;
/* /*
* The lxc parser requires that my_args.name is set. So let's satisfy * The lxc parser requires that my_args.name is set. So let's satisfy
* that condition by setting a dummy name which is never used. * that condition by setting a dummy name which is never used.
...@@ -248,6 +255,7 @@ int main(int argc, char *argv[]) ...@@ -248,6 +255,7 @@ int main(int argc, char *argv[])
struct ls *ls_arr = NULL; struct ls *ls_arr = NULL;
size_t ls_size = 0; size_t ls_size = 0;
/* &(char *){NULL} is no magic. It's just a compound literal which /* &(char *){NULL} is no magic. It's just a compound literal which
* avoids having a pointless variable in main() that serves no purpose * avoids having a pointless variable in main() that serves no purpose
* here. */ * here. */
...@@ -259,6 +267,7 @@ int main(int argc, char *argv[]) ...@@ -259,6 +267,7 @@ int main(int argc, char *argv[])
goto out; goto out;
ls_field_width(ls_arr, ls_size, &max_len); ls_field_width(ls_arr, ls_size, &max_len);
if (my_args.ls_fancy && !my_args.ls_fancy_format) { if (my_args.ls_fancy && !my_args.ls_fancy_format) {
ls_print_table(ls_arr, &max_len, ls_size); ls_print_table(ls_arr, &max_len, ls_size);
} else if (my_args.ls_fancy && my_args.ls_fancy_format) { } else if (my_args.ls_fancy && my_args.ls_fancy_format) {
...@@ -283,6 +292,7 @@ static void ls_free(struct ls *l, size_t size) ...@@ -283,6 +292,7 @@ static void ls_free(struct ls *l, size_t size)
{ {
size_t i; size_t i;
struct ls *m = NULL; struct ls *m = NULL;
for (i = 0, m = l; i < size; i++, m++) { for (i = 0, m = l; i < size; i++, m++) {
free(m->groups); free(m->groups);
free(m->interface); free(m->interface);
...@@ -319,8 +329,10 @@ static char *ls_get_config_item(struct lxc_container *c, const char *item, ...@@ -319,8 +329,10 @@ static char *ls_get_config_item(struct lxc_container *c, const char *item,
static void ls_free_arr(char **arr, size_t size) static void ls_free_arr(char **arr, size_t size)
{ {
size_t i; size_t i;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
free(arr[i]); free(arr[i]);
free(arr); free(arr);
} }
...@@ -372,18 +384,21 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args, ...@@ -372,18 +384,21 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args,
struct ls *l = NULL; struct ls *l = NULL;
struct lxc_container *c = NULL; struct lxc_container *c = NULL;
size_t i; size_t i;
for (i = 0; i < (size_t)num; i++) { for (i = 0; i < (size_t)num; i++) {
char *name = containers[i]; char *name = containers[i];
/* Filter container names by regex the user gave us. */ /* Filter container names by regex the user gave us. */
if (args->ls_filter || args->argc == 1) { if (args->ls_filter || args->argc == 1) {
regex_t preg; regex_t preg;
tmp = args->ls_filter ? args->ls_filter : args->argv[0]; tmp = args->ls_filter ? args->ls_filter : args->argv[0];
check = regcomp(&preg, tmp, REG_NOSUB | REG_EXTENDED); check = regcomp(&preg, tmp, REG_NOSUB | REG_EXTENDED);
if (check == REG_ESPACE) /* we're out of memory */ if (check == REG_ESPACE) /* we're out of memory */
goto out; goto out;
else if (check != 0) else if (check != 0)
continue; continue;
check = regexec(&preg, name, 0, NULL, 0); check = regexec(&preg, name, 0, NULL, 0);
regfree(&preg); regfree(&preg);
if (check != 0) if (check != 0)
...@@ -397,9 +412,8 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args, ...@@ -397,9 +412,8 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args,
else if (!c) else if (!c)
continue; continue;
if (args->ls_defined && !c->is_defined(c)){ if (args->ls_defined && !c->is_defined(c))
goto put_and_next; goto put_and_next;
}
/* This does not allocate memory so no worries about freeing it /* This does not allocate memory so no worries about freeing it
* when we goto next or out. */ * when we goto next or out. */
...@@ -508,6 +522,7 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args, ...@@ -508,6 +522,7 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args,
* all other information we need. */ * all other information we need. */
if (args->ls_nesting && running) { if (args->ls_nesting && running) {
struct wrapargs wargs = (struct wrapargs){.args = NULL}; struct wrapargs wargs = (struct wrapargs){.args = NULL};
/* Open a socket so that the child can communicate with us. */ /* Open a socket so that the child can communicate with us. */
check = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wargs.pipefd); check = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wargs.pipefd);
if (check == -1) if (check == -1)
...@@ -588,6 +603,7 @@ put_and_next: ...@@ -588,6 +603,7 @@ put_and_next:
out: out:
ls_free_arr(containers, num); ls_free_arr(containers, num);
free(path); free(path);
/* lockpath is shared amongst all non-fork()ing recursive calls to /* lockpath is shared amongst all non-fork()ing recursive calls to
* ls_get() so only free it on the uppermost level. */ * ls_get() so only free it on the uppermost level. */
if (lvl == 0) if (lvl == 0)
...@@ -634,6 +650,7 @@ static char *ls_get_groups(struct lxc_container *c, bool running) ...@@ -634,6 +650,7 @@ static char *ls_get_groups(struct lxc_container *c, bool running)
if (val) { if (val) {
char *tmp; char *tmp;
if ((tmp = strrchr(val, '\n'))) if ((tmp = strrchr(val, '\n')))
*tmp = '\0'; *tmp = '\0';
...@@ -648,7 +665,9 @@ static char *ls_get_groups(struct lxc_container *c, bool running) ...@@ -648,7 +665,9 @@ static char *ls_get_groups(struct lxc_container *c, bool running)
static char *ls_get_ips(struct lxc_container *c, const char *inet) static char *ls_get_ips(struct lxc_container *c, const char *inet)
{ {
char *ips = NULL; char *ips = NULL;
char **iptmp = c->get_ips(c, NULL, inet, 0); char **iptmp;
iptmp = c->get_ips(c, NULL, inet, 0);
if (iptmp) if (iptmp)
ips = lxc_string_join(", ", (const char **)iptmp, false); ips = lxc_string_join(", ", (const char **)iptmp, false);
...@@ -712,6 +731,7 @@ out: ...@@ -712,6 +731,7 @@ out:
static unsigned int ls_get_term_width(void) static unsigned int ls_get_term_width(void)
{ {
struct winsize ws; struct winsize ws;
if (((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1) && if (((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1) &&
(ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1) && (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1) &&
(ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)) || (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)) ||
...@@ -745,6 +765,7 @@ static bool ls_has_all_grps(const char *has, char **must, size_t must_len) ...@@ -745,6 +765,7 @@ static bool ls_has_all_grps(const char *has, char **must, size_t must_len)
if (j == tmp_has_len) if (j == tmp_has_len)
break; break;
} }
if (i == must_len) if (i == must_len)
bret = true; bret = true;
...@@ -780,11 +801,13 @@ static void ls_print_names(struct ls *l, struct lengths *lht, ...@@ -780,11 +801,13 @@ static void ls_print_names(struct ls *l, struct lengths *lht,
size_t i, len = 0; size_t i, len = 0;
struct ls *m = NULL; struct ls *m = NULL;
for (i = 0, m = l; i < size; i++, m++) { for (i = 0, m = l; i < size; i++, m++) {
if (list) { if (list) {
printf("%s\n", m->name ? m->name : "-"); printf("%s\n", m->name ? m->name : "-");
} else { } else {
printf("%-*s", lht->name_length, m->name ? m->name : "-"); printf("%-*s", lht->name_length, m->name ? m->name : "-");
len += lht->name_length; len += lht->name_length;
if ((len + lht->name_length) >= termwidth) { if ((len + lht->name_length) >= termwidth) {
printf("\n"); printf("\n");
...@@ -795,6 +818,7 @@ static void ls_print_names(struct ls *l, struct lengths *lht, ...@@ -795,6 +818,7 @@ static void ls_print_names(struct ls *l, struct lengths *lht,
} }
} }
} }
if (len > 0) if (len > 0)
printf("\n"); printf("\n");
} }
...@@ -854,6 +878,7 @@ static void ls_print_fancy_format(struct ls *l, struct lengths *lht, ...@@ -854,6 +878,7 @@ static void ls_print_fancy_format(struct ls *l, struct lengths *lht,
struct ls *m = NULL; struct ls *m = NULL;
size_t i; size_t i;
for (i = 0, m = l; i < size; i++, m++) { for (i = 0, m = l; i < size; i++, m++) {
for (s = tmp; s && *s; s++) { for (s = tmp; s && *s; s++) {
if (strcasecmp(*s, "NAME") == 0) { if (strcasecmp(*s, "NAME") == 0) {
...@@ -903,6 +928,8 @@ static void ls_print_fancy_format(struct ls *l, struct lengths *lht, ...@@ -903,6 +928,8 @@ static void ls_print_fancy_format(struct ls *l, struct lengths *lht,
static void ls_print_table(struct ls *l, struct lengths *lht, static void ls_print_table(struct ls *l, struct lengths *lht,
size_t size) size_t size)
{ {
size_t i;
/* If list is empty do nothing. */ /* If list is empty do nothing. */
if (size == 0) if (size == 0)
return; return;
...@@ -919,7 +946,6 @@ static void ls_print_table(struct ls *l, struct lengths *lht, ...@@ -919,7 +946,6 @@ static void ls_print_table(struct ls *l, struct lengths *lht,
printf("%-*s ", lht->unprivileged_length, "UNPRIVILEGED"); printf("%-*s ", lht->unprivileged_length, "UNPRIVILEGED");
printf("\n"); printf("\n");
size_t i;
for (i = 0, m = l; i < size; i++, m++) { for (i = 0, m = l; i < size; i++, m++) {
if (m->nestlvl > 0) { if (m->nestlvl > 0) {
printf("%*s", m->nestlvl, "\\"); printf("%*s", m->nestlvl, "\\");
...@@ -927,6 +953,7 @@ static void ls_print_table(struct ls *l, struct lengths *lht, ...@@ -927,6 +953,7 @@ static void ls_print_table(struct ls *l, struct lengths *lht,
} else { } else {
printf("%-*s ", lht->name_length, m->name ? m->name : "-"); printf("%-*s ", lht->name_length, m->name ? m->name : "-");
} }
printf("%-*s ", lht->state_length, m->state ? m->state : "-"); printf("%-*s ", lht->state_length, m->state ? m->state : "-");
printf("%-*d ", lht->autostart_length, m->autostart); printf("%-*d ", lht->autostart_length, m->autostart);
printf("%-*s ", lht->groups_length, m->groups ? m->groups : "-"); printf("%-*s ", lht->groups_length, m->groups ? m->groups : "-");
...@@ -941,6 +968,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) ...@@ -941,6 +968,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
{ {
char *invalid; char *invalid;
unsigned long int m, n = MAX_NESTLVL; unsigned long int m, n = MAX_NESTLVL;
switch (c) { switch (c) {
case '1': case '1':
args->ls_line = true; args->ls_line = true;
...@@ -1000,6 +1028,7 @@ static int ls_get_wrapper(void *wrap) ...@@ -1000,6 +1028,7 @@ static int ls_get_wrapper(void *wrap)
size_t len = 0; size_t len = 0;
struct wrapargs *wargs = (struct wrapargs *)wrap; struct wrapargs *wargs = (struct wrapargs *)wrap;
struct ls *m = NULL, *n = NULL; struct ls *m = NULL, *n = NULL;
size_t i;
/* close pipe */ /* close pipe */
close(wargs->pipefd[0]); close(wargs->pipefd[0]);
...@@ -1014,7 +1043,6 @@ static int ls_get_wrapper(void *wrap) ...@@ -1014,7 +1043,6 @@ static int ls_get_wrapper(void *wrap)
if (lxc_write_nointr(wargs->pipefd[1], &len, sizeof(len)) <= 0) if (lxc_write_nointr(wargs->pipefd[1], &len, sizeof(len)) <= 0)
goto out; goto out;
size_t i;
for (i = 0, n = m; i < len; i++, n++) { for (i = 0, n = m; i < len; i++, n++) {
if (ls_serialize(wargs->pipefd[1], n) == -1) if (ls_serialize(wargs->pipefd[1], n) == -1)
goto out; goto out;
...@@ -1071,14 +1099,18 @@ out: ...@@ -1071,14 +1099,18 @@ out:
static int ls_send_str(int fd, const char *buf) static int ls_send_str(int fd, const char *buf)
{ {
size_t slen = 0; size_t slen = 0;
if (buf) if (buf)
slen = strlen(buf); slen = strlen(buf);
if (lxc_write_nointr(fd, &slen, sizeof(slen)) != sizeof(slen)) if (lxc_write_nointr(fd, &slen, sizeof(slen)) != sizeof(slen))
return -1; return -1;
if (slen > 0) { if (slen > 0) {
if (lxc_write_nointr(fd, buf, slen) != (ssize_t)slen) if (lxc_write_nointr(fd, buf, slen) != (ssize_t)slen)
return -1; return -1;
} }
return 0; return 0;
} }
...@@ -1242,6 +1274,7 @@ static void ls_field_width(const struct ls *l, const size_t size, ...@@ -1242,6 +1274,7 @@ static void ls_field_width(const struct ls *l, const size_t size,
{ {
const struct ls *m; const struct ls *m;
size_t i, len = 0; size_t i, len = 0;
for (i = 0, m = l; i < size; i++, m++) { for (i = 0, m = l; i < size; i++, m++) {
if (m->name) { if (m->name) {
len = strlen(m->name) + m->nestlvl; len = strlen(m->name) + m->nestlvl;
...@@ -1290,3 +1323,51 @@ static void ls_field_width(const struct ls *l, const size_t size, ...@@ -1290,3 +1323,51 @@ static void ls_field_width(const struct ls *l, const size_t size,
} }
} }
} }
static 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 (!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;
}
...@@ -30,7 +30,9 @@ ...@@ -30,7 +30,9 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
lxc_log_define(lxc_snapshot, lxc);
static int my_parser(struct lxc_arguments *args, int c, char *arg); static int my_parser(struct lxc_arguments *args, int c, char *arg);
...@@ -99,42 +101,42 @@ int main(int argc, char *argv[]) ...@@ -99,42 +101,42 @@ int main(int argc, char *argv[])
if (geteuid()) { if (geteuid()) {
if (access(my_args.lxcpath[0], O_RDONLY) < 0) { if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
fprintf(stderr, "You lack access to %s\n", ERROR("You lack access to %s", my_args.lxcpath[0]);
my_args.lxcpath[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
fprintf(stderr, "System error loading container\n"); ERROR("System error loading container");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (my_args.rcfile) { if (my_args.rcfile) {
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
fprintf(stderr, "Failed to load rcfile\n"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
fprintf(stderr, "Out of memory setting new config filename\n"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!c->lxc_conf) { if (!c->lxc_conf) {
fprintf(stderr, "No container config specified\n"); ERROR("No container config specified");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
fprintf(stderr, "Insufficent privileges to control %s\n", ERROR("Insufficent privileges to control %s", my_args.name);
my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -145,6 +147,7 @@ int main(int argc, char *argv[]) ...@@ -145,6 +147,7 @@ int main(int argc, char *argv[])
if (ret == 0) if (ret == 0)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -207,7 +210,7 @@ static int do_snapshot(struct lxc_container *c, char *commentfile) ...@@ -207,7 +210,7 @@ static int do_snapshot(struct lxc_container *c, char *commentfile)
ret = c->snapshot(c, commentfile); ret = c->snapshot(c, commentfile);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error creating a snapshot\n"); ERROR("Error creating a snapshot");
return -1; return -1;
} }
...@@ -218,13 +221,13 @@ static int do_snapshot_destroy(struct lxc_container *c, char *snapname) ...@@ -218,13 +221,13 @@ static int do_snapshot_destroy(struct lxc_container *c, char *snapname)
{ {
bool ret; bool ret;
if (strcmp(snapname, "ALL") == 0) if (strncmp(snapname, "ALL", strlen(snapname)) == 0)
ret = c->snapshot_destroy_all(c); ret = c->snapshot_destroy_all(c);
else else
ret = c->snapshot_destroy(c, snapname); ret = c->snapshot_destroy(c, snapname);
if (!ret) { if (!ret) {
fprintf(stderr, "Error destroying snapshot %s\n", snapname); ERROR("Error destroying snapshot %s", snapname);
return -1; return -1;
} }
...@@ -238,9 +241,10 @@ static int do_snapshot_list(struct lxc_container *c, int print_comments) ...@@ -238,9 +241,10 @@ static int do_snapshot_list(struct lxc_container *c, int print_comments)
n = c->snapshot_list(c, &s); n = c->snapshot_list(c, &s);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error listing snapshots\n"); ERROR("Error listing snapshots");
return -1; return -1;
} }
if (n == 0) { if (n == 0) {
printf("No snapshots\n"); printf("No snapshots\n");
return 0; return 0;
...@@ -248,8 +252,10 @@ static int do_snapshot_list(struct lxc_container *c, int print_comments) ...@@ -248,8 +252,10 @@ static int do_snapshot_list(struct lxc_container *c, int print_comments)
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
printf("%s (%s) %s\n", s[i].name, s[i].lxcpath, s[i].timestamp); printf("%s (%s) %s\n", s[i].name, s[i].lxcpath, s[i].timestamp);
if (print_comments) if (print_comments)
print_file(s[i].comment_pathname); print_file(s[i].comment_pathname);
s[i].free(&s[i]); s[i].free(&s[i]);
} }
...@@ -269,7 +275,7 @@ static int do_snapshot_restore(struct lxc_container *c, ...@@ -269,7 +275,7 @@ static int do_snapshot_restore(struct lxc_container *c,
* original container will be destroyed and the restored container will * original container will be destroyed and the restored container will
* take its place. */ * take its place. */
if ((!args->newname) && (args->argc > 1)) { if ((!args->newname) && (args->argc > 1)) {
lxc_error(args, "Too many arguments"); ERROR("Too many arguments");
return -1; return -1;
} }
...@@ -278,7 +284,7 @@ static int do_snapshot_restore(struct lxc_container *c, ...@@ -278,7 +284,7 @@ static int do_snapshot_restore(struct lxc_container *c,
bret = c->snapshot_restore(c, args->snapname, args->newname); bret = c->snapshot_restore(c, args->snapname, args->newname);
if (!bret) { if (!bret) {
fprintf(stderr, "Error restoring snapshot %s\n", args->snapname); ERROR("Error restoring snapshot %s", args->snapname);
return -1; return -1;
} }
...@@ -287,19 +293,19 @@ static int do_snapshot_restore(struct lxc_container *c, ...@@ -287,19 +293,19 @@ static int do_snapshot_restore(struct lxc_container *c,
static void print_file(char *path) static void print_file(char *path)
{ {
if (!path) FILE *f;
return;
FILE *f = fopen(path, "r");
char *line = NULL; char *line = NULL;
size_t sz = 0; size_t sz = 0;
if (!path)
return;
f = fopen(path, "r");
if (!f) if (!f)
return; return;
while (getline(&line, &sz, f) != -1) { while (getline(&line, &sz, f) != -1)
printf("%s", line); printf("%s", line);
}
free(line); free(line);
fclose(f); fclose(f);
......
...@@ -42,11 +42,14 @@ ...@@ -42,11 +42,14 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_list.h" #include "caps.h"
#include "tool_utils.h" #include "confile.h"
#include "log.h"
static struct lxc_list defines; static struct lxc_list defines;
lxc_log_define(lxc_start, lxc);
static int ensure_path(struct lxc_arguments *args, char **confpath, const char *path) static int ensure_path(struct lxc_arguments *args, char **confpath, const char *path)
{ {
int err = -1, fd; int err = -1, fd;
...@@ -56,7 +59,7 @@ static int ensure_path(struct lxc_arguments *args, char **confpath, const char * ...@@ -56,7 +59,7 @@ static int ensure_path(struct lxc_arguments *args, char **confpath, const char *
if (access(path, W_OK)) { if (access(path, W_OK)) {
fd = creat(path, 0600); fd = creat(path, 0600);
if (fd < 0 && errno != EEXIST) { if (fd < 0 && errno != EEXIST) {
lxc_error(args, "Failed to create '%s'", path); ERROR("Failed to create '%s'", path);
goto err; goto err;
} }
...@@ -66,7 +69,7 @@ static int ensure_path(struct lxc_arguments *args, char **confpath, const char * ...@@ -66,7 +69,7 @@ static int ensure_path(struct lxc_arguments *args, char **confpath, const char *
fullpath = realpath(path, NULL); fullpath = realpath(path, NULL);
if (!fullpath) { if (!fullpath) {
lxc_error(args, "Failed to get the real path of '%s'", path); ERROR("Failed to get the real path of '%s'", path);
goto err; goto err;
} }
...@@ -206,7 +209,7 @@ int main(int argc, char *argv[]) ...@@ -206,7 +209,7 @@ int main(int argc, char *argv[])
lxcpath = my_args.lxcpath[0]; lxcpath = my_args.lxcpath[0];
if (access(lxcpath, O_RDONLY) < 0) { if (access(lxcpath, O_RDONLY) < 0) {
lxc_error(&my_args, "You lack access to %s", lxcpath); ERROR("You lack access to %s", lxcpath);
exit(err); exit(err);
} }
...@@ -222,21 +225,21 @@ int main(int argc, char *argv[]) ...@@ -222,21 +225,21 @@ int main(int argc, char *argv[])
c = lxc_container_new(my_args.name, lxcpath); c = lxc_container_new(my_args.name, lxcpath);
if (!c) { if (!c) {
lxc_error(&my_args, "Failed to create lxc_container"); ERROR("Failed to create lxc_container");
exit(err); exit(err);
} }
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, rcfile)) { if (!c->load_config(c, rcfile)) {
lxc_error(&my_args, "Failed to load rcfile"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(err); exit(err);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
lxc_error(&my_args, "Out of memory setting new config filename"); ERROR("Out of memory setting new config filename");
goto out; goto out;
} }
} else { } else {
...@@ -244,7 +247,7 @@ int main(int argc, char *argv[]) ...@@ -244,7 +247,7 @@ int main(int argc, char *argv[])
rc = asprintf(&rcfile, "%s/%s/config", lxcpath, my_args.name); rc = asprintf(&rcfile, "%s/%s/config", lxcpath, my_args.name);
if (rc == -1) { if (rc == -1) {
lxc_error(&my_args, "Failed to allocate memory"); ERROR("Failed to allocate memory");
exit(err); exit(err);
} }
...@@ -256,7 +259,7 @@ int main(int argc, char *argv[]) ...@@ -256,7 +259,7 @@ int main(int argc, char *argv[])
c = lxc_container_new(my_args.name, lxcpath); c = lxc_container_new(my_args.name, lxcpath);
if (!c) { if (!c) {
lxc_error(&my_args, "Failed to create lxc_container"); ERROR("Failed to create lxc_container");
exit(err); exit(err);
} }
} }
...@@ -267,12 +270,12 @@ int main(int argc, char *argv[]) ...@@ -267,12 +270,12 @@ int main(int argc, char *argv[])
* file as argument and start the container right away. * file as argument and start the container right away.
*/ */
if (!c->may_control(c)) { if (!c->may_control(c)) {
lxc_error(&my_args, "Insufficent privileges to control %s", c->name); ERROR("Insufficent privileges to control %s", c->name);
goto out; goto out;
} }
if (c->is_running(c)) { if (c->is_running(c)) {
lxc_error(&my_args, "Container is already running."); ERROR("Container is already running");
err = EXIT_SUCCESS; err = EXIT_SUCCESS;
goto out; goto out;
} }
...@@ -282,7 +285,7 @@ int main(int argc, char *argv[]) ...@@ -282,7 +285,7 @@ int main(int argc, char *argv[])
* unset c->lxc_conf for us and let us not use lxc_config_define_load() * unset c->lxc_conf for us and let us not use lxc_config_define_load()
*/ */
if (!c->lxc_conf) { if (!c->lxc_conf) {
lxc_error(&my_args, "No container config specified"); ERROR("No container config specified");
goto out; goto out;
} }
...@@ -290,13 +293,13 @@ int main(int argc, char *argv[]) ...@@ -290,13 +293,13 @@ int main(int argc, char *argv[])
goto out; goto out;
if (!rcfile && !strcmp("/sbin/init", args[0])) { if (!rcfile && !strcmp("/sbin/init", args[0])) {
lxc_error(&my_args, "Executing '/sbin/init' with no configuration file may crash the host"); ERROR("Executing '/sbin/init' with no configuration file may crash the host");
goto out; goto out;
} }
if (my_args.pidfile != NULL) { if (my_args.pidfile != NULL) {
if (ensure_path(&my_args, &c->pidfile, my_args.pidfile) < 0) { if (ensure_path(&my_args, &c->pidfile, my_args.pidfile) < 0) {
lxc_error(&my_args, "Failed to ensure pidfile '%s'", my_args.pidfile); ERROR("Failed to ensure pidfile '%s'", my_args.pidfile);
goto out; goto out;
} }
} }
...@@ -324,13 +327,13 @@ int main(int argc, char *argv[]) ...@@ -324,13 +327,13 @@ int main(int argc, char *argv[])
else else
err = c->start(c, 0, args) ? EXIT_SUCCESS : EXIT_FAILURE; err = c->start(c, 0, args) ? EXIT_SUCCESS : EXIT_FAILURE;
if (err) { if (err) {
lxc_error(&my_args, "The container failed to start."); ERROR("The container failed to start");
if (my_args.daemonize) if (my_args.daemonize)
lxc_error(&my_args, "To get more details, run the container in foreground mode."); ERROR("To get more details, run the container in foreground mode");
lxc_error(&my_args, "Additional information can be obtained by setting the " ERROR("Additional information can be obtained by setting the "
"--logfile and --logpriority options.\n"); "--logfile and --logpriority options");
err = c->error_num; err = c->error_num;
lxc_container_put(c); lxc_container_put(c);
......
...@@ -31,11 +31,14 @@ ...@@ -31,11 +31,14 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
#include "utils.h"
#define OPT_NO_LOCK OPT_USAGE + 1 #define OPT_NO_LOCK OPT_USAGE + 1
#define OPT_NO_KILL OPT_USAGE + 2 #define OPT_NO_KILL OPT_USAGE + 2
lxc_log_define(lxc_stop, lxc);
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) { switch (c) {
...@@ -130,33 +133,33 @@ int main(int argc, char *argv[]) ...@@ -130,33 +133,33 @@ int main(int argc, char *argv[])
/* some checks */ /* some checks */
if (!my_args.hardstop && my_args.timeout < -1) { if (!my_args.hardstop && my_args.timeout < -1) {
lxc_error(&my_args, "Invalid timeout"); ERROR("Invalid timeout");
exit(ret); exit(ret);
} }
if (my_args.hardstop && my_args.nokill) { if (my_args.hardstop && my_args.nokill) {
lxc_error(&my_args, "-k can't be used with --nokill"); ERROR("-k can't be used with --nokill");
exit(ret); exit(ret);
} }
if (my_args.hardstop && my_args.reboot) { if (my_args.hardstop && my_args.reboot) {
lxc_error(&my_args, "-k can't be used with -r"); ERROR("-k can't be used with -r");
exit(ret); exit(ret);
} }
if (my_args.hardstop && my_args.timeout) { if (my_args.hardstop && my_args.timeout) {
lxc_error(&my_args, "-k doesn't allow timeouts"); ERROR("-k doesn't allow timeouts");
exit(ret); exit(ret);
} }
if (my_args.nolock && !my_args.hardstop) { if (my_args.nolock && !my_args.hardstop) {
lxc_error(&my_args, "--nolock may only be used with -k"); ERROR("--nolock may only be used with -k");
exit(ret); exit(ret);
} }
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
lxc_error(&my_args, "Error opening container"); ERROR("Error opening container");
goto out; goto out;
} }
...@@ -164,24 +167,24 @@ int main(int argc, char *argv[]) ...@@ -164,24 +167,24 @@ int main(int argc, char *argv[])
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
lxc_error(&my_args, "Failed to load rcfile"); ERROR("Failed to load rcfile");
goto out; goto out;
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
lxc_error(&my_args, "Out of memory setting new config filename"); ERROR("Out of memory setting new config filename");
goto out; goto out;
} }
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
lxc_error(&my_args, "Insufficent privileges to control %s", c->name); ERROR("Insufficent privileges to control %s", c->name);
goto out; goto out;
} }
if (!c->is_running(c)) { if (!c->is_running(c)) {
lxc_error(&my_args, "%s is not running", c->name); ERROR("%s is not running", c->name);
/* Per our manpage we need to exit with exit code: /* Per our manpage we need to exit with exit code:
* 2: The specified container exists but was not running. * 2: The specified container exists but was not running.
......
...@@ -31,7 +31,9 @@ ...@@ -31,7 +31,9 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
lxc_log_define(lxc_unfreeze, lxc);
static const struct option my_longopts[] = { static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS LXC_COMMON_OPTIONS
...@@ -75,12 +77,12 @@ int main(int argc, char *argv[]) ...@@ -75,12 +77,12 @@ int main(int argc, char *argv[])
c = lxc_container_new(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) { if (!c) {
lxc_error(&my_args, "No such container: %s:%s", my_args.lxcpath[0], my_args.name); ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!c->may_control(c)) { if (!c->may_control(c)) {
lxc_error(&my_args, "Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name); ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -89,21 +91,21 @@ int main(int argc, char *argv[]) ...@@ -89,21 +91,21 @@ int main(int argc, char *argv[])
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
lxc_error(&my_args, "Failed to load rcfile"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
lxc_error(&my_args, "Out of memory setting new config filename"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!c->unfreeze(c)) { if (!c->unfreeze(c)) {
lxc_error(&my_args, "Failed to unfreeze %s:%s", my_args.lxcpath[0], my_args.name); ERROR("Failed to unfreeze %s:%s", my_args.lxcpath[0], my_args.name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
......
...@@ -40,7 +40,9 @@ ...@@ -40,7 +40,9 @@
#include <sys/wait.h> #include <sys/wait.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "caps.h"
#include "namespace.h"
#include "utils.h"
/* Define sethostname() if missing from the C library also workaround some /* Define sethostname() if missing from the C library also workaround some
* quirky with having this defined in multiple places. * quirky with having this defined in multiple places.
...@@ -76,12 +78,13 @@ static void usage(char *cmd) ...@@ -76,12 +78,13 @@ static void usage(char *cmd)
fprintf(stderr, "\t -H <hostname>: Set the hostname in the container\n"); fprintf(stderr, "\t -H <hostname>: Set the hostname in the container\n");
fprintf(stderr, "\t -d : Daemonize (do not wait for container to exit)\n"); fprintf(stderr, "\t -d : Daemonize (do not wait for container to exit)\n");
fprintf(stderr, "\t -M : Remount default fs inside container (/proc /dev/shm /dev/mqueue)\n"); fprintf(stderr, "\t -M : Remount default fs inside container (/proc /dev/shm /dev/mqueue)\n");
_exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
} }
static bool lookup_user(const char *optarg, uid_t *uid) static bool lookup_user(const char *optarg, uid_t *uid)
{ {
char name[TOOL_MAXPATHLEN]; char name[MAXPATHLEN];
struct passwd pwent; struct passwd pwent;
struct passwd *pwentp = NULL; struct passwd *pwentp = NULL;
char *buf; char *buf;
...@@ -109,20 +112,21 @@ static bool lookup_user(const char *optarg, uid_t *uid) ...@@ -109,20 +112,21 @@ static bool lookup_user(const char *optarg, uid_t *uid)
ret = getpwnam_r(name, &pwent, buf, bufsize, &pwentp); ret = getpwnam_r(name, &pwent, buf, bufsize, &pwentp);
if (!pwentp) { if (!pwentp) {
if (ret == 0) if (ret == 0)
fprintf(stderr, "could not find matched password record\n"); fprintf(stderr, "Could not find matched password record\n");
fprintf(stderr, "invalid username %s\n", name); fprintf(stderr, "Invalid username %s\n", name);
free(buf); free(buf);
return false; return false;
} }
*uid = pwent.pw_uid; *uid = pwent.pw_uid;
} else { } else {
ret = getpwuid_r(*uid, &pwent, buf, bufsize, &pwentp); ret = getpwuid_r(*uid, &pwent, buf, bufsize, &pwentp);
if (!pwentp) { if (!pwentp) {
if (ret == 0) if (ret == 0)
fprintf(stderr, "could not find matched password record\n"); fprintf(stderr, "Could not find matched password record\n");
fprintf(stderr, "invalid uid %u\n", *uid); fprintf(stderr, "Invalid uid %u\n", *uid);
free(buf); free(buf);
return false; return false;
} }
...@@ -142,6 +146,37 @@ struct start_arg { ...@@ -142,6 +146,37 @@ struct start_arg {
const char *want_hostname; const char *want_hostname;
}; };
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;
}
static 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");
}
static int do_start(void *arg) static int do_start(void *arg)
{ {
int ret; int ret;
...@@ -159,8 +194,8 @@ static int do_start(void *arg) ...@@ -159,8 +194,8 @@ static int do_start(void *arg)
ret = read(wait_fd, &wait_val, sizeof(wait_val)); ret = read(wait_fd, &wait_val, sizeof(wait_val));
if (ret == -1) { if (ret == -1) {
close(wait_fd); close(wait_fd);
fprintf(stderr, "read eventfd failed\n"); fprintf(stderr, "Failed to read eventfd\n");
exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
} }
...@@ -169,30 +204,29 @@ static int do_start(void *arg) ...@@ -169,30 +204,29 @@ static int do_start(void *arg)
if ((flags & CLONE_NEWUTS) && want_hostname) if ((flags & CLONE_NEWUTS) && want_hostname)
if (sethostname_including_android(want_hostname, strlen(want_hostname)) < 0) { if (sethostname_including_android(want_hostname, strlen(want_hostname)) < 0) {
fprintf(stderr, "failed to set hostname %s: %s\n", want_hostname, strerror(errno)); fprintf(stderr, "Failed to set hostname %s: %s\n", want_hostname, strerror(errno));
exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
/* Setuid is useful even without a new user id space. */ /* Setuid is useful even without a new user id space. */
if (start_arg->setuid && setuid(uid)) { if (start_arg->setuid && setuid(uid)) {
fprintf(stderr, "failed to set uid %d: %s\n", uid, strerror(errno)); fprintf(stderr, "Failed to set uid %d: %s\n", uid, strerror(errno));
exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
execvp(args[0], args); execvp(args[0], args);
fprintf(stderr, "failed to exec: '%s': %s\n", args[0], strerror(errno)); fprintf(stderr, "Failed to exec: '%s': %s\n", args[0], strerror(errno));
return 1; return 1;
} }
int write_id_mapping(pid_t pid, const char *buf, size_t buf_size) static int write_id_mapping(pid_t pid, const char *buf, size_t buf_size)
{ {
char path[TOOL_MAXPATHLEN]; char path[MAXPATHLEN];
int fd, ret; int fd, ret;
ret = snprintf(path, MAXPATHLEN, "/proc/%d/uid_map", pid);
ret = snprintf(path, TOOL_MAXPATHLEN, "/proc/%d/uid_map", pid); if (ret < 0 || ret >= MAXPATHLEN)
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return -E2BIG; return -E2BIG;
fd = open(path, O_WRONLY); fd = open(path, O_WRONLY);
...@@ -239,6 +273,7 @@ int main(int argc, char *argv[]) ...@@ -239,6 +273,7 @@ int main(int argc, char *argv[])
perror("malloc"); perror("malloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
tmpif->mi_ifname = optarg; tmpif->mi_ifname = optarg;
tmpif->mi_next = my_iflist; tmpif->mi_next = my_iflist;
my_iflist = tmpif; my_iflist = tmpif;
...@@ -263,7 +298,7 @@ int main(int argc, char *argv[]) ...@@ -263,7 +298,7 @@ int main(int argc, char *argv[])
} }
if (argv[optind] == NULL) { if (argv[optind] == NULL) {
fprintf(stderr, "a command to execute in the new namespace is required\n"); fprintf(stderr, "A command to execute in the new namespace is required\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -320,14 +355,14 @@ int main(int argc, char *argv[]) ...@@ -320,14 +355,14 @@ int main(int argc, char *argv[])
if (start_arg.setuid) { if (start_arg.setuid) {
start_arg.wait_fd = eventfd(0, EFD_CLOEXEC); start_arg.wait_fd = eventfd(0, EFD_CLOEXEC);
if (start_arg.wait_fd < 0) { if (start_arg.wait_fd < 0) {
fprintf(stderr, "failed to create eventfd\n"); fprintf(stderr, "Failed to create eventfd\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
pid = lxc_clone(do_start, &start_arg, flags); pid = lxc_clone(do_start, &start_arg, flags);
if (pid < 0) { if (pid < 0) {
fprintf(stderr, "failed to clone\n"); fprintf(stderr, "Failed to clone\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -341,7 +376,7 @@ int main(int argc, char *argv[]) ...@@ -341,7 +376,7 @@ int main(int argc, char *argv[])
ret = snprintf(umap, 100, "%d %d 1\n" , *(start_arg.uid), getuid()); ret = snprintf(umap, 100, "%d %d 1\n" , *(start_arg.uid), getuid());
if (ret < 0 || ret >= 100) { if (ret < 0 || ret >= 100) {
close(start_arg.wait_fd); close(start_arg.wait_fd);
fprintf(stderr, "snprintf failed"); fprintf(stderr, "snprintf is failed\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -355,7 +390,7 @@ int main(int argc, char *argv[]) ...@@ -355,7 +390,7 @@ int main(int argc, char *argv[])
ret = write(start_arg.wait_fd, &wait_val, sizeof(wait_val)); ret = write(start_arg.wait_fd, &wait_val, sizeof(wait_val));
if (ret < 0) { if (ret < 0) {
close(start_arg.wait_fd); close(start_arg.wait_fd);
fprintf(stderr, "write to eventfd failed\n"); fprintf(stderr, "Failed to write eventfd\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -375,10 +410,10 @@ int main(int argc, char *argv[]) ...@@ -375,10 +410,10 @@ int main(int argc, char *argv[])
ret = snprintf(buf, 256, "%d", pid); ret = snprintf(buf, 256, "%d", pid);
if (ret < 0 || ret >= 256) if (ret < 0 || ret >= 256)
exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
execlp("ip", "ip", "link", "set", "dev", tmpif->mi_ifname, "netns", buf, (char *)NULL); execlp("ip", "ip", "link", "set", "dev", tmpif->mi_ifname, "netns", buf, (char *)NULL);
exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
if (wait_for_pid(pid) != 0) if (wait_for_pid(pid) != 0)
...@@ -392,7 +427,7 @@ int main(int argc, char *argv[]) ...@@ -392,7 +427,7 @@ int main(int argc, char *argv[])
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
if (wait_for_pid(pid) != 0) { if (wait_for_pid(pid) != 0) {
fprintf(stderr, "failed to wait for '%d'\n", pid); fprintf(stderr, "Failed to wait for '%d'\n", pid);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
......
...@@ -33,12 +33,14 @@ ...@@ -33,12 +33,14 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "tool_utils.h" #include "log.h"
lxc_log_define(lxc_wait, lxc);
static int my_checker(const struct lxc_arguments *args) static int my_checker(const struct lxc_arguments *args)
{ {
if (!args->states) { if (!args->states) {
lxc_error(args, "missing state option to wait for."); ERROR("Missing state option to wait for");
return -1; return -1;
} }
...@@ -107,7 +109,7 @@ int main(int argc, char *argv[]) ...@@ -107,7 +109,7 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
if (!c->may_control(c)) { if (!c->may_control(c)) {
lxc_error(&my_args, "Insufficent privileges to control %s", c->name); ERROR("Insufficent privileges to control %s", c->name);
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -116,14 +118,14 @@ int main(int argc, char *argv[]) ...@@ -116,14 +118,14 @@ int main(int argc, char *argv[])
c->clear_config(c); c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) { if (!c->load_config(c, my_args.rcfile)) {
lxc_error(&my_args, "Failed to load rcfile"); ERROR("Failed to load rcfile");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
c->configfile = strdup(my_args.rcfile); c->configfile = strdup(my_args.rcfile);
if (!c->configfile) { if (!c->configfile) {
lxc_error(&my_args, "Out of memory setting new config filename"); ERROR("Out of memory setting new config filename");
lxc_container_put(c); lxc_container_put(c);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
......
/*
* 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 */
/* liblxcapi
*
* Copyright © 2018 Christian Brauner <christian.brauner@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 "config.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <lxc/lxccontainer.h>
#include "tool_list.h"
#define TOOL_MAXPATHLEN 4096
#define TOOL_NUMSTRLEN64 21
#ifndef CLONE_PARENT_SETTID
#define CLONE_PARENT_SETTID 0x00100000
#endif
#ifndef CLONE_CHILD_CLEARTID
#define CLONE_CHILD_CLEARTID 0x00200000
#endif
#ifndef CLONE_CHILD_SETTID
#define CLONE_CHILD_SETTID 0x01000000
#endif
#ifndef CLONE_VFORK
#define CLONE_VFORK 0x00004000
#endif
#ifndef CLONE_THREAD
#define CLONE_THREAD 0x00010000
#endif
#ifndef CLONE_SETTLS
#define CLONE_SETTLS 0x00080000
#endif
#ifndef CLONE_VM
#define CLONE_VM 0x00000100
#endif
#ifndef CLONE_FILES
#define CLONE_FILES 0x00000400
#endif
#ifndef CLONE_FS
# define CLONE_FS 0x00000200
#endif
#ifndef CLONE_NEWNS
# define CLONE_NEWNS 0x00020000
#endif
#ifndef CLONE_NEWCGROUP
# define CLONE_NEWCGROUP 0x02000000
#endif
#ifndef CLONE_NEWUTS
# define CLONE_NEWUTS 0x04000000
#endif
#ifndef CLONE_NEWIPC
# define CLONE_NEWIPC 0x08000000
#endif
#ifndef CLONE_NEWUSER
# define CLONE_NEWUSER 0x10000000
#endif
#ifndef CLONE_NEWPID
# define CLONE_NEWPID 0x20000000
#endif
#ifndef CLONE_NEWNET
# define CLONE_NEWNET 0x40000000
#endif
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);
extern int lxc_fill_namespace_flags(char *flaglist, int *flags);
#if !defined(__NR_setns) && !defined(__NR_set_ns)
#if defined(__x86_64__)
#define __NR_setns 308
#elif defined(__i386__)
#define __NR_setns 346
#elif defined(__arm__)
#define __NR_setns 375
#elif defined(__aarch64__)
#define __NR_setns 375
#elif defined(__powerpc__)
#define __NR_setns 350
#elif defined(__s390__)
#define __NR_setns 339
#endif
#endif
/* Define setns() if missing from the C library */
#ifndef HAVE_SETNS
static inline int setns(int fd, int nstype)
{
#ifdef __NR_setns
return syscall(__NR_setns, fd, nstype);
#elif defined(__NR_set_ns)
return syscall(__NR_set_ns, fd, nstype);
#else
errno = ENOSYS;
return -1;
#endif
}
#endif
#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 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);
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 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);
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 bool 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);
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();
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 */
...@@ -159,7 +159,7 @@ static inline int setns(int fd, int nstype) ...@@ -159,7 +159,7 @@ static inline int setns(int fd, int nstype)
/* Define sethostname() if missing from the C library */ /* Define sethostname() if missing from the C library */
#ifndef HAVE_SETHOSTNAME #ifndef HAVE_SETHOSTNAME
static inline int sethostname(const char * name, size_t len) static inline int sethostname(const char *name, size_t len)
{ {
#ifdef __NR_sethostname #ifdef __NR_sethostname
return syscall(__NR_sethostname, name, len); return syscall(__NR_sethostname, name, len);
...@@ -392,8 +392,8 @@ extern int wait_for_pid(pid_t pid); ...@@ -392,8 +392,8 @@ extern int wait_for_pid(pid_t pid);
extern int lxc_wait_for_pid_status(pid_t pid); extern int lxc_wait_for_pid_status(pid_t pid);
/* send and receive buffers completely */ /* send and receive buffers completely */
extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count); extern ssize_t lxc_write_nointr(int fd, const void *buf, size_t count);
extern ssize_t lxc_read_nointr(int fd, void* buf, size_t count); extern ssize_t lxc_read_nointr(int fd, void *buf, size_t count);
extern ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count, extern ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count,
const void *expected_buf); const void *expected_buf);
#if HAVE_LIBGNUTLS #if HAVE_LIBGNUTLS
...@@ -404,7 +404,7 @@ extern int sha1sum_file(char *fnam, unsigned char *md_value); ...@@ -404,7 +404,7 @@ extern int sha1sum_file(char *fnam, unsigned char *md_value);
/* read and write whole files */ /* read and write whole files */
extern int lxc_write_to_file(const char *filename, const void *buf, extern int lxc_write_to_file(const char *filename, const void *buf,
size_t count, bool add_newline, mode_t mode); size_t count, bool add_newline, mode_t mode);
extern int lxc_read_from_file(const char *filename, void* buf, size_t count); extern int lxc_read_from_file(const char *filename, void *buf, size_t count);
/* convert variadic argument lists to arrays (for execl type argument lists) */ /* convert variadic argument lists to arrays (for execl type argument lists) */
extern char** lxc_va_arg_list_to_argv(va_list ap, size_t skip, int do_strdup); extern char** lxc_va_arg_list_to_argv(va_list ap, size_t skip, int do_strdup);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment