mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 08:12:20 +00:00
Merge pull request #2090 from brauner/2018-01-12/tools_remove_non_api_symbols
tools: remove non api symbols
This commit is contained in:
commit
f704a070d4
@ -934,9 +934,9 @@ AC_CONFIG_FILES([
|
||||
src/Makefile
|
||||
src/lxc/Makefile
|
||||
src/lxc/lxc.functions
|
||||
src/lxc/tools/lxc-checkconfig
|
||||
src/lxc/cmd/lxc-checkconfig
|
||||
src/lxc/cmd/lxc-update-config
|
||||
src/lxc/tools/lxc-start-ephemeral
|
||||
src/lxc/tools/lxc-update-config
|
||||
src/lxc/version.h
|
||||
src/python-lxc/Makefile
|
||||
|
||||
|
@ -4,7 +4,6 @@ pkginclude_HEADERS = \
|
||||
version.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
tools/arguments.h \
|
||||
attach.h \
|
||||
storage/storage.h \
|
||||
storage/aufs.h \
|
||||
@ -18,6 +17,9 @@ noinst_HEADERS = \
|
||||
storage/rsync.h \
|
||||
storage/zfs.h \
|
||||
storage/storage_utils.h \
|
||||
tools/arguments.h \
|
||||
tools/tool_utils.h \
|
||||
tools/tool_list.h \
|
||||
cgroups/cgroup.h \
|
||||
cgroups/cgroup_utils.h \
|
||||
caps.h \
|
||||
@ -60,7 +62,7 @@ endif
|
||||
endif
|
||||
|
||||
if !HAVE_GETSUBOPT
|
||||
noinst_HEADERS += ../include/getsubopt.h
|
||||
noinst_HEADERS += tools/include/getsubopt.h
|
||||
endif
|
||||
|
||||
sodir=$(libdir)
|
||||
@ -214,8 +216,8 @@ liblxc_la_LIBADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS)
|
||||
liblxc_la_CFLAGS += $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) $(NIH_DBUS_CFLAGS)
|
||||
endif
|
||||
|
||||
bin_SCRIPTS = tools/lxc-checkconfig \
|
||||
tools/lxc-update-config
|
||||
bin_SCRIPTS = cmd/lxc-checkconfig \
|
||||
cmd/lxc-update-config
|
||||
|
||||
EXTRA_DIST = \
|
||||
tools/lxc-top.lua
|
||||
@ -266,45 +268,47 @@ AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir)
|
||||
endif
|
||||
LDADD=liblxc.la @CAP_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
|
||||
|
||||
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
|
||||
init_lxc_SOURCES = lxc_init.c
|
||||
lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c
|
||||
lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c
|
||||
lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c
|
||||
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_usernsexec_SOURCES = tools/lxc_usernsexec.c tools/arguments.c
|
||||
lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c
|
||||
lxc_user_nic_SOURCES = lxc_user_nic.c namespace.c network.c tools/arguments.c
|
||||
lxc_monitord_SOURCES = lxc_monitord.c tools/arguments.c
|
||||
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
|
||||
|
||||
# Binaries shipping with liblxc
|
||||
init_lxc_SOURCES = cmd/lxc_init.c
|
||||
lxc_monitord_SOURCES = cmd/lxc_monitord.c
|
||||
lxc_user_nic_SOURCES = cmd/lxc_user_nic.c namespace.c network.c
|
||||
lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c
|
||||
|
||||
if ENABLE_DEPRECATED
|
||||
lxc_clone_SOURCES = tools/lxc_clone.c tools/arguments.c
|
||||
endif
|
||||
|
||||
if !HAVE_GETSUBOPT
|
||||
lxc_copy_SOURCES += ../include/getsubopt.c ../include/getsubopt.h
|
||||
lxc_copy_SOURCES += tools/include/getsubopt.c tools/include/getsubopt.h
|
||||
endif
|
||||
|
||||
if HAVE_STATIC_LIBCAP
|
||||
sbin_PROGRAMS += init.lxc.static
|
||||
|
||||
init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c parse.c namespace.c
|
||||
init_lxc_static_SOURCES = cmd/lxc_init.c error.c log.c initutils.c caps.c parse.c namespace.c
|
||||
|
||||
if !HAVE_GETLINE
|
||||
if HAVE_FGETLN
|
||||
|
@ -36,13 +36,13 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
#include <lxc/version.h>
|
||||
|
||||
#include "error.h"
|
||||
#include "initutils.h"
|
||||
#include "log.h"
|
||||
#include "namespace.h"
|
||||
#include "parse.h"
|
||||
#include "version.h"
|
||||
|
||||
/* option keys for long only options */
|
||||
#define OPT_USAGE 0x1000
|
@ -39,12 +39,13 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "af_unix.h"
|
||||
#include "log.h"
|
||||
#include "mainloop.h"
|
||||
#include "monitor.h"
|
||||
#include "utils.h"
|
||||
#include "lxccontainer.h"
|
||||
|
||||
#define CLIENTFDS_CHUNK 64
|
||||
|
@ -2485,47 +2485,6 @@ signed long lxc_config_parse_arch(const char *arch)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lxc_fill_elevated_privileges(char *flaglist, int *flags)
|
||||
{
|
||||
char *token, *saveptr = NULL;
|
||||
int i, aflag;
|
||||
struct {
|
||||
const char *token;
|
||||
int flag;
|
||||
} all_privs[] = {
|
||||
{ "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
|
||||
{ "CAP", LXC_ATTACH_DROP_CAPABILITIES },
|
||||
{ "LSM", LXC_ATTACH_LSM_EXEC },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
if (!flaglist) {
|
||||
/* For the sake of backward compatibility, drop all privileges
|
||||
* if none is specified.
|
||||
*/
|
||||
for (i = 0; all_privs[i].token; i++)
|
||||
*flags |= all_privs[i].flag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
token = strtok_r(flaglist, "|", &saveptr);
|
||||
while (token) {
|
||||
aflag = -1;
|
||||
for (i = 0; all_privs[i].token; i++)
|
||||
if (!strcmp(all_privs[i].token, token))
|
||||
aflag = all_privs[i].flag;
|
||||
if (aflag < 0)
|
||||
return -1;
|
||||
|
||||
*flags |= aflag;
|
||||
|
||||
token = strtok_r(NULL, "|", &saveptr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write out a configuration file. */
|
||||
void write_config(FILE *fout, struct lxc_conf *c)
|
||||
{
|
||||
|
@ -92,8 +92,6 @@ extern int lxc_config_define_load(struct lxc_list *defines,
|
||||
/* needed for lxc-attach */
|
||||
extern signed long lxc_config_parse_arch(const char *arch);
|
||||
|
||||
extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
|
||||
|
||||
extern int lxc_clear_config_item(struct lxc_conf *c, const char *key);
|
||||
|
||||
extern void write_config(FILE *fout, struct lxc_conf *c);
|
||||
|
@ -22,6 +22,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
@ -32,10 +33,11 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
#include <lxc/version.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "utils.h"
|
||||
#include "version.h"
|
||||
#include "namespace.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static int build_shortopts(const struct option *a_options, char *a_shortopts,
|
||||
size_t a_size)
|
||||
@ -182,6 +184,13 @@ static int lxc_arguments_lxcpath_add(struct lxc_arguments *args,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void remove_trailing_slashes(char *p)
|
||||
{
|
||||
int l = strlen(p);
|
||||
while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
|
||||
p[l] = '\0';
|
||||
}
|
||||
|
||||
extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
@ -250,7 +259,7 @@ extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
|
||||
/* If no lxcpaths were given, use default */
|
||||
if (!args->lxcpath_cnt) {
|
||||
ret = lxc_arguments_lxcpath_add(
|
||||
args, lxc_global_config_value("lxc.lxcpath"));
|
||||
args, lxc_get_global_config_item("lxc.lxcpath"));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
599
src/lxc/tools/include/ifaddrs.c
Normal file
599
src/lxc/tools/include/ifaddrs.c
Normal file
@ -0,0 +1,599 @@
|
||||
/*
|
||||
Copyright (c) 2013, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ifaddrs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
typedef struct NetlinkList
|
||||
{
|
||||
struct NetlinkList *m_next;
|
||||
struct nlmsghdr *m_data;
|
||||
unsigned int m_size;
|
||||
} NetlinkList;
|
||||
|
||||
static int netlink_socket(void)
|
||||
{
|
||||
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_nl l_addr;
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return l_socket;
|
||||
}
|
||||
|
||||
static int netlink_send(int p_socket, int p_request)
|
||||
{
|
||||
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
|
||||
memset(l_buffer, 0, sizeof(l_buffer));
|
||||
struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer;
|
||||
struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
|
||||
|
||||
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
|
||||
l_hdr->nlmsg_type = p_request;
|
||||
l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
l_hdr->nlmsg_pid = 0;
|
||||
l_hdr->nlmsg_seq = p_socket;
|
||||
l_msg->rtgen_family = AF_UNSPEC;
|
||||
|
||||
struct sockaddr_nl l_addr;
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
|
||||
}
|
||||
|
||||
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
|
||||
{
|
||||
struct msghdr l_msg;
|
||||
struct iovec l_iov = { p_buffer, p_len };
|
||||
struct sockaddr_nl l_addr;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
l_msg.msg_name = (void *)&l_addr;
|
||||
l_msg.msg_namelen = sizeof(l_addr);
|
||||
l_msg.msg_iov = &l_iov;
|
||||
l_msg.msg_iovlen = 1;
|
||||
l_msg.msg_control = NULL;
|
||||
l_msg.msg_controllen = 0;
|
||||
l_msg.msg_flags = 0;
|
||||
int l_result = recvmsg(p_socket, &l_msg, 0);
|
||||
|
||||
if(l_result < 0)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(l_msg.msg_flags & MSG_TRUNC)
|
||||
{ // buffer was too small
|
||||
return -1;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
}
|
||||
|
||||
static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
|
||||
{
|
||||
size_t l_size = 4096;
|
||||
void *l_buffer = NULL;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
free(l_buffer);
|
||||
l_buffer = malloc(l_size);
|
||||
|
||||
int l_read = netlink_recv(p_socket, l_buffer, l_size);
|
||||
*p_size = l_read;
|
||||
if(l_read == -2)
|
||||
{
|
||||
free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
if(l_read >= 0)
|
||||
{
|
||||
pid_t l_pid = getpid();
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
*p_done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return l_buffer;
|
||||
}
|
||||
|
||||
l_size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
|
||||
{
|
||||
NetlinkList *l_item = malloc(sizeof(NetlinkList));
|
||||
l_item->m_next = NULL;
|
||||
l_item->m_data = p_data;
|
||||
l_item->m_size = p_size;
|
||||
return l_item;
|
||||
}
|
||||
|
||||
static void freeResultList(NetlinkList *p_list)
|
||||
{
|
||||
NetlinkList *l_cur;
|
||||
while(p_list)
|
||||
{
|
||||
l_cur = p_list;
|
||||
p_list = p_list->m_next;
|
||||
free(l_cur->m_data);
|
||||
free(l_cur);
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *getResultList(int p_socket, int p_request)
|
||||
{
|
||||
if(netlink_send(p_socket, p_request) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetlinkList *l_list = NULL;
|
||||
NetlinkList *l_end = NULL;
|
||||
int l_size;
|
||||
int l_done = 0;
|
||||
while(!l_done)
|
||||
{
|
||||
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
|
||||
if(!l_hdr)
|
||||
{ // error
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetlinkList *l_item = newListItem(l_hdr, l_size);
|
||||
if(!l_list)
|
||||
{
|
||||
l_list = l_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_end->m_next = l_item;
|
||||
}
|
||||
l_end = l_item;
|
||||
}
|
||||
return l_list;
|
||||
}
|
||||
|
||||
static size_t maxSize(size_t a, size_t b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
return sizeof(struct sockaddr_in);
|
||||
case AF_INET6:
|
||||
return sizeof(struct sockaddr_in6);
|
||||
case AF_PACKET:
|
||||
return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
|
||||
default:
|
||||
return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_PACKET:
|
||||
memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
|
||||
((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
|
||||
break;
|
||||
default:
|
||||
memcpy(p_dest->sa_data, p_data, p_size);
|
||||
break;
|
||||
}
|
||||
p_dest->sa_family = p_family;
|
||||
}
|
||||
|
||||
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
|
||||
{
|
||||
if(!*p_resultList)
|
||||
{
|
||||
*p_resultList = p_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ifaddrs *l_cur = *p_resultList;
|
||||
while(l_cur->ifa_next)
|
||||
{
|
||||
l_cur = l_cur->ifa_next;
|
||||
}
|
||||
l_cur->ifa_next = p_entry;
|
||||
}
|
||||
}
|
||||
|
||||
static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||
{
|
||||
struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
size_t l_dataSize = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
struct rtattr *l_rta;
|
||||
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
|
||||
break;
|
||||
case IFLA_IFNAME:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
l_dataSize += NLMSG_ALIGN(l_rtaSize);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize);
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = "";
|
||||
|
||||
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
char *l_addr = l_name + l_nameSize;
|
||||
char *l_data = l_addr + l_addrSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifi_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
|
||||
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
|
||||
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
|
||||
if(l_rta->rta_type == IFLA_ADDRESS)
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFLA_IFNAME:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
memcpy(l_data, l_rtaData, l_rtaDataSize);
|
||||
l_entry->ifa_data = l_data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
p_links[l_info->ifi_index - 1] = l_entry;
|
||||
}
|
||||
|
||||
static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||
{
|
||||
struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
|
||||
int l_addedNetmask = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
struct rtattr *l_rta;
|
||||
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
if(l_info->ifa_family == AF_PACKET)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_LOCAL:
|
||||
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
|
||||
{ // make room for netmask
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
l_addedNetmask = 1;
|
||||
}
|
||||
case IFA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name;
|
||||
|
||||
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
char *l_addr = l_name + l_nameSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_BROADCAST:
|
||||
case IFA_LOCAL:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
|
||||
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
if(l_info->ifa_family == AF_INET6)
|
||||
{
|
||||
if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
|
||||
{
|
||||
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
|
||||
}
|
||||
}
|
||||
|
||||
if(l_rta->rta_type == IFA_ADDRESS)
|
||||
{ // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
}
|
||||
else if(l_rta->rta_type == IFA_LOCAL)
|
||||
{
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = l_entry->ifa_addr;
|
||||
}
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFA_LABEL:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
|
||||
{
|
||||
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
|
||||
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
|
||||
char l_mask[16] = {0};
|
||||
unsigned i;
|
||||
for(i=0; i<(l_prefix/8); ++i)
|
||||
{
|
||||
l_mask[i] = 0xff;
|
||||
}
|
||||
if (l_prefix % 8) {
|
||||
l_mask[i] = 0xff << (8 - (l_prefix % 8));
|
||||
}
|
||||
|
||||
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
|
||||
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
}
|
||||
|
||||
static void interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||
{
|
||||
pid_t l_pid = getpid();
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||
{
|
||||
interpretLink(l_hdr, p_links, p_resultList);
|
||||
}
|
||||
else if(l_hdr->nlmsg_type == RTM_NEWADDR)
|
||||
{
|
||||
interpretAddr(l_hdr, p_links, p_resultList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList)
|
||||
{
|
||||
unsigned l_links = 0;
|
||||
pid_t l_pid = getpid();
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||
{
|
||||
++l_links;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return l_links;
|
||||
}
|
||||
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
if(!ifap)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*ifap = NULL;
|
||||
|
||||
int l_socket = netlink_socket();
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
|
||||
if(!l_linkResults)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
|
||||
if(!l_addrResults)
|
||||
{
|
||||
close(l_socket);
|
||||
freeResultList(l_linkResults);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
|
||||
struct ifaddrs *l_links[l_numLinks];
|
||||
memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
|
||||
|
||||
interpret(l_socket, l_linkResults, l_links, ifap);
|
||||
interpret(l_socket, l_addrResults, l_links, ifap);
|
||||
|
||||
freeResultList(l_linkResults);
|
||||
freeResultList(l_addrResults);
|
||||
close(l_socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void freeifaddrs(struct ifaddrs *ifa)
|
||||
{
|
||||
struct ifaddrs *l_cur;
|
||||
while(ifa)
|
||||
{
|
||||
l_cur = ifa;
|
||||
ifa = ifa->ifa_next;
|
||||
free(l_cur);
|
||||
}
|
||||
}
|
54
src/lxc/tools/include/ifaddrs.h
Normal file
54
src/lxc/tools/include/ifaddrs.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||
* to be included it must be included before this header file.
|
||||
*/
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int getifaddrs(struct ifaddrs **ifap);
|
||||
extern void freeifaddrs(struct ifaddrs *ifa);
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
@ -21,12 +21,12 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
@ -36,16 +36,8 @@
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "attach.h"
|
||||
#include "arguments.h"
|
||||
#include "caps.h"
|
||||
#include "conf.h"
|
||||
#include "confile.h"
|
||||
#include "console.h"
|
||||
#include "log.h"
|
||||
#include "list.h"
|
||||
#include "mainloop.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static const struct option my_longopts[] = {
|
||||
{"elevated-privileges", optional_argument, 0, 'e'},
|
||||
@ -290,7 +282,6 @@ int main(int argc, char *argv[])
|
||||
r = lxc_log_init(&log);
|
||||
if (r)
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
if (geteuid()) {
|
||||
if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
|
||||
|
@ -18,15 +18,17 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include "tool_list.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list);
|
||||
|
||||
@ -145,14 +147,13 @@ int lists_contain_common_entry(struct lxc_list *p1, struct lxc_list *p2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a variation of get_list below it.
|
||||
* This version allows two additional features.
|
||||
* If a list is passed to it, it adds to it.
|
||||
* It allows for empty entries (i.e. "group1,,group2") generating
|
||||
* and empty list entry.
|
||||
/* This is a variation of get_list below it. This version allows two additional
|
||||
* features. If a list is passed to it, it adds to it. It allows for empty
|
||||
* entries (i.e. "group1,,group2") generating and empty list entry.
|
||||
*/
|
||||
static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list) {
|
||||
static struct lxc_list *accumulate_list(char *input, char *delimiter,
|
||||
struct lxc_list *str_list)
|
||||
{
|
||||
char *workstr = NULL;
|
||||
char *workptr = NULL;
|
||||
char *next_ptr = NULL;
|
||||
@ -160,45 +161,33 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc
|
||||
struct lxc_list *workstr_list;
|
||||
|
||||
workstr = strdup(input);
|
||||
if (!workstr) {
|
||||
if (!workstr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
workstr_list = str_list;
|
||||
if ( ! workstr_list ) {
|
||||
if (!workstr_list) {
|
||||
workstr_list = malloc(sizeof(*workstr_list));
|
||||
lxc_list_init(workstr_list);
|
||||
}
|
||||
|
||||
for (workptr = workstr; workptr; workptr = next_ptr) {
|
||||
/*
|
||||
* We can't use strtok_r here because it collapses
|
||||
* multiple delimiters into 1 making empty fields
|
||||
* impossible...
|
||||
/* We can't use strtok_r here because it collapses multiple
|
||||
* delimiters into 1 making empty fields impossible...
|
||||
*/
|
||||
/* token = strtok_r(workptr, delimiter, &sptr); */
|
||||
next_ptr = strchr( workptr, *delimiter );
|
||||
|
||||
if( next_ptr ) {
|
||||
next_ptr = strchr(workptr, *delimiter);
|
||||
if (next_ptr)
|
||||
*next_ptr++ = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we'd like to check to see if this
|
||||
* group is already contained in the list and ignore
|
||||
* it if it is... This also helps us with any
|
||||
* corner cases where a string begins or ends with a
|
||||
* delimiter.
|
||||
/* At this point, we'd like to check to see if this group is
|
||||
* already contained in the list and ignore it if it is... This
|
||||
* also helps us with any corner cases where a string begins or
|
||||
* ends with a delimiter.
|
||||
*/
|
||||
|
||||
if ( list_contains_entry( workptr, workstr_list ) ) {
|
||||
if ( *workptr ) {
|
||||
fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr );
|
||||
fflush(stderr);
|
||||
} else {
|
||||
fprintf(stderr, "Duplicate NULL group in list - ignoring\n" );
|
||||
fflush(stderr);
|
||||
}
|
||||
if (list_contains_entry(workptr, workstr_list)) {
|
||||
if (*workptr)
|
||||
fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr);
|
||||
else
|
||||
fprintf(stderr, "Duplicate NULL group in list - ignoring\n");
|
||||
} else {
|
||||
worklist = malloc(sizeof(*worklist));
|
||||
if (!worklist)
|
||||
@ -219,7 +208,8 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc
|
||||
return workstr_list;
|
||||
}
|
||||
|
||||
static struct lxc_list *get_list(char *input, char *delimiter) {
|
||||
static struct lxc_list *get_list(char *input, char *delimiter)
|
||||
{
|
||||
char *workstr = NULL;
|
||||
char *workptr = NULL;
|
||||
char *sptr = NULL;
|
||||
@ -236,11 +226,10 @@ static struct lxc_list *get_list(char *input, char *delimiter) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (workptr = workstr;;workptr = NULL) {
|
||||
for (workptr = workstr;; workptr = NULL) {
|
||||
token = strtok_r(workptr, delimiter, &sptr);
|
||||
if (!token) {
|
||||
if (!token)
|
||||
break;
|
||||
}
|
||||
|
||||
worklist = malloc(sizeof(*worklist));
|
||||
if (!worklist)
|
||||
@ -260,16 +249,17 @@ static struct lxc_list *get_list(char *input, char *delimiter) {
|
||||
return workstr_list;
|
||||
}
|
||||
|
||||
static struct lxc_list *get_config_list(struct lxc_container *c, char *key) {
|
||||
static struct lxc_list *get_config_list(struct lxc_container *c, char *key)
|
||||
{
|
||||
int len = 0;
|
||||
char* value = NULL;
|
||||
char *value = NULL;
|
||||
struct lxc_list *config_list = NULL;
|
||||
|
||||
len = c->get_config_item(c, key, NULL, 0);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
|
||||
value = (char*) malloc(sizeof(char)*len + 1);
|
||||
value = (char *)malloc(sizeof(char) * len + 1);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -289,16 +279,16 @@ static struct lxc_list *get_config_list(struct lxc_container *c, char *key) {
|
||||
return config_list;
|
||||
}
|
||||
|
||||
static int get_config_integer(struct lxc_container *c, char *key) {
|
||||
int len = 0;
|
||||
int ret = 0;
|
||||
char* value = NULL;
|
||||
static int get_config_integer(struct lxc_container *c, char *key)
|
||||
{
|
||||
int len = 0, ret = 0;
|
||||
char *value = NULL;
|
||||
|
||||
len = c->get_config_item(c, key, NULL, 0);
|
||||
if (len < 0)
|
||||
return 0;
|
||||
|
||||
value = (char*) malloc(sizeof(char)*len + 1);
|
||||
value = (char *)malloc(sizeof(char) * len + 1);
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
|
||||
@ -315,7 +305,8 @@ static int get_config_integer(struct lxc_container *c, char *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cmporder(const void *p1, const void *p2) {
|
||||
static int cmporder(const void *p1, const void *p2)
|
||||
{
|
||||
struct lxc_container *c1 = *(struct lxc_container **)p1;
|
||||
struct lxc_container *c2 = *(struct lxc_container **)p2;
|
||||
|
||||
@ -324,33 +315,33 @@ static int cmporder(const void *p1, const void *p2) {
|
||||
|
||||
if (c1_order == c2_order)
|
||||
return strcmp(c1->name, c2->name);
|
||||
else
|
||||
return (c1_order - c2_order);
|
||||
|
||||
return (c1_order - c2_order);
|
||||
}
|
||||
|
||||
static int toss_list( struct lxc_list *c_groups_list ) {
|
||||
static int toss_list(struct lxc_list *c_groups_list)
|
||||
{
|
||||
struct lxc_list *it, *next;
|
||||
|
||||
if (c_groups_list) {
|
||||
lxc_list_for_each_safe(it, c_groups_list, next) {
|
||||
lxc_list_del(it);
|
||||
free(it->elem);
|
||||
free(it);
|
||||
}
|
||||
free(c_groups_list);
|
||||
if (!c_groups_list)
|
||||
return 1;
|
||||
|
||||
lxc_list_for_each_safe(it, c_groups_list, next) {
|
||||
lxc_list_del(it);
|
||||
free(it->elem);
|
||||
free(it);
|
||||
}
|
||||
free(c_groups_list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
int count = 0, i = 0, ret = 0;
|
||||
struct lxc_list *cmd_group;
|
||||
struct lxc_container **containers = NULL;
|
||||
struct lxc_list **c_groups_lists = NULL;
|
||||
struct lxc_list *cmd_group;
|
||||
struct lxc_log log;
|
||||
|
||||
if (lxc_arguments_parse(&my_args, argc, argv))
|
||||
@ -365,7 +356,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
@ -375,36 +365,29 @@ int main(int argc, char *argv[])
|
||||
if (count < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (!my_args.all) {
|
||||
/* Allocate an array for our container group lists */
|
||||
/* Allocate an array for our container group lists */
|
||||
if (!my_args.all)
|
||||
c_groups_lists = calloc( count, sizeof( struct lxc_list * ) );
|
||||
}
|
||||
|
||||
qsort(&containers[0], count, sizeof(struct lxc_container *), cmporder);
|
||||
|
||||
if (cmd_groups_list && my_args.all) {
|
||||
if (cmd_groups_list && my_args.all)
|
||||
fprintf(stderr, "Specifying -a (all) with -g (groups) doesn't make sense. All option overrides.\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
if (!cmd_groups_list) {
|
||||
/*
|
||||
* We need a default cmd_groups_list even for the -a
|
||||
* case in order to force a pass through the loop for
|
||||
* the NULL group. This, someday, could be taken from
|
||||
* a config file somewhere...
|
||||
*/
|
||||
/* We need a default cmd_groups_list even for the -a
|
||||
* case in order to force a pass through the loop for
|
||||
* the NULL group. This, someday, could be taken from
|
||||
* a config file somewhere...
|
||||
*/
|
||||
if (!cmd_groups_list)
|
||||
cmd_groups_list = accumulate_list( "" , ",", NULL );
|
||||
}
|
||||
|
||||
lxc_list_for_each(cmd_group, cmd_groups_list) {
|
||||
|
||||
/*
|
||||
* Prograpmmers Note:
|
||||
* Because we may take several passes through the container list
|
||||
* We'll switch on if the container pointer is NULL and if we process a
|
||||
* container (run it or decide to ignore it) and call lxc_container_put
|
||||
* then we'll NULL it out and not check it again.
|
||||
/* Because we may take several passes through the container list
|
||||
* We'll switch on if the container pointer is NULL and if we
|
||||
* process a container (run it or decide to ignore it) and call
|
||||
* lxc_container_put then we'll NULL it out and not check it
|
||||
* again.
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
struct lxc_container *c = containers[i];
|
||||
@ -413,10 +396,9 @@ int main(int argc, char *argv[])
|
||||
/* Skip - must have been already processed */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We haven't loaded the container groups yet so
|
||||
* these next two checks don't need to free them
|
||||
* if they fail. They'll fail on the first pass.
|
||||
/* We haven't loaded the container groups yet so these
|
||||
* next two checks don't need to free them if they fail.
|
||||
* They'll fail on the first pass.
|
||||
*/
|
||||
if (!c->may_control(c)) {
|
||||
/* We're done with this container */
|
||||
@ -443,8 +425,10 @@ int main(int argc, char *argv[])
|
||||
ret = list_contains_entry(cmd_group->elem, c_groups_lists[i]);
|
||||
|
||||
if ( ret == 0 ) {
|
||||
/* Not in the target group this pass */
|
||||
/* Leave in the list for subsequent passes */
|
||||
/* Not in the target group this pass so
|
||||
* leave in the list for subsequent
|
||||
* passes.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -468,8 +452,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (my_args.hardstop) {
|
||||
} else if (my_args.hardstop) {
|
||||
/* Kill the container */
|
||||
if (c->is_running(c)) {
|
||||
if (my_args.list) {
|
||||
@ -483,8 +466,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (my_args.reboot) {
|
||||
} else if (my_args.reboot) {
|
||||
/* Reboot the container */
|
||||
if (c->is_running(c)) {
|
||||
if (my_args.list) {
|
||||
@ -501,8 +483,7 @@ int main(int argc, char *argv[])
|
||||
sleep(get_config_integer(c, "lxc.start.delay"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* Start the container */
|
||||
if (!c->is_running(c)) {
|
||||
if (my_args.list) {
|
||||
@ -526,9 +507,8 @@ int main(int argc, char *argv[])
|
||||
* then we're done with this container... We can dump any
|
||||
* c_groups_list and the container itself.
|
||||
*/
|
||||
if ( lxc_container_put(c) > 0 ) {
|
||||
if ( lxc_container_put(c) > 0 )
|
||||
containers[i] = NULL;
|
||||
}
|
||||
if ( c_groups_lists ) {
|
||||
toss_list(c_groups_lists[i]);
|
||||
c_groups_lists[i] = NULL;
|
||||
@ -539,12 +519,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* clean up any lingering detritus */
|
||||
for (i = 0; i < count; i++) {
|
||||
if ( containers[i] ) {
|
||||
if (containers[i])
|
||||
lxc_container_put(containers[i]);
|
||||
}
|
||||
if ( c_groups_lists && c_groups_lists[i] ) {
|
||||
|
||||
if (c_groups_lists && c_groups_lists[i])
|
||||
toss_list(c_groups_lists[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(c_groups_lists);
|
||||
|
@ -21,17 +21,18 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "log.h"
|
||||
#include "lxc.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static int my_checker(const struct lxc_arguments* args)
|
||||
{
|
||||
@ -39,6 +40,7 @@ static int my_checker(const struct lxc_arguments* args)
|
||||
lxc_error(args, "missing state object");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -83,7 +85,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
@ -130,8 +131,8 @@ int main(int argc, char *argv[])
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
char buffer[MAXPATHLEN];
|
||||
int ret = c->get_cgroup_item(c, state_object, buffer, MAXPATHLEN);
|
||||
char buffer[TOOL_MAXPATHLEN];
|
||||
int ret = c->get_cgroup_item(c, state_object, buffer, TOOL_MAXPATHLEN);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to retrieve value of '%s' for '%s:%s'\n",
|
||||
state_object, my_args.lxcpath[0], my_args.name);
|
||||
|
@ -1,5 +1,4 @@
|
||||
/*
|
||||
*
|
||||
* Copyright © 2014 Tycho Andersen <tycho.andersen@canonical.com>.
|
||||
* Copyright © 2014 Canonical Ltd.
|
||||
*
|
||||
@ -17,19 +16,18 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
#include "lxc.h"
|
||||
#include "arguments.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static char *checkpoint_dir = NULL;
|
||||
static bool stop = false;
|
||||
@ -253,8 +251,6 @@ int main(int argc, char *argv[])
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
|
||||
|
@ -17,25 +17,19 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
#include "lxc.h"
|
||||
#include "conf.h"
|
||||
#include "state.h"
|
||||
|
||||
/* we pass fssize in bytes */
|
||||
static uint64_t get_fssize(char *s)
|
||||
{
|
||||
@ -43,30 +37,33 @@ static uint64_t get_fssize(char *s)
|
||||
char *end;
|
||||
|
||||
ret = strtoull(s, &end, 0);
|
||||
if (end == s)
|
||||
{
|
||||
fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s);
|
||||
if (end == s) {
|
||||
fprintf(stderr,
|
||||
"Invalid blockdev size '%s', using default size\n", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (isblank(*end))
|
||||
end++;
|
||||
if (*end == '\0')
|
||||
if (*end == '\0') {
|
||||
ret *= 1024ULL * 1024ULL; /* MB by default */
|
||||
else if (*end == 'b' || *end == 'B')
|
||||
} else if (*end == 'b' || *end == 'B') {
|
||||
ret *= 1ULL;
|
||||
else if (*end == 'k' || *end == 'K')
|
||||
} else if (*end == 'k' || *end == 'K') {
|
||||
ret *= 1024ULL;
|
||||
else if (*end == 'm' || *end == 'M')
|
||||
} else if (*end == 'm' || *end == 'M') {
|
||||
ret *= 1024ULL * 1024ULL;
|
||||
else if (*end == 'g' || *end == 'G')
|
||||
} else if (*end == 'g' || *end == 'G') {
|
||||
ret *= 1024ULL * 1024ULL * 1024ULL;
|
||||
else if (*end == 't' || *end == 'T')
|
||||
} else if (*end == 't' || *end == 'T') {
|
||||
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', "
|
||||
"using default size\n",
|
||||
*end, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -124,42 +121,76 @@ int main(int argc, char *argv[])
|
||||
if (argc < 3)
|
||||
usage(argv[0]);
|
||||
|
||||
while (1) {
|
||||
c = getopt_long(argc, argv, "sB:L:o:n:v:KMHp:P:Rt:h", options, &option_index);
|
||||
while (true) {
|
||||
c = getopt_long(argc, argv, "sB:L:o:n:v:KMHp:P:Rt:h", options,
|
||||
&option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
switch (c) {
|
||||
case 's': snapshot = 1; break;
|
||||
case 'B': bdevtype = optarg; break;
|
||||
case 'L': newsize = get_fssize(optarg); break;
|
||||
case 'o': orig = optarg; break;
|
||||
case 'n': new = optarg; break;
|
||||
case 'v': vgname = optarg; break;
|
||||
case 'K': keepname = 1; break;
|
||||
case 'M': keepmac = 1; break;
|
||||
case 'p': lxcpath = optarg; break;
|
||||
case 'P': newpath = optarg; break;
|
||||
case 'R': rename = 1; break;
|
||||
case 't': fstype = optarg; break;
|
||||
case 'h': usage(argv[0]);
|
||||
default: break;
|
||||
case 's':
|
||||
snapshot = 1;
|
||||
break;
|
||||
case 'B':
|
||||
bdevtype = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
newsize = get_fssize(optarg);
|
||||
break;
|
||||
case 'o':
|
||||
orig = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
new = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
vgname = optarg;
|
||||
break;
|
||||
case 'K':
|
||||
keepname = 1;
|
||||
break;
|
||||
case 'M':
|
||||
keepmac = 1;
|
||||
break;
|
||||
case 'p':
|
||||
lxcpath = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
newpath = optarg;
|
||||
break;
|
||||
case 'R':
|
||||
rename = 1;
|
||||
break;
|
||||
case 't':
|
||||
fstype = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optind < argc && !orig)
|
||||
|
||||
if (optind < argc && !orig)
|
||||
orig = argv[optind++];
|
||||
if (optind < argc && !new)
|
||||
|
||||
if (optind < argc && !new)
|
||||
new = argv[optind++];
|
||||
|
||||
/* arguments for the clone hook */
|
||||
if (optind < argc)
|
||||
/* arguments for the clone hook */
|
||||
args = &argv[optind];
|
||||
|
||||
if (!new || !orig) {
|
||||
printf("Error: you must provide orig and new names\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
if (snapshot) flags |= LXC_CLONE_SNAPSHOT;
|
||||
if (keepname) flags |= LXC_CLONE_KEEPNAME;
|
||||
if (keepmac) flags |= LXC_CLONE_KEEPMACADDR;
|
||||
if (snapshot)
|
||||
flags |= LXC_CLONE_SNAPSHOT;
|
||||
if (keepname)
|
||||
flags |= LXC_CLONE_KEEPNAME;
|
||||
if (keepmac)
|
||||
flags |= LXC_CLONE_KEEPMACADDR;
|
||||
|
||||
/* vgname and fstype could be supported by sending them through the
|
||||
* bdevdata. However, they currently are not yet. I'm not convinced
|
||||
@ -201,8 +232,7 @@ int main(int argc, char *argv[])
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize,
|
||||
args);
|
||||
c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize, args);
|
||||
if (c2 == NULL) {
|
||||
lxc_container_put(c1);
|
||||
fprintf(stderr, "clone failed\n");
|
||||
|
@ -23,8 +23,6 @@
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
struct lxc_config_items {
|
||||
char *name;
|
||||
};
|
||||
|
@ -39,12 +39,7 @@
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "commands.h"
|
||||
#include "error.h"
|
||||
#include "log.h"
|
||||
#include "lxc.h"
|
||||
#include "mainloop.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static char etoc(const char *expr)
|
||||
{
|
||||
@ -115,7 +110,6 @@ int main(int argc, char *argv[])
|
||||
ret = lxc_log_init(&log);
|
||||
if (ret)
|
||||
return EXIT_FAILURE;
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
|
@ -17,37 +17,29 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "attach.h"
|
||||
#include "log.h"
|
||||
#include "confile.h"
|
||||
#include "arguments.h"
|
||||
#include "lxc.h"
|
||||
#include "conf.h"
|
||||
#include "state.h"
|
||||
#include "storage.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
#ifndef HAVE_GETSUBOPT
|
||||
#include <../include/getsubopt.h>
|
||||
#include "include/getsubopt.h"
|
||||
#endif
|
||||
|
||||
enum mnttype {
|
||||
@ -186,7 +178,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(ret);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
@ -273,17 +264,17 @@ static struct mnts *add_mnt(struct mnts **mnts, unsigned int *num, enum mnttype
|
||||
|
||||
static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_arguments *arg)
|
||||
{
|
||||
char upperdir[MAXPATHLEN];
|
||||
char workdir[MAXPATHLEN];
|
||||
char upperdir[TOOL_MAXPATHLEN];
|
||||
char workdir[TOOL_MAXPATHLEN];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
struct mnts *m = NULL;
|
||||
|
||||
for (i = 0, m = mnts; i < num; i++, m++) {
|
||||
if ((m->mnt_type == LXC_MNT_OVL) || (m->mnt_type == LXC_MNT_AUFS)) {
|
||||
ret = snprintf(upperdir, MAXPATHLEN, "%s/%s/delta#XXXXXX",
|
||||
ret = snprintf(upperdir, TOOL_MAXPATHLEN, "%s/%s/delta#XXXXXX",
|
||||
arg->newpath, arg->newname);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
|
||||
return -1;
|
||||
if (!mkdtemp(upperdir))
|
||||
return -1;
|
||||
@ -293,9 +284,9 @@ static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_argu
|
||||
}
|
||||
|
||||
if (m->mnt_type == LXC_MNT_OVL) {
|
||||
ret = snprintf(workdir, MAXPATHLEN, "%s/%s/work#XXXXXX",
|
||||
ret = snprintf(workdir, TOOL_MAXPATHLEN, "%s/%s/work#XXXXXX",
|
||||
arg->newpath, arg->newname);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
|
||||
return -1;
|
||||
if (!mkdtemp(workdir))
|
||||
return -1;
|
||||
@ -400,19 +391,19 @@ static int do_clone(struct lxc_container *c, char *newname, char *newpath,
|
||||
static int do_clone_ephemeral(struct lxc_container *c,
|
||||
struct lxc_arguments *arg, char **args, int flags)
|
||||
{
|
||||
char *bdev;
|
||||
char *premount;
|
||||
char randname[MAXPATHLEN];
|
||||
char randname[TOOL_MAXPATHLEN];
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
bool bret = true, started = false;
|
||||
char *tmp_buf = randname;
|
||||
struct lxc_container *clone;
|
||||
lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
|
||||
attach_options.env_policy = LXC_ATTACH_CLEAR_ENV;
|
||||
|
||||
if (!arg->newname) {
|
||||
ret = snprintf(randname, MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
ret = snprintf(randname, TOOL_MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name);
|
||||
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
|
||||
return -1;
|
||||
if (!mkdtemp(randname))
|
||||
return -1;
|
||||
@ -429,12 +420,6 @@ static int do_clone_ephemeral(struct lxc_container *c,
|
||||
return -1;
|
||||
|
||||
if (arg->tmpfs) {
|
||||
bdev = c->lxc_conf->rootfs.bdev_type;
|
||||
if (bdev && strcmp(bdev, "dir")) {
|
||||
fprintf(stderr, "Cannot currently use tmpfs with %s storage backend.\n", bdev);
|
||||
goto destroy_and_put;
|
||||
}
|
||||
|
||||
premount = mount_tmpfs(arg->name, arg->newname, arg->newpath, arg);
|
||||
if (!premount)
|
||||
goto destroy_and_put;
|
||||
@ -501,7 +486,8 @@ static int do_clone_ephemeral(struct lxc_container *c,
|
||||
destroy_and_put:
|
||||
if (started)
|
||||
clone->shutdown(clone, -1);
|
||||
if (!started || clone->lxc_conf->ephemeral != 1)
|
||||
ret = clone->get_config_item(clone, "lxc.ephemeral", tmp_buf, TOOL_MAXPATHLEN);
|
||||
if (ret > 0 && strcmp(tmp_buf, "0"))
|
||||
clone->destroy(clone);
|
||||
free_mnts();
|
||||
lxc_container_put(clone);
|
||||
|
@ -22,16 +22,14 @@
|
||||
#include <libgen.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <lxc/lxccontainer.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "log.h"
|
||||
#include "lxc.h"
|
||||
#include "storage.h"
|
||||
#include "storage_utils.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static uint64_t get_fssize(char *s)
|
||||
{
|
||||
@ -203,6 +201,23 @@ static bool validate_bdev_args(struct lxc_arguments *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_valid_storage_type(const char *type)
|
||||
{
|
||||
if (strcmp(type, "dir") == 0 ||
|
||||
strcmp(type, "btrfs") == 0 ||
|
||||
strcmp(type, "aufs") == 0 ||
|
||||
strcmp(type, "loop") == 0 ||
|
||||
strcmp(type, "lvm") == 0 ||
|
||||
strcmp(type, "nbd") == 0 ||
|
||||
strcmp(type, "overlay") == 0 ||
|
||||
strcmp(type, "overlayfs") == 0 ||
|
||||
strcmp(type, "rbd") == 0 ||
|
||||
strcmp(type, "zfs") == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct lxc_container *c;
|
||||
@ -225,7 +240,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
@ -286,7 +300,7 @@ int main(int argc, char *argv[])
|
||||
if (my_args.configfile)
|
||||
c->load_config(c, my_args.configfile);
|
||||
else
|
||||
c->load_config(c, lxc_global_config_value("lxc.default_config"));
|
||||
c->load_config(c, lxc_get_global_config_item("lxc.default_config"));
|
||||
|
||||
if (my_args.fstype)
|
||||
spec.fstype = my_args.fstype;
|
||||
|
@ -18,19 +18,18 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "log.h"
|
||||
#include "lxc.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static int my_parser(struct lxc_arguments* args, int c, char* arg);
|
||||
static bool quiet;
|
||||
@ -83,7 +82,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
if (my_args.quiet)
|
||||
quiet = true;
|
||||
|
||||
@ -155,11 +154,11 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
|
||||
static bool do_destroy(struct lxc_container *c)
|
||||
{
|
||||
bool bret = true;
|
||||
char path[MAXPATHLEN];
|
||||
char path[TOOL_MAXPATHLEN];
|
||||
|
||||
/* First check whether the container has dependent clones or snapshots. */
|
||||
int ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
int ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
|
||||
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
|
||||
return false;
|
||||
|
||||
if (file_exists(path)) {
|
||||
@ -168,8 +167,8 @@ static bool do_destroy(struct lxc_container *c)
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
|
||||
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
|
||||
return false;
|
||||
|
||||
if (rmdir(path) < 0 && errno != ENOENT) {
|
||||
@ -189,8 +188,13 @@ static bool do_destroy(struct lxc_container *c)
|
||||
|
||||
/* If the container was ephemeral we have already removed it when we
|
||||
* stopped it. */
|
||||
if (c->is_defined(c) && !c->lxc_conf->ephemeral)
|
||||
bret = c->destroy(c);
|
||||
if (c->is_defined(c)) {
|
||||
char buf[256];
|
||||
ret = c->get_config_item(c, "lxc.ephemeral", buf, 256);
|
||||
if (ret > 0 && strcmp(buf, "0") == 0) {
|
||||
bret = c->destroy(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bret) {
|
||||
if (!quiet)
|
||||
@ -206,7 +210,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
|
||||
struct lxc_container *c1;
|
||||
struct stat fbuf;
|
||||
bool bret = false;
|
||||
char path[MAXPATHLEN];
|
||||
char path[TOOL_MAXPATHLEN];
|
||||
char *buf = NULL;
|
||||
char *lxcpath = NULL;
|
||||
char *lxcname = NULL;
|
||||
@ -216,8 +220,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
|
||||
int counter = 0;
|
||||
|
||||
/* Destroy clones. */
|
||||
ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
|
||||
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
|
||||
return false;
|
||||
|
||||
fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
@ -268,8 +272,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
|
||||
}
|
||||
|
||||
/* Destroy snapshots located in the containers snap/ folder. */
|
||||
ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
ret = snprintf(path, TOOL_MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
|
||||
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
|
||||
return false;
|
||||
|
||||
if (rmdir(path) < 0 && errno != ENOENT)
|
||||
|
@ -18,25 +18,24 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "lxc.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "arguments.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
#if HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h>
|
||||
#else
|
||||
#include <../include/ifaddrs.h>
|
||||
#include "include/ifaddrs.h"
|
||||
#endif
|
||||
|
||||
static const struct option my_longopts[] = {
|
||||
@ -123,7 +122,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
goto err;
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
|
@ -20,6 +20,7 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
@ -35,19 +36,15 @@
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "caps.h"
|
||||
#include "conf.h"
|
||||
#include "config.h"
|
||||
#include "confile.h"
|
||||
#include "log.h"
|
||||
#include "lxc.h"
|
||||
#include "start.h"
|
||||
#include "utils.h"
|
||||
#include "tool_list.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static struct lxc_list defines;
|
||||
|
||||
static int my_parser(struct lxc_arguments* args, int c, char* arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (c) {
|
||||
case 'd':
|
||||
args->daemonize = 1;
|
||||
@ -56,7 +53,9 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
|
||||
args->rcfile = arg;
|
||||
break;
|
||||
case 's':
|
||||
return lxc_config_define_add(&defines, arg);
|
||||
ret = lxc_config_define_add(&defines, arg);
|
||||
if (ret < 0)
|
||||
lxc_config_define_free(&defines);
|
||||
break;
|
||||
case 'u':
|
||||
if (lxc_safe_uint(arg, &args->uid) < 0)
|
||||
@ -114,14 +113,17 @@ Options :\n\
|
||||
.daemonize = 0,
|
||||
};
|
||||
|
||||
static bool set_argv(struct lxc_conf *conf, struct lxc_arguments *args)
|
||||
static bool set_argv(struct lxc_container *c, struct lxc_arguments *args)
|
||||
{
|
||||
int ret;
|
||||
char buf[TOOL_MAXPATHLEN];
|
||||
char **components, **p;
|
||||
|
||||
if (!conf->execute_cmd)
|
||||
ret = c->get_config_item(c, "lxc.execute.cmd", buf, TOOL_MAXPATHLEN);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
components = lxc_string_split_quoted(conf->execute_cmd);
|
||||
components = lxc_string_split_quoted(buf);
|
||||
if (!components)
|
||||
return false;
|
||||
|
||||
@ -156,7 +158,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
@ -189,24 +190,50 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (my_args.argc == 0) {
|
||||
if (!set_argv(c->lxc_conf, &my_args)) {
|
||||
if (!set_argv(c, &my_args)) {
|
||||
fprintf(stderr, "missing command to execute!\n");
|
||||
lxc_container_put(c);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
ret = lxc_config_define_load(&defines, c->lxc_conf);
|
||||
ret = lxc_config_define_load(&defines, c);
|
||||
if (ret) {
|
||||
lxc_container_put(c);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (my_args.uid)
|
||||
c->lxc_conf->init_uid = my_args.uid;
|
||||
if (my_args.uid) {
|
||||
char buf[256];
|
||||
|
||||
if (my_args.gid)
|
||||
c->lxc_conf->init_gid = my_args.gid;
|
||||
ret = snprintf(buf, 256, "%d", my_args.uid);
|
||||
if (ret < 0 || (size_t)ret >= 256) {
|
||||
lxc_container_put(c);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = c->set_config_item(c, "lxc.init.uid", buf);
|
||||
if (ret < 0) {
|
||||
lxc_container_put(c);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (my_args.gid) {
|
||||
char buf[256];
|
||||
|
||||
ret = snprintf(buf, 256, "%d", my_args.gid);
|
||||
if (ret < 0 || (size_t)ret >= 256) {
|
||||
lxc_container_put(c);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = c->set_config_item(c, "lxc.init.gid", buf);
|
||||
if (ret < 0) {
|
||||
lxc_container_put(c);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lxc_setup_shared_ns(&my_args, c)) {
|
||||
lxc_container_put(c);
|
||||
|
@ -20,17 +20,17 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "lxc.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "arguments.h"
|
||||
|
||||
static const struct option my_longopts[] = {
|
||||
@ -72,7 +72,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
|
@ -21,21 +21,20 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#define _GNU_SOURCE
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "lxc.h"
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include "commands.h"
|
||||
#include "arguments.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static bool ips;
|
||||
static bool state;
|
||||
@ -205,7 +204,7 @@ static void print_stats(struct lxc_container *c)
|
||||
char buf[4096];
|
||||
|
||||
ret = c->get_cgroup_item(c, "cpuacct.usage", buf, sizeof(buf));
|
||||
if (ret > 0 && ret < sizeof(buf)) {
|
||||
if (ret > 0 && (size_t)ret < sizeof(buf)) {
|
||||
str_chomp(buf);
|
||||
if (humanize) {
|
||||
float seconds = strtof(buf, NULL) / 1000000000.0;
|
||||
@ -217,7 +216,7 @@ static void print_stats(struct lxc_container *c)
|
||||
}
|
||||
|
||||
ret = c->get_cgroup_item(c, "blkio.throttle.io_service_bytes", buf, sizeof(buf));
|
||||
if (ret > 0 && ret < sizeof(buf)) {
|
||||
if (ret > 0 && (size_t)ret < sizeof(buf)) {
|
||||
char *ch;
|
||||
|
||||
/* put ch on last "Total" line */
|
||||
@ -247,7 +246,7 @@ static void print_stats(struct lxc_container *c)
|
||||
|
||||
for (i = 0; lxstat[i].name; i++) {
|
||||
ret = c->get_cgroup_item(c, lxstat[i].file, buf, sizeof(buf));
|
||||
if (ret > 0 && ret < sizeof(buf)) {
|
||||
if (ret > 0 && (size_t)ret < sizeof(buf)) {
|
||||
str_chomp(buf);
|
||||
str_size_humanize(buf, sizeof(buf));
|
||||
printf("%-15s %s\n", lxstat[i].name, buf);
|
||||
@ -409,7 +408,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(ret);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
|
@ -16,9 +16,9 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@ -35,11 +35,7 @@
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "conf.h"
|
||||
#include "confile.h"
|
||||
#include "log.h"
|
||||
#include "lxc.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
/* Per default we only allow five levels of recursion to protect the stack at
|
||||
* least a little bit. */
|
||||
@ -231,7 +227,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
@ -1072,7 +1067,7 @@ static int ls_remove_lock(const char *path, const char *name,
|
||||
if (check < 0 || (size_t)check >= *len_lockpath)
|
||||
goto out;
|
||||
|
||||
lxc_rmdir_onedev(*lockpath, NULL);
|
||||
(void)rm_r(*lockpath);
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
|
@ -20,22 +20,31 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <libgen.h>
|
||||
#include <poll.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#include <regex.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "lxc.h"
|
||||
#include "log.h"
|
||||
#include "monitor.h"
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "lxccontainer.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static bool quit_monitord;
|
||||
|
||||
@ -82,6 +91,408 @@ static void close_fds(struct pollfd *fds, nfds_t nfds)
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
lxc_msg_state,
|
||||
lxc_msg_priority,
|
||||
lxc_msg_exit_code,
|
||||
} lxc_msg_type_t;
|
||||
|
||||
struct lxc_msg {
|
||||
lxc_msg_type_t type;
|
||||
char name[NAME_MAX+1];
|
||||
int value;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
STOPPED,
|
||||
STARTING,
|
||||
RUNNING,
|
||||
STOPPING,
|
||||
ABORTING,
|
||||
FREEZING,
|
||||
FROZEN,
|
||||
THAWED,
|
||||
MAX_STATE,
|
||||
} lxc_state_t;
|
||||
|
||||
static const char *const strstate[] = {
|
||||
"STOPPED", "STARTING", "RUNNING", "STOPPING",
|
||||
"ABORTING", "FREEZING", "FROZEN", "THAWED",
|
||||
};
|
||||
|
||||
const char *lxc_state2str(lxc_state_t state)
|
||||
{
|
||||
if (state < STOPPED || state > MAX_STATE - 1)
|
||||
return NULL;
|
||||
return strstate[state];
|
||||
}
|
||||
|
||||
/* Note we don't use SHA-1 here as we don't want to depend on HAVE_GNUTLS.
|
||||
* FNV has good anti collision properties and we're not worried
|
||||
* about pre-image resistance or one-way-ness, we're just trying to make
|
||||
* the name unique in the 108 bytes of space we have.
|
||||
*/
|
||||
#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
|
||||
static uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
|
||||
{
|
||||
unsigned char *bp;
|
||||
|
||||
for(bp = buf; bp < (unsigned char *)buf + len; bp++)
|
||||
{
|
||||
/* xor the bottom with the current octet */
|
||||
hval ^= (uint64_t)*bp;
|
||||
|
||||
/* gcc optimised:
|
||||
* multiply by the 64 bit FNV magic prime mod 2^64
|
||||
*/
|
||||
hval += (hval << 1) + (hval << 4) + (hval << 5) +
|
||||
(hval << 7) + (hval << 8) + (hval << 40);
|
||||
}
|
||||
|
||||
return hval;
|
||||
}
|
||||
|
||||
static int open_devnull(void)
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
|
||||
if (fd < 0)
|
||||
fprintf(stderr, "%s - Failed to open \"/dev/null\"\n",
|
||||
strerror(errno));
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int set_stdfds(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
ret = dup2(fd, STDIN_FILENO);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
ret = dup2(fd, STDOUT_FILENO);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
ret = dup2(fd, STDERR_FILENO);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int null_stdfds(void)
|
||||
{
|
||||
int ret = -1;
|
||||
int fd = open_devnull();
|
||||
|
||||
if (fd >= 0) {
|
||||
ret = set_stdfds(fd);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lxc_check_inherited(bool closeall, int *fds_to_ignore, size_t len_fds)
|
||||
{
|
||||
struct dirent *direntp;
|
||||
int fd, fddir;
|
||||
size_t i;
|
||||
DIR *dir;
|
||||
|
||||
restart:
|
||||
dir = opendir("/proc/self/fd");
|
||||
if (!dir) {
|
||||
fprintf(stderr, "%s - Failed to open directory\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fddir = dirfd(dir);
|
||||
|
||||
while ((direntp = readdir(dir))) {
|
||||
if (!strcmp(direntp->d_name, "."))
|
||||
continue;
|
||||
|
||||
if (!strcmp(direntp->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (lxc_safe_int(direntp->d_name, &fd) < 0)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < len_fds; i++)
|
||||
if (fds_to_ignore[i] == fd)
|
||||
break;
|
||||
|
||||
if (fd == fddir || (i < len_fds && fd == fds_to_ignore[i]))
|
||||
continue;
|
||||
|
||||
if (fd == 0 || fd == 1 || fd == 2)
|
||||
continue;
|
||||
|
||||
if (closeall) {
|
||||
close(fd);
|
||||
closedir(dir);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enforces \0-termination for the abstract unix socket. This is not required
|
||||
* but allows us to print it out.
|
||||
*
|
||||
* Older version of liblxc only allowed for 105 bytes to be used for the
|
||||
* abstract unix domain socket name because the code for our abstract unix
|
||||
* socket handling performed invalid checks. Since we \0-terminate we could now
|
||||
* have a maximum of 106 chars. But to not break backwards compatibility we keep
|
||||
* the limit at 105.
|
||||
*/
|
||||
static int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr)
|
||||
{
|
||||
size_t len;
|
||||
int ret;
|
||||
char *path;
|
||||
uint64_t hash;
|
||||
|
||||
/* addr.sun_path is only 108 bytes, so we hash the full name and
|
||||
* then append as much of the name as we can fit.
|
||||
*/
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
addr->sun_family = AF_UNIX;
|
||||
|
||||
/* strlen("lxc/") + strlen("/monitor-sock") + 1 = 18 */
|
||||
len = strlen(lxcpath) + 18;
|
||||
path = alloca(len);
|
||||
ret = snprintf(path, len, "lxc/%s/monitor-sock", lxcpath);
|
||||
if (ret < 0 || (size_t)ret >= len) {
|
||||
fprintf(stderr, "failed to create name for monitor socket\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Note: snprintf() will \0-terminate addr->sun_path on the 106th byte
|
||||
* and so the abstract socket name has 105 "meaningful" characters. This
|
||||
* is absolutely intentional. For further info read the comment for this
|
||||
* function above!
|
||||
*/
|
||||
len = sizeof(addr->sun_path) - 1;
|
||||
hash = fnv_64a_buf(path, ret, FNV1A_64_INIT);
|
||||
ret = snprintf(addr->sun_path, len, "@lxc/%016" PRIx64 "/%s", hash, lxcpath);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to create hashed name for monitor socket\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* replace @ with \0 */
|
||||
addr->sun_path[0] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lxc_abstract_unix_connect(const char *path)
|
||||
{
|
||||
int fd, ret;
|
||||
size_t len;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
len = strlen(&path[1]);
|
||||
/* do not enforce \0-termination */
|
||||
if (len >= sizeof(addr.sun_path)) {
|
||||
close(fd);
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
/* addr.sun_path[0] has already been set to 0 by memset() */
|
||||
strncpy(&addr.sun_path[1], &path[1], strlen(&path[1]));
|
||||
|
||||
ret = connect(fd, (struct sockaddr *)&addr,
|
||||
offsetof(struct sockaddr_un, sun_path) + len + 1);
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int lxc_monitor_open(const char *lxcpath)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int fd;
|
||||
size_t retry;
|
||||
size_t len;
|
||||
int ret = -1;
|
||||
int backoff_ms[] = {10, 50, 100};
|
||||
|
||||
if (lxc_monitor_sock_name(lxcpath, &addr) < 0)
|
||||
return -1;
|
||||
|
||||
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
len = strlen(&addr.sun_path[1]);
|
||||
if (len >= sizeof(addr.sun_path) - 1) {
|
||||
errno = ENAMETOOLONG;
|
||||
ret = -errno;
|
||||
fprintf(stderr, "name of monitor socket too long (%zu bytes): %s\n", len, strerror(errno));
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
for (retry = 0; retry < sizeof(backoff_ms) / sizeof(backoff_ms[0]); retry++) {
|
||||
fd = lxc_abstract_unix_connect(addr.sun_path);
|
||||
if (fd != -1 || errno != ECONNREFUSED)
|
||||
break;
|
||||
fprintf(stderr, "Failed to connect to monitor socket. Retrying in %d ms: %s\n", backoff_ms[retry], strerror(errno));
|
||||
usleep(backoff_ms[retry] * 1000);
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "Failed to connect to monitor socket: %s\n", strerror(errno));
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
on_error:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds,
|
||||
struct lxc_msg *msg, int timeout)
|
||||
{
|
||||
nfds_t i;
|
||||
int ret;
|
||||
|
||||
ret = poll(fds, nfds, timeout * 1000);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
else if (ret == 0)
|
||||
return -2; /* timed out */
|
||||
|
||||
/* Only read from the first ready fd, the others will remain ready for
|
||||
* when this routine is called again.
|
||||
*/
|
||||
for (i = 0; i < nfds; i++) {
|
||||
if (fds[i].revents != 0) {
|
||||
fds[i].revents = 0;
|
||||
ret = recv(fds[i].fd, msg, sizeof(*msg), 0);
|
||||
if (ret <= 0) {
|
||||
fprintf(stderr, "%s - Failed to receive message. Did monitord die?\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define LXC_MONITORD_PATH LIBEXECDIR "/lxc/lxc-monitord"
|
||||
|
||||
/* Used to spawn a monitord either on startup of a daemon container, or when
|
||||
* lxc-monitor starts.
|
||||
*/
|
||||
static int lxc_monitord_spawn(const char *lxcpath)
|
||||
{
|
||||
int ret;
|
||||
int pipefd[2];
|
||||
char pipefd_str[TOOL_NUMSTRLEN64];
|
||||
pid_t pid1, pid2;
|
||||
|
||||
char *const args[] = {
|
||||
LXC_MONITORD_PATH,
|
||||
(char *)lxcpath,
|
||||
pipefd_str,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* double fork to avoid zombies when monitord exits */
|
||||
pid1 = fork();
|
||||
if (pid1 < 0) {
|
||||
fprintf(stderr, "Failed to fork()\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pid1) {
|
||||
if (waitpid(pid1, NULL, 0) != pid1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pipe(pipefd) < 0) {
|
||||
fprintf(stderr, "Failed to create pipe\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pid2 = fork();
|
||||
if (pid2 < 0) {
|
||||
fprintf(stderr, "Failed to fork()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid2) {
|
||||
char c;
|
||||
/* Wait for daemon to create socket. */
|
||||
close(pipefd[1]);
|
||||
|
||||
/* Sync with child, we're ignoring the return from read
|
||||
* because regardless if it works or not, either way we've
|
||||
* synced with the child process. the if-empty-statement
|
||||
* construct is to quiet the warn-unused-result warning.
|
||||
*/
|
||||
if (read(pipefd[0], &c, 1))
|
||||
;
|
||||
|
||||
close(pipefd[0]);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
fprintf(stderr, "Failed to setsid()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
lxc_check_inherited(true, &pipefd[1], 1);
|
||||
if (null_stdfds() < 0) {
|
||||
fprintf(stderr, "Failed to dup2() standard file descriptors to /dev/null\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
close(pipefd[0]);
|
||||
|
||||
ret = snprintf(pipefd_str, TOOL_NUMSTRLEN64, "%d", pipefd[1]);
|
||||
if (ret < 0 || ret >= TOOL_NUMSTRLEN64) {
|
||||
fprintf(stderr, "Failed to create pid argument to pass to monitord\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
execvp(args[0], args);
|
||||
fprintf(stderr, "Failed to exec lxc-monitord\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *regexp;
|
||||
@ -109,7 +520,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(rc_main);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
@ -160,7 +570,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
nfds = my_args.lxcpath_cnt;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
for (i = 0; (unsigned long)i < nfds; i++) {
|
||||
int fd;
|
||||
|
||||
lxc_monitord_spawn(my_args.lxcpath[i]);
|
||||
|
@ -17,21 +17,20 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "confile.h"
|
||||
#include <stdio.h>
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#define _GNU_SOURCE
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "lxc.h"
|
||||
#include "log.h"
|
||||
#include "arguments.h"
|
||||
#include "storage.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static int my_parser(struct lxc_arguments *args, int c, char *arg);
|
||||
|
||||
@ -97,7 +96,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
|
@ -20,35 +20,30 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <libgen.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <net/if.h>
|
||||
#include <signal.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "caps.h"
|
||||
#include "lxc.h"
|
||||
#include "conf.h"
|
||||
#include "cgroup.h"
|
||||
#include "utils.h"
|
||||
#include "confile.h"
|
||||
#include "arguments.h"
|
||||
#include "tool_list.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static struct lxc_list defines;
|
||||
|
||||
@ -82,21 +77,44 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int my_parser(struct lxc_arguments* args, int c, char* arg)
|
||||
static int my_parser(struct lxc_arguments *args, int c, char *arg)
|
||||
{
|
||||
switch (c) {
|
||||
case 'c': args->console = arg; break;
|
||||
case 'L': args->console_log = arg; break;
|
||||
case 'd': args->daemonize = 1; break;
|
||||
case 'F': args->daemonize = 0; break;
|
||||
case 'f': args->rcfile = arg; break;
|
||||
case 'C': args->close_all_fds = 1; break;
|
||||
case 's': return lxc_config_define_add(&defines, arg);
|
||||
case 'p': args->pidfile = arg; break;
|
||||
case OPT_SHARE_NET: args->share_ns[LXC_NS_NET] = arg; break;
|
||||
case OPT_SHARE_IPC: args->share_ns[LXC_NS_IPC] = arg; break;
|
||||
case OPT_SHARE_UTS: args->share_ns[LXC_NS_UTS] = arg; break;
|
||||
case OPT_SHARE_PID: args->share_ns[LXC_NS_PID] = arg; break;
|
||||
case 'c':
|
||||
args->console = arg;
|
||||
break;
|
||||
case 'L':
|
||||
args->console_log = arg;
|
||||
break;
|
||||
case 'd':
|
||||
args->daemonize = 1;
|
||||
break;
|
||||
case 'F':
|
||||
args->daemonize = 0;
|
||||
break;
|
||||
case 'f':
|
||||
args->rcfile = arg;
|
||||
break;
|
||||
case 'C':
|
||||
args->close_all_fds = 1;
|
||||
break;
|
||||
case 's':
|
||||
return lxc_config_define_add(&defines, arg);
|
||||
case 'p':
|
||||
args->pidfile = arg;
|
||||
break;
|
||||
case OPT_SHARE_NET:
|
||||
args->share_ns[LXC_NS_NET] = arg;
|
||||
break;
|
||||
case OPT_SHARE_IPC:
|
||||
args->share_ns[LXC_NS_IPC] = arg;
|
||||
break;
|
||||
case OPT_SHARE_UTS:
|
||||
args->share_ns[LXC_NS_UTS] = arg;
|
||||
break;
|
||||
case OPT_SHARE_PID:
|
||||
args->share_ns[LXC_NS_PID] = arg;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -147,11 +165,10 @@ Options :\n\
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct lxc_conf *conf;
|
||||
struct lxc_log log;
|
||||
const char *lxcpath;
|
||||
char *const *args;
|
||||
struct lxc_container *c;
|
||||
struct lxc_log log;
|
||||
int err = EXIT_FAILURE;
|
||||
char *rcfile = NULL;
|
||||
char *const default_args[] = {
|
||||
@ -181,7 +198,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(err);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
lxcpath = my_args.lxcpath[0];
|
||||
if (access(lxcpath, O_RDONLY) < 0) {
|
||||
@ -259,11 +275,12 @@ int main(int argc, char *argv[])
|
||||
* We should use set_config_item() over &defines, which would handle
|
||||
* unset c->lxc_conf for us and let us not use lxc_config_define_load()
|
||||
*/
|
||||
if (!c->lxc_conf)
|
||||
c->lxc_conf = lxc_conf_init();
|
||||
conf = c->lxc_conf;
|
||||
if (!c->lxc_conf) {
|
||||
fprintf(stderr, "No container config specified\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lxc_config_define_load(&defines, conf))
|
||||
if (lxc_config_define_load(&defines, c))
|
||||
goto out;
|
||||
|
||||
if (!rcfile && !strcmp("/sbin/init", args[0])) {
|
||||
|
@ -20,18 +20,18 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "lxc.h"
|
||||
#include "log.h"
|
||||
#include "arguments.h"
|
||||
#include "commands.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
#define OPT_NO_LOCK OPT_USAGE + 1
|
||||
#define OPT_NO_KILL OPT_USAGE + 2
|
||||
@ -113,7 +113,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(ret);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
@ -155,13 +154,6 @@ int main(int argc, char *argv[])
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
/* shortcut - if locking is bogus, we should be able to kill
|
||||
* containers at least */
|
||||
if (my_args.nolock) {
|
||||
ret = lxc_cmd_stop(my_args.name, my_args.lxcpath[0]);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
|
||||
if (!c) {
|
||||
fprintf(stderr, "Error opening container\n");
|
||||
|
@ -21,25 +21,26 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "arguments.h"
|
||||
#include "log.h"
|
||||
#include "lxc.h"
|
||||
#include "mainloop.h"
|
||||
#include "utils.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
#define USER_HZ 100
|
||||
#define ESC "\033"
|
||||
@ -181,24 +182,6 @@ static int stdin_tios_rows(void)
|
||||
return 25;
|
||||
}
|
||||
|
||||
static int stdin_handler(int fd, uint32_t events, void *data,
|
||||
struct lxc_epoll_descr *descr)
|
||||
{
|
||||
char *in_char = data;
|
||||
|
||||
if (events & EPOLLIN) {
|
||||
int rc;
|
||||
|
||||
rc = read(fd, in_char, sizeof(*in_char));
|
||||
if (rc <= 0)
|
||||
*in_char = '\0';
|
||||
}
|
||||
|
||||
if (events & EPOLLHUP)
|
||||
*in_char = 'q';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void sig_handler(int sig)
|
||||
{
|
||||
exit(EXIT_SUCCESS);
|
||||
@ -310,7 +293,7 @@ static void stat_get_blk_stats(struct lxc_container *c, const char *item,
|
||||
char **lines, **cols;
|
||||
|
||||
len = c->get_cgroup_item(c, item, buf, sizeof(buf));
|
||||
if (len <= 0 || len >= sizeof(buf)) {
|
||||
if (len <= 0 || (size_t)len >= sizeof(buf)) {
|
||||
fprintf(stderr, "unable to read cgroup item %s\n", item);
|
||||
return;
|
||||
}
|
||||
@ -409,7 +392,7 @@ static void stats_print(const char *name, const struct stats *stats,
|
||||
size_humanize(stats->mem_used, mem_used_str, sizeof(mem_used_str));
|
||||
|
||||
ret = snprintf(iosb_str, sizeof(iosb_str), "%s(%s/%s)", iosb_total_str, iosb_read_str, iosb_write_str);
|
||||
if (ret < 0 || ret >= sizeof(iosb_str))
|
||||
if (ret < 0 || (size_t)ret >= sizeof(iosb_str))
|
||||
printf("snprintf'd too many characters: %d\n", ret);
|
||||
|
||||
printf("%-18.18s %12.2f %12.2f %12.2f %36s %10s",
|
||||
@ -429,7 +412,7 @@ static void stats_print(const char *name, const struct stats *stats,
|
||||
printf(" %10s", kmem_used_str);
|
||||
}
|
||||
} else {
|
||||
gettimeofday(&time_val, NULL);
|
||||
(void)gettimeofday(&time_val, NULL);
|
||||
time_ms = (unsigned long long) (time_val.tv_sec) * 1000 + (unsigned long long) (time_val.tv_usec) / 1000;
|
||||
printf("%" PRIu64 ",%s,%" PRIu64 ",%" PRIu64 ",%" PRIu64
|
||||
",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64,
|
||||
@ -554,6 +537,143 @@ static void ct_realloc(int active_cnt)
|
||||
}
|
||||
}
|
||||
|
||||
#define LXC_MAINLOOP_CONTINUE 0
|
||||
#define LXC_MAINLOOP_CLOSE 1
|
||||
|
||||
struct lxc_epoll_descr {
|
||||
int epfd;
|
||||
struct lxc_list handlers;
|
||||
};
|
||||
|
||||
typedef int (*lxc_mainloop_callback_t)(int fd, uint32_t event, void *data,
|
||||
struct lxc_epoll_descr *descr);
|
||||
|
||||
struct mainloop_handler {
|
||||
lxc_mainloop_callback_t callback;
|
||||
int fd;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define MAX_EVENTS 10
|
||||
|
||||
int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
|
||||
{
|
||||
int i, nfds, ret;
|
||||
struct mainloop_handler *handler;
|
||||
struct epoll_event events[MAX_EVENTS];
|
||||
|
||||
for (;;) {
|
||||
nfds = epoll_wait(descr->epfd, events, MAX_EVENTS, timeout_ms);
|
||||
if (nfds < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
handler = events[i].data.ptr;
|
||||
|
||||
/* If the handler returns a positive value, exit the
|
||||
* mainloop.
|
||||
*/
|
||||
ret = handler->callback(handler->fd, events[i].events,
|
||||
handler->data, descr);
|
||||
if (ret == LXC_MAINLOOP_CLOSE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nfds == 0)
|
||||
return 0;
|
||||
|
||||
if (lxc_list_empty(&descr->handlers))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int lxc_mainloop_open(struct lxc_epoll_descr *descr)
|
||||
{
|
||||
/* hint value passed to epoll create */
|
||||
descr->epfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (descr->epfd < 0)
|
||||
return -1;
|
||||
|
||||
lxc_list_init(&descr->handlers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
|
||||
lxc_mainloop_callback_t callback, void *data)
|
||||
{
|
||||
struct epoll_event ev;
|
||||
struct mainloop_handler *handler;
|
||||
struct lxc_list *item;
|
||||
|
||||
handler = malloc(sizeof(*handler));
|
||||
if (!handler)
|
||||
return -1;
|
||||
|
||||
handler->callback = callback;
|
||||
handler->fd = fd;
|
||||
handler->data = data;
|
||||
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.ptr = handler;
|
||||
|
||||
if (epoll_ctl(descr->epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
|
||||
goto out_free_handler;
|
||||
|
||||
item = malloc(sizeof(*item));
|
||||
if (!item)
|
||||
goto out_free_handler;
|
||||
|
||||
item->elem = handler;
|
||||
lxc_list_add(&descr->handlers, item);
|
||||
return 0;
|
||||
|
||||
out_free_handler:
|
||||
free(handler);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lxc_mainloop_close(struct lxc_epoll_descr *descr)
|
||||
{
|
||||
struct lxc_list *iterator, *next;
|
||||
|
||||
iterator = descr->handlers.next;
|
||||
while (iterator != &descr->handlers) {
|
||||
next = iterator->next;
|
||||
|
||||
lxc_list_del(iterator);
|
||||
free(iterator->elem);
|
||||
free(iterator);
|
||||
iterator = next;
|
||||
}
|
||||
|
||||
if (descr->epfd >= 0)
|
||||
return close(descr->epfd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stdin_handler(int fd, uint32_t events, void *data,
|
||||
struct lxc_epoll_descr *descr)
|
||||
{
|
||||
char *in_char = data;
|
||||
|
||||
if (events & EPOLLIN) {
|
||||
int rc;
|
||||
|
||||
rc = read(fd, in_char, sizeof(*in_char));
|
||||
if (rc <= 0)
|
||||
*in_char = '\0';
|
||||
}
|
||||
|
||||
if (events & EPOLLHUP)
|
||||
*in_char = 'q';
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct lxc_epoll_descr descr;
|
||||
|
@ -20,16 +20,18 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "lxc.h"
|
||||
#include "log.h"
|
||||
#include "arguments.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static const struct option my_longopts[] = {
|
||||
LXC_COMMON_OPTIONS
|
||||
@ -71,7 +73,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
|
@ -20,30 +20,44 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pwd.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "caps.h"
|
||||
#include "cgroup.h"
|
||||
#include "error.h"
|
||||
#include "log.h"
|
||||
#include "namespace.h"
|
||||
#include "network.h"
|
||||
#include "utils.h"
|
||||
#include "arguments.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
/* Define sethostname() if missing from the C library also workaround some
|
||||
* quirky with having this defined in multiple places.
|
||||
*/
|
||||
static inline int sethostname_including_android(const char *name, size_t len)
|
||||
{
|
||||
#ifndef HAVE_SETHOSTNAME
|
||||
#ifdef __NR_sethostname
|
||||
return syscall(__NR_sethostname, name, len);
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
#else
|
||||
return sethostname(name, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct my_iflist
|
||||
{
|
||||
@ -67,7 +81,7 @@ static void usage(char *cmd)
|
||||
|
||||
static bool lookup_user(const char *optarg, uid_t *uid)
|
||||
{
|
||||
char name[MAXPATHLEN];
|
||||
char name[TOOL_MAXPATHLEN];
|
||||
struct passwd *pwent = NULL;
|
||||
|
||||
if (!optarg || (optarg[0] == '\0'))
|
||||
@ -130,7 +144,7 @@ static int do_start(void *arg)
|
||||
lxc_setup_fs();
|
||||
|
||||
if ((flags & CLONE_NEWUTS) && want_hostname)
|
||||
if (sethostname(want_hostname, strlen(want_hostname)) < 0) {
|
||||
if (sethostname_including_android(want_hostname, strlen(want_hostname)) < 0) {
|
||||
fprintf(stderr, "failed to set hostname %s: %s\n", want_hostname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -147,11 +161,34 @@ static int do_start(void *arg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_id_mapping(pid_t pid, const char *buf, size_t buf_size)
|
||||
{
|
||||
char path[TOOL_MAXPATHLEN];
|
||||
int fd, ret;
|
||||
|
||||
|
||||
ret = snprintf(path, TOOL_MAXPATHLEN, "/proc/%d/uid_map", pid);
|
||||
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
|
||||
return -E2BIG;
|
||||
|
||||
fd = open(path, O_WRONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
errno = 0;
|
||||
ret = lxc_write_nointr(fd, buf, buf_size);
|
||||
close(fd);
|
||||
if (ret < 0 || (size_t)ret != buf_size)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *del;
|
||||
char **it, **args;
|
||||
int opt, status;
|
||||
int opt;
|
||||
int ret;
|
||||
char *namespaces = NULL;
|
||||
int flags = 0, daemonize = 0;
|
||||
@ -284,7 +321,7 @@ int main(int argc, char *argv[])
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = write_id_mapping(ID_TYPE_UID, pid, umap, strlen(umap));
|
||||
ret = write_id_mapping(pid, umap, strlen(umap));
|
||||
if (ret < 0) {
|
||||
close(start_arg.wait_fd);
|
||||
fprintf(stderr, "uid mapping failed\n");
|
||||
@ -301,19 +338,40 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (my_iflist) {
|
||||
for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) {
|
||||
if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid, NULL) < 0)
|
||||
fprintf(stderr,"Could not move interface %s into container %d: %s\n", tmpif->mi_ifname, pid, strerror(errno));
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
fprintf(stderr, "Failed to move network device "
|
||||
"\"%s\" to network namespace\n",
|
||||
tmpif->mi_ifname);
|
||||
|
||||
if (pid == 0) {
|
||||
char buf[256];
|
||||
|
||||
ret = snprintf(buf, 256, "%d", pid);
|
||||
if (ret < 0 || ret >= 256)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
execlp("ip", "ip", "link", "set", "dev", tmpif->mi_ifname, "netns", buf, (char *)NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (wait_for_pid(pid) != 0)
|
||||
fprintf(stderr, "Could not move interface %s "
|
||||
"into container %d: %s\n",
|
||||
tmpif->mi_ifname, pid, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if (daemonize)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
if (wait_for_pid(pid) != 0) {
|
||||
fprintf(stderr, "failed to wait for '%d'\n", pid);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Call exit() directly on this function because it retuns an exit code. */
|
||||
exit(lxc_error_set_and_log(pid, status));
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
@ -30,9 +32,8 @@
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#include "lxc.h"
|
||||
#include "log.h"
|
||||
#include "arguments.h"
|
||||
#include "tool_utils.h"
|
||||
|
||||
static int my_checker(const struct lxc_arguments* args)
|
||||
{
|
||||
@ -98,7 +99,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (lxc_log_init(&log))
|
||||
exit(EXIT_FAILURE);
|
||||
lxc_log_options_no_override();
|
||||
|
||||
/* REMOVE IN LXC 3.0 */
|
||||
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
|
||||
|
167
src/lxc/tools/tool_list.h
Normal file
167
src/lxc/tools/tool_list.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* lxc: linux Container library
|
||||
*
|
||||
* (C) Copyright IBM Corp. 2007, 2008
|
||||
*
|
||||
* Authors:
|
||||
* Daniel Lezcano <daniel.lezcano at free.fr>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __LXC_LIST_H
|
||||
#define __LXC_LIST_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct lxc_list {
|
||||
void *elem;
|
||||
struct lxc_list *next;
|
||||
struct lxc_list *prev;
|
||||
};
|
||||
|
||||
#define lxc_init_list(l) \
|
||||
{ \
|
||||
.next = l, .prev = l \
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate through an lxc list. An example for an idiom would be:
|
||||
*
|
||||
* struct lxc_list *iterator;
|
||||
* lxc_list_for_each(iterator, list) {
|
||||
* type *tmp;
|
||||
* tmp = iterator->elem;
|
||||
* }
|
||||
*/
|
||||
#define lxc_list_for_each(__iterator, __list) \
|
||||
for (__iterator = (__list)->next; __iterator != __list; \
|
||||
__iterator = __iterator->next)
|
||||
|
||||
/* Iterate safely through an lxc list. An example for an appropriate use case
|
||||
* would be:
|
||||
*
|
||||
* struct lxc_list *cur, *next;
|
||||
* lxc_list_for_each_safe(cur, list, next) {
|
||||
* type *tmp;
|
||||
* tmp = cur->elem;
|
||||
* }
|
||||
*/
|
||||
#define lxc_list_for_each_safe(__iterator, __list, __next) \
|
||||
for (__iterator = (__list)->next, __next = __iterator->next; \
|
||||
__iterator != __list; __iterator = __next, __next = __next->next)
|
||||
|
||||
/* Initalize list. */
|
||||
static inline void lxc_list_init(struct lxc_list *list)
|
||||
{
|
||||
list->elem = NULL;
|
||||
list->next = list->prev = list;
|
||||
}
|
||||
|
||||
/* Add an element to a list. See lxc_list_add() and lxc_list_add_tail() for an
|
||||
* idiom.
|
||||
*/
|
||||
static inline void lxc_list_add_elem(struct lxc_list *list, void *elem)
|
||||
{
|
||||
list->elem = elem;
|
||||
}
|
||||
|
||||
/* Retrieve first element of list. */
|
||||
static inline void *lxc_list_first_elem(struct lxc_list *list)
|
||||
{
|
||||
return list->next->elem;
|
||||
}
|
||||
|
||||
/* Retrieve last element of list. */
|
||||
static inline void *lxc_list_last_elem(struct lxc_list *list)
|
||||
{
|
||||
return list->prev->elem;
|
||||
}
|
||||
|
||||
/* Determine if list is empty. */
|
||||
static inline int lxc_list_empty(struct lxc_list *list)
|
||||
{
|
||||
return list == list->next;
|
||||
}
|
||||
|
||||
/* Workhorse to be called from lxc_list_add() and lxc_list_add_tail(). */
|
||||
static inline void __lxc_list_add(struct lxc_list *new, struct lxc_list *prev,
|
||||
struct lxc_list *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/* Idiom to add an element to the beginning of an lxc list:
|
||||
*
|
||||
* struct lxc_list *tmp = malloc(sizeof(*tmp));
|
||||
* if (tmp == NULL)
|
||||
* return 1;
|
||||
* lxc_list_add_elem(tmp, elem);
|
||||
* lxc_list_add(list, tmp);
|
||||
*/
|
||||
static inline void lxc_list_add(struct lxc_list *head, struct lxc_list *list)
|
||||
{
|
||||
__lxc_list_add(list, head, head->next);
|
||||
}
|
||||
|
||||
/* Idiom to add an element to the end of an lxc list:
|
||||
*
|
||||
* struct lxc_list *tmp = malloc(sizeof(*tmp));
|
||||
* if (tmp == NULL)
|
||||
* return 1;
|
||||
* lxc_list_add_elem(tmp, elem);
|
||||
* lxc_list_add_tail(list, tmp);
|
||||
*/
|
||||
static inline void lxc_list_add_tail(struct lxc_list *head,
|
||||
struct lxc_list *list)
|
||||
{
|
||||
__lxc_list_add(list, head->prev, head);
|
||||
}
|
||||
|
||||
/* Idiom to remove an element from a list:
|
||||
* struct lxc_list *cur, *next;
|
||||
* lxc_list_for_each_safe(cur, list, next) {
|
||||
* lxc_list_del(cur);
|
||||
* free(cur->elem);
|
||||
* free(cur);
|
||||
* }
|
||||
*/
|
||||
static inline void lxc_list_del(struct lxc_list *list)
|
||||
{
|
||||
struct lxc_list *next, *prev;
|
||||
|
||||
next = list->next;
|
||||
prev = list->prev;
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/* Return length of the list. */
|
||||
static inline size_t lxc_list_len(struct lxc_list *list)
|
||||
{
|
||||
size_t i = 0;
|
||||
struct lxc_list *iter;
|
||||
|
||||
lxc_list_for_each(iter, list) {
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif /* __LXC_LIST_H */
|
1196
src/lxc/tools/tool_utils.c
Normal file
1196
src/lxc/tools/tool_utils.c
Normal file
File diff suppressed because it is too large
Load Diff
204
src/lxc/tools/tool_utils.h
Normal file
204
src/lxc/tools/tool_utils.h
Normal file
@ -0,0 +1,204 @@
|
||||
/* 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 <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 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 int lxc_config_define_load(struct lxc_list *defines,
|
||||
struct lxc_container *c);
|
||||
extern void lxc_config_define_free(struct lxc_list *defines);
|
||||
extern int lxc_char_left_gc(const char *buffer, size_t len);
|
||||
extern int lxc_char_right_gc(const char *buffer, size_t len);
|
||||
|
||||
struct new_config_item {
|
||||
char *key;
|
||||
char *val;
|
||||
};
|
||||
extern struct new_config_item *parse_line(char *buffer);
|
||||
|
||||
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 */
|
Loading…
Reference in New Issue
Block a user