From patchwork Fri Jun 19 16:51:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Denis V. Lunev" X-Patchwork-Id: 486799 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 7DF1B1401DE for ; Sat, 20 Jun 2015 02:48:54 +1000 (AEST) Received: from localhost ([::1]:59144 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5zTI-0007uK-MQ for incoming@patchwork.ozlabs.org; Fri, 19 Jun 2015 12:48:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41631) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5zSi-0006iR-9H for qemu-devel@nongnu.org; Fri, 19 Jun 2015 12:48:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z5zSh-0007cF-70 for qemu-devel@nongnu.org; Fri, 19 Jun 2015 12:48:16 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:30456 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5zSg-0007be-Pc for qemu-devel@nongnu.org; Fri, 19 Jun 2015 12:48:15 -0400 Received: from hades.sw.ru ([10.30.8.132]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id t5JGlp1h026593; Fri, 19 Jun 2015 19:48:00 +0300 (MSK) From: "Denis V. Lunev" To: Date: Fri, 19 Jun 2015 19:51:28 +0300 Message-Id: <1434732693-24127-6-git-send-email-den@openvz.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1434732693-24127-1-git-send-email-den@openvz.org> References: <1434732693-24127-1-git-send-email-den@openvz.org> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x X-Received-From: 195.214.232.25 Cc: Michael Roth , Olga Krishtal , qemu-devel@nongnu.org, "Denis V. Lunev" Subject: [Qemu-devel] [PATCH 05/10] qga: guest-pipe-open for Windows guest X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Olga Krishtal The patch creates anonymous pipe that can be passed as stdin/stdout/stderr handle to a child process spawned using forthcoming guest-file-exec command. Working with a pipe is done using the existing guest-file-* API. Signed-off-by: Olga Krishtal Signed-off-by: Denis V. Lunev CC: Eric Blake CC: Michael Roth --- qga/commands-win32.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 3db7255..b216628 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -21,6 +21,7 @@ #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" #include "qemu/queue.h" +#include "qemu/sockets.h" #ifndef SHTDN_REASON_FLAG_PLANNED #define SHTDN_REASON_FLAG_PLANNED 0x80000000 @@ -37,6 +38,7 @@ typedef struct GuestFileHandle { int64_t id; HANDLE fh; + HANDLE pipe_other_end_fd; /* if set, it's a pipe fd of the other end. */ QTAILQ_ENTRY(GuestFileHandle) next; } GuestFileHandle; @@ -84,7 +86,8 @@ static OpenFlags *find_open_flag(const char *mode_str) return NULL; } -static int64_t guest_file_handle_add(HANDLE fh, Error **errp) +static int64_t guest_file_handle_add(HANDLE fh, HANDLE pipe_other_end_fd, + Error **errp) { GuestFileHandle *gfh; int64_t handle; @@ -96,6 +99,7 @@ static int64_t guest_file_handle_add(HANDLE fh, Error **errp) gfh = g_malloc0(sizeof(GuestFileHandle)); gfh->id = handle; gfh->fh = fh; + gfh->pipe_other_end_fd = pipe_other_end_fd; QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next); return handle; @@ -143,7 +147,7 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, return -1; } - fd = guest_file_handle_add(fh, errp); + fd = guest_file_handle_add(fh, INVALID_HANDLE_VALUE, errp); if (fd < 0) { CloseHandle(&fh); error_setg(errp, "failed to add handle to qmp handle table"); @@ -154,12 +158,68 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, return fd; } +/* Create an anonymous pipe. To set NOWAIT mode is done via qemu_set_nonblock * + * will fail with ERROR_NO_DATA; WriteFile() will return 0 bytes written. */ GuestPipeInfoList *qmp_guest_pipe_open(GuestPipeMode mode, Error **errp) { - error_set(errp, QERR_UNSUPPORTED); + HANDLE fd[2]; + int this_end, other_end; + int64_t handle; + GuestPipeInfoList *pipe_list; + GuestPipeInfo *pipe_inf; + SECURITY_ATTRIBUTES sa = { + sizeof(SECURITY_ATTRIBUTES), NULL, 0 + }; + + slog("guest-pipe-open called"); + if (mode > 2) { + error_set(errp, ERROR_CLASS_GENERIC_ERROR, + "Only \"r\" or \"w\" are the valid modes to open a pipe"); + return NULL; + } + + if (!CreatePipe(&fd[0], &fd[1], &sa, 0)) { + error_setg_win32(errp, GetLastError(), "CreatePipe() failed"); + return NULL; + } + + this_end = (mode == GUEST_PIPE_MODE_WRITE); + other_end = !this_end; + + qemu_set_nonblock(_open_osfhandle((intptr_t)fd[this_end], O_WRONLY)); + + handle = guest_file_handle_add(fd[this_end], fd[other_end], errp); + if (handle == -1) { + goto fail; + } + + slog("guest-pipe-open: handle: %" PRId64, handle); + + pipe_inf = g_malloc0(sizeof(*pipe_inf)); + pipe_inf->fd = handle; + pipe_list = g_malloc0(sizeof(*pipe_list)); + pipe_list->value = pipe_inf; + pipe_list->next = NULL; + return pipe_list; + +fail: + CloseHandle(fd[0]); + CloseHandle(fd[1]); return NULL; } +static int guest_pipe_close_other_end(GuestFileHandle *gfh) +{ + if (gfh->pipe_other_end_fd != INVALID_HANDLE_VALUE) { + if (!CloseHandle(gfh->pipe_other_end_fd)) { + return 1; + } + gfh->pipe_other_end_fd = INVALID_HANDLE_VALUE; + } + + return 0; + } + void qmp_guest_file_close(int64_t handle, Error **errp) { bool ret; @@ -168,6 +228,12 @@ void qmp_guest_file_close(int64_t handle, Error **errp) if (gfh == NULL) { return; } + + if (guest_pipe_close_other_end(gfh) != 0) { + error_setg_win32(errp, GetLastError(), "failed to close pipe handle"); + return; + } + ret = CloseHandle(gfh->fh); if (!ret) { error_setg_win32(errp, GetLastError(), "failed close handle"); @@ -737,7 +803,7 @@ GList *ga_command_blacklist_init(GList *blacklist) "guest-get-memory-blocks", "guest-set-memory-blocks", "guest-get-memory-block-size", "guest-fsfreeze-freeze-list", "guest-get-fsinfo", - "guest-fstrim", "guest-pipe-open", "guest-exec-status", + "guest-fstrim", "guest-exec-status", "guest-exec", NULL}; char **p = (char **)list_unsupported;