Merge pull request #2090 from brauner/2018-01-12/tools_remove_non_api_symbols

tools: remove non api symbols
This commit is contained in:
Stéphane Graber 2018-02-11 17:52:01 -05:00 committed by GitHub
commit f704a070d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 3314 additions and 517 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}

View 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);
}
}

View 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

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -23,8 +23,6 @@
#include <lxc/lxccontainer.h>
#include "config.h"
struct lxc_config_items {
char *name;
};

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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]);

View File

@ -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);

View File

@ -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])) {

View File

@ -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");

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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
View 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

File diff suppressed because it is too large Load Diff

204
src/lxc/tools/tool_utils.h Normal file
View 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 */