/* * 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 request 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 on its side of the socket in its mainloop select and * then free the slot with lxc_cmd_fd_cleanup(). The socket fd will be * returned in the cmd response structure. */ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped, const char *lxcpath, const char *hashed_sock_name) { __do_close_prot_errno int client_fd = -EBADF; int ret = -1; bool stay_connected = false; if (cmd->req.cmd == LXC_CMD_CONSOLE || cmd->req.cmd == LXC_CMD_ADD_STATE_CLIENT) stay_connected = true; *stopped = 0; client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name); if (client_fd < 0) { SYSTRACE("Command \"%s\" failed to connect command socket", lxc_cmd_str(cmd->req.cmd)); if (errno == ECONNREFUSED || errno == EPIPE) *stopped = 1; return -1; } ret = lxc_cmd_rsp_recv(client_fd, cmd); if (ret < 0 && errno == ECONNRESET) *stopped = 1; if (stay_connected && ret > 0) cmd->rsp.ret = move_fd(client_fd); return ret; }
/* * 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 request 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 on its side of the socket in its mainloop select and * then free the slot with lxc_cmd_fd_cleanup(). The socket fd will be * returned in the cmd response structure. */ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped, const char *lxcpath, const char *hashed_sock_name) { int client_fd, saved_errno; int ret = -1; bool stay_connected = false; if (cmd->req.cmd == LXC_CMD_CONSOLE || cmd->req.cmd == LXC_CMD_ADD_STATE_CLIENT) stay_connected = true; *stopped = 0; client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name); if (client_fd < 0) { SYSTRACE("Command \"%s\" failed to connect command socket", lxc_cmd_str(cmd->req.cmd)); if (errno == ECONNREFUSED) *stopped = 1; if (errno == EPIPE) { *stopped = 1; client_fd = 0; } return -1; } ret = lxc_cmd_rsp_recv(client_fd, cmd); if (ret < 0 && errno == ECONNRESET) *stopped = 1; if (!stay_connected || ret <= 0) if (client_fd >= 0) { saved_errno = errno; close(client_fd); errno = saved_errno; } if (stay_connected && ret > 0) cmd->rsp.ret = client_fd; return ret; }