[lxc-devel] [PATCH] extend command processor to handle generic data
Serge Hallyn
serge.hallyn at ubuntu.com
Tue May 21 13:18:01 UTC 2013
Quoting Dwight Engen (dwight.engen at oracle.com):
> Motivation for this change is to have the ability to get the run-time
> configuration items from a container, which may differ from its current
> on disk configuration, or might not be available any other way (for
> example lxc.network.0.veth.pair). In adding this ability it seemed there
> was room for refactoring improvements.
>
> Genericize the command infrastructure so that both command requests and
> responses can have arbitrary data. Consolidate all commands into command.c
> and name them consistently. This allows all the callback routines to be
> made static, reducing exposure.
>
> Return the actual allocated tty for the console command. Don't print the
> init pid in lxc_info if the container isn't actually running. Command
> processing was made more thread safe by removing the static buffer from
> receive_answer(). Refactored command response code to a common routine.
>
> Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
Working great on my box - thanks.
Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
It seems like a general cleanup, but I'm wondering what your motivation
was for the get-config command? Programs using the struct
lxc_container API or lua/python3 bindings can after all just do
import lxc
c = lxcContainer('c1', NULL);
c.get_config_item('lxc.rootfs')
> ---
> src/lxc/Makefile.am | 1 -
> src/lxc/cgroup.c | 70 ++----
> src/lxc/cgroup.h | 1 -
> src/lxc/commands.c | 648 +++++++++++++++++++++++++++++++++++++++++--------
> src/lxc/commands.h | 75 +++---
> src/lxc/console.c | 84 -------
> src/lxc/lxc.h | 8 -
> src/lxc/lxc_attach.c | 4 +-
> src/lxc/lxc_console.c | 8 +-
> src/lxc/lxc_info.c | 10 +-
> src/lxc/lxc_kill.c | 2 +-
> src/lxc/lxc_stop.c | 3 +-
> src/lxc/lxccontainer.c | 4 +-
> src/lxc/start.c | 88 +------
> src/lxc/state.c | 63 +----
> src/lxc/stop.c | 115 ---------
> src/tests/cgpath.c | 5 +-
> 17 files changed, 633 insertions(+), 556 deletions(-)
> delete mode 100644 src/lxc/stop.c
>
> diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
> index 4a19061..f8eb41b 100644
> --- a/src/lxc/Makefile.am
> +++ b/src/lxc/Makefile.am
> @@ -40,7 +40,6 @@ liblxc_so_SOURCES = \
> bdev.c bdev.h \
> commands.c commands.h \
> start.c start.h \
> - stop.c \
> execute.c \
> monitor.c monitor.h \
> console.c \
> diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
> index a8ae8c1..a3fa2c6 100644
> --- a/src/lxc/cgroup.c
> +++ b/src/lxc/cgroup.c
> @@ -120,7 +120,7 @@ static int get_cgroup_mount(const char *subsystem, char *mnt)
> while ((getmntent_r(file, &mntent_r, buf, sizeof(buf)))) {
> if (strcmp(mntent_r.mnt_type, "cgroup") != 0)
> continue;
> -
> +
> if (subsystem) {
> if (!hasmntopt(&mntent_r, subsystem))
> continue;
> @@ -215,55 +215,9 @@ fail:
> }
>
> /*
> - * Calculate a container's cgroup path for a particular subsystem. This
> - * is the cgroup path relative to the root of the cgroup filesystem.
> - * @path: A char ** into which we copy the char* containing the answer
> - * @subsystem: the cgroup subsystem of interest (i.e. freezer)
> - * @name: container name
> - * @lxcpath: the lxcpath in which the container is running.
> - *
> - * Returns 0 on success, -1 on error.
> - *
> - * Note that the char* copied into *path is a static char[MAXPATHLEN] in
> - * commands.c:receive_answer(). It should not be freed.
> - */
> -extern int lxc_get_cgpath(const char **path, const char *subsystem, const char *name, const char *lxcpath)
> -{
> - struct lxc_command command = {
> - .request = { .type = LXC_COMMAND_CGROUP },
> - };
> -
> - int ret, stopped = 0;
> -
> - ret = lxc_command(name, &command, &stopped, lxcpath);
> - if (ret < 0) {
> - if (!stopped)
> - ERROR("failed to send command");
> - return -1;
> - }
> -
> - if (!ret) {
> - WARN("'%s' has stopped before sending its state", name);
> - return -1;
> - }
> -
> - if (command.answer.ret < 0 || command.answer.pathlen < 0) {
> - ERROR("failed to get state for '%s': %s",
> - name, strerror(-command.answer.ret));
> - return -1;
> - }
> -
> - *path = command.answer.path;
> -
> - return 0;
> -}
> -
> -/*
> * lxc_cgroup_path_get: determine full pathname for a cgroup
> * file for a specific container.
> - * @path: char ** used to return the answer. The char * will point
> - * into the static char* retuf from cgroup_path_get() (so no need
> - * to free it).
> + * @path: char ** used to return the answer.
> * @subsystem: cgroup subsystem (i.e. "freezer") for which to
> * return an answer. If NULL, then the first cgroup entry in
> * mtab will be used.
> @@ -275,12 +229,16 @@ extern int lxc_get_cgpath(const char **path, const char *subsystem, const char *
> */
> int lxc_cgroup_path_get(char **path, const char *subsystem, const char *name, const char *lxcpath)
> {
> - const char *cgpath;
> + int ret;
> + char *cgpath;
>
> - if (lxc_get_cgpath(&cgpath, subsystem, name, lxcpath) < 0)
> + cgpath = lxc_cmd_get_cgroup_path(subsystem, name, lxcpath);
> + if (!cgpath)
> return -1;
>
> - return cgroup_path_get(path, subsystem, cgpath);
> + ret = cgroup_path_get(path, subsystem, cgpath);
> + free(cgpath);
> + return ret;
> }
>
> /*
> @@ -917,13 +875,17 @@ int lxc_cgroup_destroy(const char *cgpath)
>
> int lxc_cgroup_attach(pid_t pid, const char *name, const char *lxcpath)
> {
> - const char *dirpath;
> + int ret;
> + char *dirpath;
>
> - if (lxc_get_cgpath(&dirpath, NULL, name, lxcpath) < 0) {
> + dirpath = lxc_cmd_get_cgroup_path(NULL, name, lxcpath);
> + if (!dirpath) {
> ERROR("Error getting cgroup for container %s: %s", lxcpath, name);
> return -1;
> }
> INFO("joining pid %d to cgroup %s", pid, dirpath);
>
> - return lxc_cgroup_enter(dirpath, pid);
> + ret = lxc_cgroup_enter(dirpath, pid);
> + free(dirpath);
> + return ret;
> }
> diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
> index 937b9c9..971311e 100644
> --- a/src/lxc/cgroup.h
> +++ b/src/lxc/cgroup.h
> @@ -34,5 +34,4 @@ extern char *lxc_cgroup_path_create(const char *lxcgroup, const char *name);
> extern int lxc_cgroup_enter(const char *cgpath, pid_t pid);
> extern int lxc_cgroup_attach(pid_t pid, const char *name, const char *lxcpath);
> extern int cgroup_path_get(char **path, const char *subsystem, const char *cgpath);
> -extern int lxc_get_cgpath(const char **path, const char *subsystem, const char *name, const char *lxcpath);
> #endif
> diff --git a/src/lxc/commands.c b/src/lxc/commands.c
> index d45ae21..3f21488 100644
> --- a/src/lxc/commands.c
> +++ b/src/lxc/commands.c
> @@ -34,27 +34,30 @@
> #include <stdlib.h>
>
> #include <lxc/log.h>
> +#include <lxc/lxc.h>
> #include <lxc/conf.h>
> #include <lxc/start.h> /* for struct lxc_handler */
> #include <lxc/utils.h>
>
> #include "commands.h"
> +#include "confile.h"
> #include "mainloop.h"
> #include "af_unix.h"
> #include "config.h"
>
> /*
> - * This file provides the different functions to have the client
> - * and the server to communicate
> + * This file provides the different functions for clients to
> + * query/command the server. The client is typically some lxc
> + * tool and the server is typically the container (ie. lxc-start).
> *
> - * Each command is transactional, the client send a request to
> - * the server and the server answer the request with a message
> + * Each command is transactional, the clients send a request to
> + * the server and the server answers the request with a message
> * giving the request's status (zero or a negative errno value).
> + * Both the request and response may contain addtional data.
> *
> * Each command is wrapped in a ancillary message in order to pass
> * a credential making possible to the server to check if the client
> * is allowed to ask for this command or not.
> - *
> */
>
> lxc_log_define(lxc_commands, lxc);
> @@ -81,66 +84,183 @@ static int fill_sock_name(char *path, int len, const char *name,
> return 0;
> }
>
> -static int receive_answer(int sock, struct lxc_answer *answer)
> +static const char *lxc_cmd_str(lxc_cmd_t cmd)
> {
> - int ret;
> - static char answerpath[MAXPATHLEN];
> + static const char *cmdname[LXC_CMD_MAX] = {
> + [LXC_CMD_CONSOLE] = "console",
> + [LXC_CMD_STOP] = "stop",
> + [LXC_CMD_GET_STATE] = "get_state",
> + [LXC_CMD_GET_INIT_PID] = "get_init_pid",
> + [LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
> + [LXC_CMD_GET_CGROUP] = "get_cgroup",
> + [LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
> + };
>
> - ret = lxc_af_unix_recv_fd(sock, &answer->fd, answer, sizeof(*answer));
> - if (ret < 0)
> - ERROR("failed to receive answer for the command");
> - if (answer->pathlen == 0)
> + if (cmd < 0 || cmd >= LXC_CMD_MAX)
> + return "Unknown cmd";
> + return cmdname[cmd];
> +}
> +
> +/*
> + * lxc_cmd_rsp_recv: Receive a response to a command
> + *
> + * @sock : the socket connected to the container
> + * @cmd : command to put response in
> + *
> + * Returns the size of the response message or < 0 on failure
> + *
> + * Note that if the command response datalen > 0, then data is
> + * a malloc()ed buffer and should be free()ed by the caller. If
> + * the response data is <= a void * worth of data, it will be
> + * stored directly in data and datalen will be 0.
> + *
> + * As a special case, the response for LXC_CMD_CONSOLE is created
> + * here as it contains an fd passed through the unix socket.
> + */
> +static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
> +{
> + int ret,rspfd;
> + struct lxc_cmd_rsp *rsp = &cmd->rsp;
> +
> + ret = lxc_af_unix_recv_fd(sock, &rspfd, rsp, sizeof(*rsp));
> + if (ret < 0) {
> + ERROR("command %s failed to receive response",
> + lxc_cmd_str(cmd->req.cmd));
> + return -1;
> + }
> +
> + if (cmd->req.cmd == LXC_CMD_CONSOLE) {
> + struct lxc_cmd_console_rsp_data *rspdata;
> +
> + rspdata = malloc(sizeof(*rspdata));
> + if (!rspdata) {
> + ERROR("command %s couldn't allocate response buffer",
> + lxc_cmd_str(cmd->req.cmd));
> + return -1;
> + }
> + rspdata->fd = rspfd;
> + rspdata->ttynum = PTR_TO_INT(rsp->data);
> + rsp->data = rspdata;
> + }
> +
> + if (rsp->datalen == 0)
> return ret;
> - if (answer->pathlen >= MAXPATHLEN) {
> - ERROR("cgroup path was too long");
> + if (rsp->datalen > LXC_CMD_DATA_MAX) {
> + ERROR("command %s response data %d too long",
> + lxc_cmd_str(cmd->req.cmd), rsp->datalen);
> + errno = EFBIG;
> return -1;
> }
> - ret = recv(sock, answerpath, answer->pathlen, 0);
> - if (ret != answer->pathlen) {
> - ERROR("failed to receive answer for the command");
> - ret = 0;
> - } else
> - answer->path = answerpath;
> +
> + rsp->data = malloc(rsp->datalen);
> + if (!rsp->data) {
> + ERROR("command %s unable to allocate response buffer",
> + lxc_cmd_str(cmd->req.cmd));
> + return -1;
> + }
> + ret = recv(sock, rsp->data, rsp->datalen, 0);
> + if (ret != rsp->datalen) {
> + ERROR("command %s failed to receive response data",
> + lxc_cmd_str(cmd->req.cmd));
> + if (ret >= 0)
> + ret = -1;
> + }
>
> return ret;
> }
>
> -static int __lxc_command(const char *name, struct lxc_command *command,
> - int *stopped, int stay_connected, const char *lxcpath)
> +/*
> + * lxc_cmd_rsp_send: Send a command response
> + *
> + * @fd : file descriptor of socket to send response on
> + * @rsp : response to send
> + *
> + * Returns 0 on success, < 0 on failure
> + */
> +static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
> +{
> + int ret;
> +
> + ret = send(fd, rsp, sizeof(*rsp), 0);
> + if (ret != sizeof(*rsp)) {
> + ERROR("failed to send command response %d %s", ret,
> + strerror(errno));
> + return -1;
> + }
> +
> + if (rsp->datalen > 0) {
> + ret = send(fd, rsp->data, rsp->datalen, 0);
> + if (ret != rsp->datalen) {
> + WARN("failed to send command response data %d %s", ret,
> + strerror(errno));
> + return -1;
> + }
> + }
> + return 0;
> +}
> +
> +/*
> + * lxc_cmd: Connect to the specified running container, send it a command
> + * request and collect the response
> + *
> + * @name : name of container to connect to
> + * @cmd : command with initialized reqest to send
> + * @stopped : output indicator if the container was not running
> + * @lxcpath : the lxcpath in which the container is running
> + *
> + * Returns the size of the response message on success, < 0 on failure
> + *
> + * Note that there is a special case for LXC_CMD_CONSOLE. For this command
> + * the fd cannot be closed because it is used as a placeholder to indicate
> + * that a particular tty slot is in use. The fd is also used as a signal to
> + * the container that when the caller dies or closes the fd, the container
> + * will notice the fd in its mainloop select and then free the slot with
> + * lxc_cmd_fd_cleanup().
> + */
> +static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
> + const char *lxcpath)
> {
> int sock, ret = -1;
> char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
> char *offset = &path[1];
> int len;
> + int stay_connected = cmd->req.cmd == LXC_CMD_CONSOLE;
>
> len = sizeof(path)-1;
> if (fill_sock_name(offset, len, name, lxcpath))
> return -1;
>
> sock = lxc_af_unix_connect(path);
> - if (sock < 0 && errno == ECONNREFUSED) {
> - *stopped = 1;
> - return -1;
> - }
> -
> if (sock < 0) {
> - SYSERROR("failed to connect to '@%s'", offset);
> + if (errno == ECONNREFUSED)
> + *stopped = 1;
> + else
> + SYSERROR("command %s failed to connect to '@%s'",
> + lxc_cmd_str(cmd->req.cmd), offset);
> return -1;
> }
>
> - ret = lxc_af_unix_send_credential(sock, &command->request,
> - sizeof(command->request));
> - if (ret < 0) {
> - SYSERROR("failed to send request to '@%s'", offset);
> + ret = lxc_af_unix_send_credential(sock, &cmd->req, sizeof(cmd->req));
> + if (ret != sizeof(cmd->req)) {
> + SYSERROR("command %s failed to send req to '@%s' %d",
> + lxc_cmd_str(cmd->req.cmd), offset, ret);
> + if (ret >=0)
> + ret = -1;
> goto out;
> }
>
> - if (ret != sizeof(command->request)) {
> - SYSERROR("message partially sent to '@%s'", offset);
> - goto out;
> + if (cmd->req.datalen > 0) {
> + ret = send(sock, cmd->req.data, cmd->req.datalen, 0);
> + if (ret != cmd->req.datalen) {
> + SYSERROR("command %s failed to send request data to '@%s' %d",
> + lxc_cmd_str(cmd->req.cmd), offset, ret);
> + if (ret >=0)
> + ret = -1;
> + goto out;
> + }
> }
>
> - ret = receive_answer(sock, &command->answer);
> + ret = lxc_cmd_rsp_recv(sock, cmd);
> out:
> if (!stay_connected || ret < 0)
> close(sock);
> @@ -148,114 +268,418 @@ out:
> return ret;
> }
>
> -extern int lxc_command(const char *name,
> - struct lxc_command *command, int *stopped,
> - const char *lxcpath)
> +/* Implentations of the commands and their callbacks */
> +
> +/*
> + * lxc_cmd_get_init_pid: Get pid of the container's init process
> + *
> + * @name : name of container to connect to
> + * @lxcpath : the lxcpath in which the container is running
> + *
> + * Returns the pid on success, < 0 on failure
> + */
> +pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
> {
> - return __lxc_command(name, command, stopped, 0, lxcpath);
> + int ret, stopped = 0;
> + struct lxc_cmd_rr cmd = {
> + .req = { .cmd = LXC_CMD_GET_INIT_PID },
> + };
> +
> + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> + if (ret < 0)
> + return ret;
> +
> + return PTR_TO_INT(cmd.rsp.data);
> }
>
> -extern int lxc_command_connected(const char *name,
> - struct lxc_command *command, int *stopped,
> - const char *lxcpath)
> +static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
> + struct lxc_handler *handler)
> {
> - return __lxc_command(name, command, stopped, 1, lxcpath);
> + struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->pid) };
> +
> + return lxc_cmd_rsp_send(fd, &rsp);
> }
>
> +/*
> + * lxc_cmd_get_clone_flags: Get clone flags container was spawned with
> + *
> + * @name : name of container to connect to
> + * @lxcpath : the lxcpath in which the container is running
> + *
> + * Returns the clone flags on success, < 0 on failure
> + */
> +int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
> +{
> + int ret, stopped = 0;
> + struct lxc_cmd_rr cmd = {
> + .req = { .cmd = LXC_CMD_GET_CLONE_FLAGS },
> + };
> +
> + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> + if (ret < 0)
> + return ret;
>
> -pid_t get_init_pid(const char *name, const char *lxcpath)
> + return PTR_TO_INT(cmd.rsp.data);
> +}
> +
> +static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
> + struct lxc_handler *handler)
> {
> - struct lxc_command command = {
> - .request = { .type = LXC_COMMAND_PID },
> + struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->clone_flags) };
> +
> + return lxc_cmd_rsp_send(fd, &rsp);
> +}
> +
> +/*
> + * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
> + * particular subsystem. This is the cgroup path relative to the root
> + * of the cgroup filesystem.
> + *
> + * @subsystem : the cgroup subsystem of interest (i.e. freezer)
> + * @name : name of container to connect to
> + * @lxcpath : the lxcpath in which the container is running
> + *
> + * Returns the path on success, NULL on failure. The caller must free() the
> + * returned path.
> + */
> +char *lxc_cmd_get_cgroup_path(const char *subsystem, const char *name,
> + const char *lxcpath)
> +{
> + int ret, stopped = 0;
> + struct lxc_cmd_rr cmd = {
> + .req = { .cmd = LXC_CMD_GET_CGROUP },
> };
>
> + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> + if (ret < 0)
> + return NULL;
> +
> + if (!ret) {
> + WARN("'%s' has stopped before sending its state", name);
> + return NULL;
> + }
> +
> + if (cmd.rsp.ret < 0 || cmd.rsp.datalen < 0) {
> + ERROR("command %s failed for '%s': %s",
> + lxc_cmd_str(cmd.req.cmd), name,
> + strerror(-cmd.rsp.ret));
> + return NULL;
> + }
> +
> + return cmd.rsp.data;
> +}
> +
> +static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
> + struct lxc_handler *handler)
> +{
> + struct lxc_cmd_rsp rsp = {
> + .datalen = strlen(handler->cgroup) + 1,
> + .data = handler->cgroup,
> + };
> +
> + return lxc_cmd_rsp_send(fd, &rsp);
> +}
> +
> +/*
> + * lxc_cmd_get_config_item: Get config item the running container
> + *
> + * @name : name of container to connect to
> + * @item : the configuration item to retrieve (ex: lxc.network.0.veth.pair)
> + * @lxcpath : the lxcpath in which the container is running
> + *
> + * Returns the item on success, NULL on failure. The caller must free() the
> + * returned item.
> + */
> +char *lxc_cmd_get_config_item(const char *name, const char *item,
> + const char *lxcpath)
> +{
> + int ret, stopped = 0;
> + struct lxc_cmd_rr cmd = {
> + .req = { .cmd = LXC_CMD_GET_CONFIG_ITEM,
> + .data = item,
> + .datalen = strlen(item)+1,
> + },
> + };
> +
> + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> + if (ret < 0)
> + return NULL;
> +
> + if (cmd.rsp.ret == 0)
> + return cmd.rsp.data;
> + return NULL;
> +}
> +
> +static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
> + struct lxc_handler *handler)
> +{
> + int cilen;
> + struct lxc_cmd_rsp rsp;
> + char *cidata;
> +
> + memset(&rsp, 0, sizeof(rsp));
> + cilen = lxc_get_config_item(handler->conf, req->data, NULL, 0);
> + if (cilen <= 0)
> + goto err1;
> +
> + cidata = alloca(cilen + 1);
> + if (lxc_get_config_item(handler->conf, req->data, cidata, cilen + 1) != cilen)
> + goto err1;
> + cidata[cilen] = '\0';
> + rsp.data = cidata;
> + rsp.datalen = cilen + 1;
> + rsp.ret = 0;
> + goto out;
> +
> +err1:
> + rsp.ret = -1;
> +out:
> + return lxc_cmd_rsp_send(fd, &rsp);
> +}
> +
> +/*
> + * lxc_cmd_get_state: Get current state of the container
> + *
> + * @name : name of container to connect to
> + * @lxcpath : the lxcpath in which the container is running
> + *
> + * Returns the state on success, < 0 on failure
> + */
> +lxc_state_t lxc_cmd_get_state(const char *name, const char *lxcpath)
> +{
> int ret, stopped = 0;
> + struct lxc_cmd_rr cmd = {
> + .req = { .cmd = LXC_CMD_GET_STATE }
> + };
>
> - ret = lxc_command(name, &command, &stopped, lxcpath);
> + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> if (ret < 0 && stopped)
> + return STOPPED;
> +
> + if (ret < 0)
> return -1;
>
> + if (!ret) {
> + WARN("'%s' has stopped before sending its state", name);
> + return -1;
> + }
> +
> + DEBUG("'%s' is in '%s' state", name,
> + lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
> + return PTR_TO_INT(cmd.rsp.data);
> +}
> +
> +static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
> + struct lxc_handler *handler)
> +{
> + struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->state) };
> +
> + return lxc_cmd_rsp_send(fd, &rsp);
> +}
> +
> +/*
> + * lxc_cmd_stop: Stop the container previously started with lxc_start. All
> + * the processes running inside this container will be killed.
> + *
> + * @name : name of container to connect to
> + * @lxcpath : the lxcpath in which the container is running
> + *
> + * Returns 0 on success, < 0 on failure
> + */
> +int lxc_cmd_stop(const char *name, const char *lxcpath)
> +{
> + int ret, stopped = 0;
> + struct lxc_cmd_rr cmd = {
> + .req = { .cmd = LXC_CMD_STOP },
> + };
> +
> + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> if (ret < 0) {
> - ERROR("failed to send command");
> + if (stopped) {
> + INFO("'%s' is already stopped", name);
> + return 0;
> + }
> return -1;
> }
>
> - if (command.answer.ret) {
> - ERROR("failed to retrieve the init pid: %s",
> - strerror(-command.answer.ret));
> + /* we do not expect any answer, because we wait for the connection to be
> + * closed
> + */
> + if (ret > 0) {
> + ERROR("failed to stop '%s': %s", name, strerror(-cmd.rsp.ret));
> return -1;
> }
>
> - return command.answer.pid;
> + INFO("'%s' has stopped", name);
> + return 0;
> }
>
> -int lxc_get_clone_flags(const char *name, const char *lxcpath)
> +static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
> + struct lxc_handler *handler)
> {
> - struct lxc_command command = {
> - .request = { .type = LXC_COMMAND_CLONE_FLAGS },
> - };
> + struct lxc_cmd_rsp rsp;
> + int ret;
> + int stopsignal = SIGKILL;
> +
> + if (handler->conf->stopsignal)
> + stopsignal = handler->conf->stopsignal;
> + memset(&rsp, 0, sizeof(rsp));
> + rsp.ret = kill(handler->pid, stopsignal);
> + if (!rsp.ret) {
> + ret = lxc_unfreeze_bypath(handler->cgroup);
> + if (!ret)
> + return 0;
> +
> + ERROR("failed to unfreeze container");
> + rsp.ret = ret;
> + }
> +
> + return lxc_cmd_rsp_send(fd, &rsp);
> +}
>
> +/*
> + * lxc_cmd_console: Open an fd to a tty in the container
> + *
> + * @name : name of container to connect to
> + * @ttynum : in: the tty to open or -1 for next available
> + * : out: the tty allocated
> + * @fd : out: file descriptor for master side of pty
> + * @lxcpath : the lxcpath in which the container is running
> + *
> + * Returns 0 on success, < 0 on failure
> + */
> +int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
> +{
> int ret, stopped = 0;
> + struct lxc_cmd_console_rsp_data *rspdata;
> + struct lxc_cmd_rr cmd = {
> + .req = { .cmd = LXC_CMD_CONSOLE, .data = INT_TO_PTR(*ttynum) },
> + };
>
> - ret = lxc_command(name, &command, &stopped, lxcpath);
> - if (ret < 0 && stopped)
> - return -1;
> + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> + if (ret < 0)
> + return ret;
> + if (ret == 0) {
> + ERROR("console %d invalid or all consoles busy", *ttynum);
> + ret = -1;
> + goto out;
> + }
>
> - if (ret < 0) {
> - ERROR("failed to send command");
> - return -1;
> + ret = -1;
> + #if 1 /* FIXME: how can this happen? */
> + if (cmd.rsp.ret) {
> + ERROR("console access denied: %s",
> + strerror(-cmd.rsp.ret));
> + goto out;
> + }
> + #endif
> +
> + rspdata = cmd.rsp.data;
> + if (rspdata->fd < 0) {
> + ERROR("unable to allocate fd for tty %d", rspdata->ttynum);
> + goto out;
> + }
> +
> + ret = 0;
> + *fd = rspdata->fd;
> + *ttynum = rspdata->ttynum;
> + INFO("tty %d allocated", rspdata->ttynum);
> +out:
> + free(cmd.rsp.data);
> + return ret;
> +}
> +
> +static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
> + struct lxc_handler *handler)
> +{
> + int ttynum = PTR_TO_INT(req->data);
> + struct lxc_tty_info *tty_info = &handler->conf->tty_info;
> + struct lxc_cmd_rsp rsp;
> +
> + if (ttynum > 0) {
> + if (ttynum > tty_info->nbtty)
> + goto out_close;
> +
> + if (tty_info->pty_info[ttynum - 1].busy)
> + goto out_close;
> +
> + /* the requested tty is available */
> + goto out_send;
> }
>
> - return command.answer.ret;
> + /* search for next available tty, fixup index tty1 => [0] */
> + for (ttynum = 1;
> + ttynum <= tty_info->nbtty && tty_info->pty_info[ttynum - 1].busy;
> + ttynum++);
> +
> + /* we didn't find any available slot for tty */
> + if (ttynum > tty_info->nbtty)
> + goto out_close;
> +
> +out_send:
> + memset(&rsp, 0, sizeof(rsp));
> + rsp.data = INT_TO_PTR(ttynum);
> + if (lxc_af_unix_send_fd(fd, tty_info->pty_info[ttynum - 1].master,
> + &rsp, sizeof(rsp)) < 0) {
> + ERROR("failed to send tty to client");
> + goto out_close;
> + }
> +
> + tty_info->pty_info[ttynum - 1].busy = fd;
> + return 0;
> +
> +out_close:
> + /* special indicator to lxc_cmd_handler() to close the fd and do
> + * related cleanup
> + */
> + return 1;
> }
>
> -extern void lxc_console_remove_fd(int, struct lxc_tty_info *);
> -extern int lxc_console_callback(int, struct lxc_request *, struct lxc_handler *);
> -extern int lxc_stop_callback(int, struct lxc_request *, struct lxc_handler *);
> -extern int lxc_state_callback(int, struct lxc_request *, struct lxc_handler *);
> -extern int lxc_pid_callback(int, struct lxc_request *, struct lxc_handler *);
> -extern int lxc_clone_flags_callback(int, struct lxc_request *, struct lxc_handler *);
> -extern int lxc_cgroup_callback(int, struct lxc_request *, struct lxc_handler *);
>
> -static int trigger_command(int fd, struct lxc_request *request,
> +
> +static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
> struct lxc_handler *handler)
> {
> - typedef int (*callback)(int, struct lxc_request *, struct lxc_handler *);
> -
> - callback cb[LXC_COMMAND_MAX] = {
> - [LXC_COMMAND_TTY] = lxc_console_callback,
> - [LXC_COMMAND_STOP] = lxc_stop_callback,
> - [LXC_COMMAND_STATE] = lxc_state_callback,
> - [LXC_COMMAND_PID] = lxc_pid_callback,
> - [LXC_COMMAND_CLONE_FLAGS] = lxc_clone_flags_callback,
> - [LXC_COMMAND_CGROUP] = lxc_cgroup_callback,
> + typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *);
> +
> + callback cb[LXC_CMD_MAX] = {
> + [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
> + [LXC_CMD_STOP] = lxc_cmd_stop_callback,
> + [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
> + [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
> + [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
> + [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
> + [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
> };
>
> - if (request->type < 0 || request->type >= LXC_COMMAND_MAX)
> + if (req->cmd < 0 || req->cmd >= LXC_CMD_MAX) {
> + ERROR("bad cmd %d recieved", req->cmd);
> return -1;
> -
> - return cb[request->type](fd, request, handler);
> + }
> + return cb[req->cmd](fd, req, handler);
> }
>
> -static void command_fd_cleanup(int fd, struct lxc_handler *handler,
> +static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
> struct lxc_epoll_descr *descr)
> {
> + extern void lxc_console_remove_fd(int, struct lxc_tty_info *);
> lxc_console_remove_fd(fd, &handler->conf->tty_info);
> lxc_mainloop_del_handler(descr, fd);
> close(fd);
> }
>
> -static int command_handler(int fd, void *data, struct lxc_epoll_descr *descr)
> +static int lxc_cmd_handler(int fd, void *data, struct lxc_epoll_descr *descr)
> {
> int ret;
> - struct lxc_request request;
> + struct lxc_cmd_req req;
> struct lxc_handler *handler = data;
>
> - ret = lxc_af_unix_rcv_credential(fd, &request, sizeof(request));
> + ret = lxc_af_unix_rcv_credential(fd, &req, sizeof(req));
> if (ret == -EACCES) {
> /* we don't care for the peer, just send and close */
> - struct lxc_answer answer = { .ret = ret };
> - send(fd, &answer, sizeof(answer), 0);
> + struct lxc_cmd_rsp rsp = { .ret = ret };
> +
> + lxc_cmd_rsp_send(fd, &rsp);
> goto out_close;
> }
>
> @@ -269,12 +693,32 @@ static int command_handler(int fd, void *data, struct lxc_epoll_descr *descr)
> goto out_close;
> }
>
> - if (ret != sizeof(request)) {
> + if (ret != sizeof(req)) {
> WARN("partial request, ignored");
> + ret = -1;
> + goto out_close;
> + }
> +
> + if (req.datalen > LXC_CMD_DATA_MAX) {
> + ERROR("cmd data length %d too large", req.datalen);
> + ret = -1;
> goto out_close;
> }
>
> - ret = trigger_command(fd, &request, handler);
> + if (req.datalen > 0) {
> + void *reqdata;
> +
> + reqdata = alloca(req.datalen);
> + ret = recv(fd, reqdata, req.datalen, 0);
> + if (ret != req.datalen) {
> + WARN("partial request, ignored");
> + ret = -1;
> + goto out_close;
> + }
> + req.data = reqdata;
> + }
> +
> + ret = lxc_cmd_process(fd, &req, handler);
> if (ret) {
> /* this is not an error, but only a request to close fd */
> ret = 0;
> @@ -284,12 +728,11 @@ static int command_handler(int fd, void *data, struct lxc_epoll_descr *descr)
> out:
> return ret;
> out_close:
> - command_fd_cleanup(fd, handler, descr);
> + lxc_cmd_fd_cleanup(fd, handler, descr);
> goto out;
> }
>
> -static int incoming_command_handler(int fd, void *data,
> - struct lxc_epoll_descr *descr)
> +static int lxc_cmd_accept(int fd, void *data, struct lxc_epoll_descr *descr)
> {
> int opt = 1, ret = -1, connection;
>
> @@ -310,7 +753,7 @@ static int incoming_command_handler(int fd, void *data,
> goto out_close;
> }
>
> - ret = lxc_mainloop_add_handler(descr, connection, command_handler, data);
> + ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
> if (ret) {
> ERROR("failed to add handler");
> goto out_close;
> @@ -324,8 +767,8 @@ out_close:
> goto out;
> }
>
> -extern int lxc_command_init(const char *name, struct lxc_handler *handler,
> - const char *lxcpath)
> +int lxc_cmd_init(const char *name, struct lxc_handler *handler,
> + const char *lxcpath)
> {
> int fd;
> char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
> @@ -357,14 +800,13 @@ extern int lxc_command_init(const char *name, struct lxc_handler *handler,
> return 0;
> }
>
> -extern int lxc_command_mainloop_add(const char *name,
> - struct lxc_epoll_descr *descr,
> - struct lxc_handler *handler)
> +int lxc_cmd_mainloop_add(const char *name,
> + struct lxc_epoll_descr *descr,
> + struct lxc_handler *handler)
> {
> int ret, fd = handler->conf->maincmd_fd;
>
> - ret = lxc_mainloop_add_handler(descr, fd, incoming_command_handler,
> - handler);
> + ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
> if (ret) {
> ERROR("failed to add handler for command socket");
> close(fd);
> diff --git a/src/lxc/commands.h b/src/lxc/commands.h
> index 3b725fb..b5b4788 100644
> --- a/src/lxc/commands.h
> +++ b/src/lxc/commands.h
> @@ -20,52 +20,67 @@
> * License along with this library; if not, write to the Free Software
> * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> */
> +
> #ifndef __commands_h
> #define __commands_h
>
> -enum {
> - LXC_COMMAND_TTY,
> - LXC_COMMAND_STOP,
> - LXC_COMMAND_STATE,
> - LXC_COMMAND_PID,
> - LXC_COMMAND_CLONE_FLAGS,
> - LXC_COMMAND_CGROUP,
> - LXC_COMMAND_MAX,
> -};
> +#include "state.h"
> +
> +#define LXC_CMD_DATA_MAX (MAXPATHLEN*2)
> +
> +/* https://developer.gnome.org/glib/2.28/glib-Type-Conversion-Macros.html */
> +#define INT_TO_PTR(n) ((void *) (long) (n))
> +#define PTR_TO_INT(p) ((int) (long) (p))
> +
> +typedef enum {
> + LXC_CMD_CONSOLE,
> + LXC_CMD_STOP,
> + LXC_CMD_GET_STATE,
> + LXC_CMD_GET_INIT_PID,
> + LXC_CMD_GET_CLONE_FLAGS,
> + LXC_CMD_GET_CGROUP,
> + LXC_CMD_GET_CONFIG_ITEM,
> + LXC_CMD_MAX,
> +} lxc_cmd_t;
>
> -struct lxc_request {
> - int type;
> - int data;
> +struct lxc_cmd_req {
> + lxc_cmd_t cmd;
> + int datalen;
> + const void *data;
> };
>
> -struct lxc_answer {
> - int fd;
> +struct lxc_cmd_rsp {
> int ret; /* 0 on success, -errno on failure */
> - pid_t pid;
> - int pathlen;
> - const char *path;
> + int datalen;
> + void *data;
> };
>
> -struct lxc_command {
> - struct lxc_request request;
> - struct lxc_answer answer;
> +struct lxc_cmd_rr {
> + struct lxc_cmd_req req;
> + struct lxc_cmd_rsp rsp;
> };
>
> -extern pid_t get_init_pid(const char *name, const char *lxcpath);
> -extern int lxc_get_clone_flags(const char *name, const char *lxcpath);
> -
> -extern int lxc_command(const char *name, struct lxc_command *command,
> - int *stopped, const char *lxcpath);
> +struct lxc_cmd_console_rsp_data {
> + int fd;
> + int ttynum;
> +};
>
> -extern int lxc_command_connected(const char *name, struct lxc_command *command,
> - int *stopped, const char *lxcpath);
> +extern int lxc_cmd_console(const char *name, int *ttynum, int *fd,
> + const char *lxcpath);
> +extern char *lxc_cmd_get_cgroup_path(const char *subsystem,
> + const char *name, const char *lxcpath);
> +extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath);
> +extern char *lxc_cmd_get_config_item(const char *name, const char *item, const char *lxcpath);
> +extern pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath);
> +extern lxc_state_t lxc_cmd_get_state(const char *name, const char *lxcpath);
> +extern int lxc_cmd_stop(const char *name, const char *lxcpath);
>
> struct lxc_epoll_descr;
> struct lxc_handler;
>
> -extern int lxc_command_init(const char *name, struct lxc_handler *handler,
> +extern int lxc_cmd_init(const char *name, struct lxc_handler *handler,
> const char *lxcpath);
> -extern int lxc_command_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
> +extern int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
> struct lxc_handler *handler);
>
> -#endif
> +#endif /* __commands_h */
> diff --git a/src/lxc/console.c b/src/lxc/console.c
> index 9ef62c1..93c16b5 100644
> --- a/src/lxc/console.c
> +++ b/src/lxc/console.c
> @@ -46,49 +46,6 @@
>
> lxc_log_define(lxc_console, lxc);
>
> -extern int lxc_console(const char *name, int ttynum, int *fd, const char *lxcpath)
> -{
> - int ret, stopped = 0;
> - struct lxc_command command = {
> - .request = { .type = LXC_COMMAND_TTY, .data = ttynum },
> - };
> -
> - ret = lxc_command_connected(name, &command, &stopped, lxcpath);
> - if (ret < 0 && stopped) {
> - ERROR("'%s' is stopped", name);
> - return -1;
> - }
> -
> - if (ret < 0) {
> - ERROR("failed to send command");
> - return -1;
> - }
> -
> - if (!ret) {
> - ERROR("console denied by '%s'", name);
> - return -1;
> - }
> -
> - if (command.answer.ret) {
> - ERROR("console access denied: %s",
> - strerror(-command.answer.ret));
> - return -1;
> - }
> -
> - *fd = command.answer.fd;
> - if (*fd <0) {
> - ERROR("unable to allocate fd for tty %d", ttynum);
> - return -1;
> - }
> -
> - INFO("tty %d allocated", ttynum);
> - return 0;
> -}
> -
> -/*----------------------------------------------------------------------------
> - * functions used by lxc-start mainloop
> - * to handle above command request.
> - *--------------------------------------------------------------------------*/
> extern void lxc_console_remove_fd(int fd, struct lxc_tty_info *tty_info)
> {
> int i;
> @@ -104,47 +61,6 @@ extern void lxc_console_remove_fd(int fd, struct lxc_tty_info *tty_info)
> return;
> }
>
> -extern int lxc_console_callback(int fd, struct lxc_request *request,
> - struct lxc_handler *handler)
> -{
> - int ttynum = request->data;
> - struct lxc_tty_info *tty_info = &handler->conf->tty_info;
> -
> - if (ttynum > 0) {
> - if (ttynum > tty_info->nbtty)
> - goto out_close;
> -
> - if (tty_info->pty_info[ttynum - 1].busy)
> - goto out_close;
> -
> - goto out_send;
> - }
> -
> - /* fixup index tty1 => [0] */
> - for (ttynum = 1;
> - ttynum <= tty_info->nbtty && tty_info->pty_info[ttynum - 1].busy;
> - ttynum++);
> -
> - /* we didn't find any available slot for tty */
> - if (ttynum > tty_info->nbtty)
> - goto out_close;
> -
> -out_send:
> - if (lxc_af_unix_send_fd(fd, tty_info->pty_info[ttynum - 1].master,
> - &ttynum, sizeof(ttynum)) < 0) {
> - ERROR("failed to send tty to client");
> - goto out_close;
> - }
> -
> - tty_info->pty_info[ttynum - 1].busy = fd;
> -
> - return 0;
> -
> -out_close:
> - /* the close fd and related cleanup will be done by caller */
> - return 1;
> -}
> -
> static int get_default_console(char **console)
> {
> int fd;
> diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h
> index 9057757..8491ff3 100644
> --- a/src/lxc/lxc.h
> +++ b/src/lxc/lxc.h
> @@ -52,14 +52,6 @@ extern int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf
> const char *lxcpath);
>
> /*
> - * Stop the container previously started with lxc_start, all
> - * the processes running inside this container will be killed.
> - * @name : the name of the container
> - * Returns 0 on success, < 0 otherwise
> - */
> -extern int lxc_stop(const char *name, const char *lxcpath);
> -
> -/*
> * Start the specified command inside an application container
> * @name : the name of the container
> * @argv : an array of char * corresponding to the commande line
> diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
> index e0c253b..efa7d89 100644
> --- a/src/lxc/lxc_attach.c
> +++ b/src/lxc/lxc_attach.c
> @@ -296,7 +296,7 @@ int main(int argc, char *argv[])
> if (ret)
> return ret;
>
> - init_pid = get_init_pid(my_args.name, my_args.lxcpath[0]);
> + init_pid = lxc_cmd_get_init_pid(my_args.name, my_args.lxcpath[0]);
> if (init_pid < 0) {
> ERROR("failed to get the init pid");
> return -1;
> @@ -314,7 +314,7 @@ int main(int argc, char *argv[])
> * by asking lxc-start
> */
> if (namespace_flags == -1) {
> - namespace_flags = lxc_get_clone_flags(my_args.name, my_args.lxcpath[0]);
> + namespace_flags = lxc_cmd_get_clone_flags(my_args.name, my_args.lxcpath[0]);
> /* call failed */
> if (namespace_flags == -1) {
> ERROR("failed to automatically determine the "
> diff --git a/src/lxc/lxc_console.c b/src/lxc/lxc_console.c
> index 795b54c..820794a 100644
> --- a/src/lxc/lxc_console.c
> +++ b/src/lxc/lxc_console.c
> @@ -43,6 +43,7 @@
> #include "log.h"
> #include "mainloop.h"
> #include "arguments.h"
> +#include "commands.h"
>
> lxc_log_define(lxc_console_ui, lxc_console);
>
> @@ -202,13 +203,14 @@ int main(int argc, char *argv[])
> return -1;
> }
>
> - err = lxc_console(my_args.name, my_args.ttynum, &master, my_args.lxcpath[0]);
> + err = lxc_cmd_console(my_args.name, &my_args.ttynum, &master, my_args.lxcpath[0]);
> if (err)
> goto out;
>
> fprintf(stderr, "\n\
> -Type <Ctrl+%1$c q> to exit the console, \
> -<Ctrl+%1$c Ctrl+%1$c> to enter Ctrl+%1$c itself\n",
> +Connected to tty %1$d\n\
> +Type <Ctrl+%2$c q> to exit the console, \
> +<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n", my_args.ttynum,
> 'a' + my_args.escape - 1);
>
> err = setsid();
> diff --git a/src/lxc/lxc_info.c b/src/lxc/lxc_info.c
> index f815b0f..f86626d 100644
> --- a/src/lxc/lxc_info.c
> +++ b/src/lxc/lxc_info.c
> @@ -22,6 +22,7 @@
> */
> #include <stdio.h>
> #include <stdbool.h>
> +#include <stdlib.h>
> #include <unistd.h>
> #include <libgen.h>
> #include <sys/types.h>
> @@ -96,8 +97,13 @@ int main(int argc, char *argv[])
> printf("state:%10s\n", lxc_state2str(ret));
> }
>
> - if (pid)
> - printf("pid:%10d\n", get_init_pid(my_args.name, my_args.lxcpath[0]));
> + if (pid) {
> + pid_t initpid;
> +
> + initpid = lxc_cmd_get_init_pid(my_args.name, my_args.lxcpath[0]);
> + if (initpid >= 0)
> + printf("pid:%10d\n", initpid);
> + }
>
> return 0;
> }
> diff --git a/src/lxc/lxc_kill.c b/src/lxc/lxc_kill.c
> index 9a24209..1fedf1d 100644
> --- a/src/lxc/lxc_kill.c
> +++ b/src/lxc/lxc_kill.c
> @@ -76,7 +76,7 @@ int main(int argc, char *argv[], char *envp[])
> } else
> sig=SIGKILL;
>
> - pid = get_init_pid(my_args.name, my_args.lxcpath[0]);
> + pid = lxc_cmd_get_init_pid(my_args.name, my_args.lxcpath[0]);
> if (pid < 0) {
> ERROR("failed to get the init pid");
> return -1;
> diff --git a/src/lxc/lxc_stop.c b/src/lxc/lxc_stop.c
> index d7c7283..0ed8ca0 100644
> --- a/src/lxc/lxc_stop.c
> +++ b/src/lxc/lxc_stop.c
> @@ -29,6 +29,7 @@
> #include <lxc/log.h>
>
> #include "arguments.h"
> +#include "commands.h"
> #include "utils.h"
>
> static const struct option my_longopts[] = {
> @@ -58,5 +59,5 @@ int main(int argc, char *argv[])
> my_args.progname, my_args.quiet, my_args.lxcpath[0]))
> return -1;
>
> - return lxc_stop(my_args.name, my_args.lxcpath[0]);
> + return lxc_cmd_stop(my_args.name, my_args.lxcpath[0]);
> }
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index 23db6f2..01501e7 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -279,7 +279,7 @@ static pid_t lxcapi_init_pid(struct lxc_container *c)
>
> if (lxclock(c->slock, 0))
> return -1;
> - ret = get_init_pid(c->name, c->config_path);
> + ret = lxc_cmd_get_init_pid(c->name, c->config_path);
> lxcunlock(c->slock);
> return ret;
> }
> @@ -517,7 +517,7 @@ static bool lxcapi_stop(struct lxc_container *c)
> if (!c)
> return false;
>
> - ret = lxc_stop(c->name, c->config_path);
> + ret = lxc_cmd_stop(c->name, c->config_path);
>
> return ret == 0;
> }
> diff --git a/src/lxc/start.c b/src/lxc/start.c
> index 692de44..d43d580 100644
> --- a/src/lxc/start.c
> +++ b/src/lxc/start.c
> @@ -262,90 +262,6 @@ static int signal_handler(int fd, void *data,
> return 1;
> }
>
> -int lxc_pid_callback(int fd, struct lxc_request *request,
> - struct lxc_handler *handler)
> -{
> - struct lxc_answer answer;
> - int ret;
> -
> - memset(&answer, 0, sizeof(answer));
> - answer.pid = handler->pid;
> - answer.ret = 0;
> -
> - ret = send(fd, &answer, sizeof(answer), 0);
> - if (ret < 0) {
> - WARN("failed to send answer to the peer");
> - return -1;
> - }
> -
> - if (ret != sizeof(answer)) {
> - ERROR("partial answer sent");
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> -int lxc_cgroup_callback(int fd, struct lxc_request *request,
> - struct lxc_handler *handler)
> -{
> - struct lxc_answer answer;
> - int ret;
> -
> - memset(&answer, 0, sizeof(answer));
> - answer.pathlen = strlen(handler->cgroup) + 1;
> - answer.path = handler->cgroup;
> - answer.ret = 0;
> -
> - ret = send(fd, &answer, sizeof(answer), 0);
> - if (ret < 0) {
> - WARN("failed to send answer to the peer");
> - return -1;
> - }
> -
> - if (ret != sizeof(answer)) {
> - ERROR("partial answer sent");
> - return -1;
> - }
> -
> - ret = send(fd, answer.path, answer.pathlen, 0);
> - if (ret < 0) {
> - WARN("failed to send answer to the peer");
> - return -1;
> - }
> -
> - if (ret != answer.pathlen) {
> - ERROR("partial answer sent");
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> -int lxc_clone_flags_callback(int fd, struct lxc_request *request,
> - struct lxc_handler *handler)
> -{
> - struct lxc_answer answer;
> - int ret;
> -
> - memset(&answer, 0, sizeof(answer));
> - answer.pid = 0;
> - answer.ret = handler->clone_flags;
> -
> - ret = send(fd, &answer, sizeof(answer), 0);
> - if (ret < 0) {
> - WARN("failed to send answer to the peer");
> - return -1;
> - }
> -
> - if (ret != sizeof(answer)) {
> - ERROR("partial answer sent");
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> int lxc_set_state(const char *name, struct lxc_handler *handler, lxc_state_t state)
> {
> handler->state = state;
> @@ -374,7 +290,7 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
> goto out_mainloop_open;
> }
>
> - if (lxc_command_mainloop_add(name, &descr, handler)) {
> + if (lxc_cmd_mainloop_add(name, &descr, handler)) {
> ERROR("failed to add command handler to mainloop");
> goto out_mainloop_open;
> }
> @@ -426,7 +342,7 @@ struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char
> goto out_free;
> }
>
> - if (lxc_command_init(name, handler, lxcpath))
> + if (lxc_cmd_init(name, handler, lxcpath))
> goto out_free_name;
>
> if (lxc_read_seccomp_config(conf) != 0) {
> diff --git a/src/lxc/state.c b/src/lxc/state.c
> index 68ec00b..ed59535 100644
> --- a/src/lxc/state.c
> +++ b/src/lxc/state.c
> @@ -103,75 +103,14 @@ fail:
> return -1;
> }
>
> -static lxc_state_t __lxc_getstate(const char *name, const char *lxcpath)
> -{
> - struct lxc_command command = {
> - .request = { .type = LXC_COMMAND_STATE },
> - };
> -
> - int ret, stopped = 0;
> -
> - ret = lxc_command(name, &command, &stopped, lxcpath);
> - if (ret < 0 && stopped)
> - return STOPPED;
> -
> - if (ret < 0) {
> - ERROR("failed to send command");
> - return -1;
> - }
> -
> - if (!ret) {
> - WARN("'%s' has stopped before sending its state", name);
> - return -1;
> - }
> -
> - if (command.answer.ret < 0) {
> - ERROR("failed to get state for '%s': %s",
> - name, strerror(-command.answer.ret));
> - return -1;
> - }
> -
> - DEBUG("'%s' is in '%s' state", name, lxc_state2str(command.answer.ret));
> -
> - return command.answer.ret;
> -}
> -
> lxc_state_t lxc_getstate(const char *name, const char *lxcpath)
> {
> lxc_state_t state = freezer_state(name, lxcpath);
> if (state != FROZEN && state != FREEZING)
> - state = __lxc_getstate(name, lxcpath);
> + state = lxc_cmd_get_state(name, lxcpath);
> return state;
> }
>
> -/*----------------------------------------------------------------------------
> - * functions used by lxc-start mainloop
> - * to handle above command request.
> - *--------------------------------------------------------------------------*/
> -extern int lxc_state_callback(int fd, struct lxc_request *request,
> - struct lxc_handler *handler)
> -{
> - struct lxc_answer answer;
> - int ret;
> -
> - memset(&answer, 0, sizeof(answer));
> - answer.ret = handler->state;
> -
> - ret = send(fd, &answer, sizeof(answer), 0);
> - if (ret < 0) {
> - WARN("failed to send answer to the peer");
> - goto out;
> - }
> -
> - if (ret != sizeof(answer)) {
> - ERROR("partial answer sent");
> - goto out;
> - }
> -
> -out:
> - return ret;
> -}
> -
> static int fillwaitedstates(const char *strstates, int *states)
> {
> char *token, *saveptr = NULL;
> diff --git a/src/lxc/stop.c b/src/lxc/stop.c
> deleted file mode 100644
> index 4fb4480..0000000
> --- a/src/lxc/stop.c
> +++ /dev/null
> @@ -1,115 +0,0 @@
> -/*
> - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> - */
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <errno.h>
> -#include <unistd.h>
> -#include <sys/param.h>
> -#include <signal.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <sys/socket.h>
> -#include <fcntl.h>
> -
> -#include <lxc/log.h>
> -#include <lxc/start.h>
> -#include <lxc/conf.h>
> -
> -#include "lxc.h"
> -#include "commands.h"
> -
> -lxc_log_define(lxc_stop, lxc);
> -
> -int lxc_stop(const char *name, const char *lxcpath)
> -{
> - struct lxc_command command = {
> - .request = { .type = LXC_COMMAND_STOP },
> - };
> -
> - int ret, stopped = 0;
> -
> - ret = lxc_command(name, &command,&stopped, lxcpath);
> - if (ret < 0 && stopped) {
> - INFO("'%s' is already stopped", name);
> - return 0;
> - }
> -
> - if (ret < 0) {
> - ERROR("failed to send command");
> - return -1;
> - }
> -
> - /* we do not expect any answer, because we wait for the connection to be
> - * closed
> - */
> - if (ret > 0) {
> - ERROR("failed to stop '%s': %s",
> - name, strerror(-command.answer.ret));
> - return -1;
> - }
> -
> - INFO("'%s' has stopped", name);
> -
> - return 0;
> -}
> -
> -/*----------------------------------------------------------------------------
> - * functions used by lxc-start mainloop
> - * to handle above command request.
> - *--------------------------------------------------------------------------*/
> -extern int lxc_stop_callback(int fd, struct lxc_request *request,
> - struct lxc_handler *handler)
> -{
> - struct lxc_answer answer;
> - int ret;
> - int stopsignal = SIGKILL;
> -
> - if (handler->conf->stopsignal)
> - stopsignal = handler->conf->stopsignal;
> - memset(&answer, 0, sizeof(answer));
> - answer.ret = kill(handler->pid, stopsignal);
> - if (!answer.ret) {
> - ret = lxc_unfreeze_bypath(handler->cgroup);
> - if (!ret)
> - return 0;
> -
> - ERROR("failed to unfreeze container");
> - answer.ret = ret;
> - }
> -
> - ret = send(fd, &answer, sizeof(answer), 0);
> - if (ret < 0) {
> - WARN("failed to send answer to the peer");
> - goto out;
> - }
> -
> - if (ret != sizeof(answer)) {
> - ERROR("partial answer sent");
> - goto out;
> - }
> -
> -out:
> - return -1;
> -}
> -
> diff --git a/src/tests/cgpath.c b/src/tests/cgpath.c
> index d8c3624..b7f0885 100644
> --- a/src/tests/cgpath.c
> +++ b/src/tests/cgpath.c
> @@ -137,7 +137,8 @@ int main()
> }
>
> const char *dirpath;
> - if (lxc_get_cgpath(&dirpath, NULL, c2->name, c2->config_path) < 0) {
> + dirpath = lxc_cmd_get_cgroup_path(NULL, c2->name, c2->config_path);
> + if (!dirpath) {
> TSTERR("getting second container's cgpath");
> goto out;
> }
> @@ -150,6 +151,8 @@ int main()
>
> retv = 0;
> out:
> + if (dirpath)
> + free(dirpath);
> if (c2) {
> c2->stop(c2);
> c2->destroy(c2);
> --
> 1.8.1.4
>
>
> ------------------------------------------------------------------------------
> AlienVault Unified Security Management (USM) platform delivers complete
> security visibility with the essential security capabilities. Easily and
> efficiently configure, manage, and operate all of your security controls
> from a single console and one unified framework. Download a free trial.
> http://p.sf.net/sfu/alienvault_d2d
> _______________________________________________
> Lxc-devel mailing list
> Lxc-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel
More information about the lxc-devel
mailing list