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