From nobody Tue Nov 26 09:38:12 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1709314238; cv=none; d=zohomail.com; s=zohoarc; b=gFznwUzAEmSZVO9S2kumzerWk9MaPgY/xKcAJ+MPY8bvUvyWecOgWu8gN7IaMHqV2XsKGofwB81j5S9QqU6ooPIiC2MEyDTgcVWzBZWq1PBO6fmIwUj3wpcAS3cTWV78nq22tpVZxOH5rujZv0XwDhXmjrb6y6oiLhyV70WIw6s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709314238; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=GsygPxWNyTKxxDZM8oS5g4+qWI+r/5+qm83ovsg8YcM=; b=nGRP1xt9ZHiWfW4pK4Le6zoMYSENNZK0hLMvwVwIu+oWzIG6w/A1rdmEVWZMWj8/vYBXd5n9MNQvMSH5sMPyr8nCEIdVLw5dO/p5NdiVtMQshnluOdOOn01B4xdRcMTaB+Jr9XMivNqHMyOK+UiAsiEhI9110nXrVXqFGuhtFr0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709314238435300.453712371698; Fri, 1 Mar 2024 09:30:38 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rg6h3-0003o4-VE; Fri, 01 Mar 2024 12:29:09 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rg6h1-0003mX-Tp for qemu-devel@nongnu.org; Fri, 01 Mar 2024 12:29:07 -0500 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rg6gx-0005d0-VY for qemu-devel@nongnu.org; Fri, 01 Mar 2024 12:29:07 -0500 Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1rg6fM-0022sZ-0m; Fri, 01 Mar 2024 18:28:57 +0100 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=GsygPxWNyTKxxDZM8oS5g4+qWI+r/5+qm83ovsg8YcM=; b=qZeClQaVu4KL /XYUTeYpkEmQOhqbNwikPzp0shBV1SVLeSVjebVK5J1TDycMix3esvJDPZ4RYsKo2FTFlKtYNI8Uf OB9TOpDSJoVVxFXaka5sUHqK1dyRmBEymLAqC7NZUUVGqHG483r96jmOxf/ccYElQWWWPVlDngiO3 WWt6TCdg+L9yMy4AFDfQftC1Cn0bGMGzumfcPHSceM2X7gvMX+yN1rm29+B5nXO4r8vFTtWT9lb11 r1RMKHClbi5WpC50IGnnDM8v3+Qd5TKQHkPa6CpkRH6CSBuNYvToDHdVSUykpYjJ6/ATZiZkZQvfG oUUPFZlhg/2X3CFmK9pR6g==; From: Andrey Drobyshev To: qemu-devel@nongnu.org Cc: michael.roth@amd.com, kkostiuk@redhat.com, marcandre.lureau@redhat.com, philmd@linaro.org, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v2 2/7] qga: introduce ga_run_command() helper for guest cmd execution Date: Fri, 1 Mar 2024 19:28:53 +0200 Message-Id: <20240301172858.665135-3-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240301172858.665135-1-andrey.drobyshev@virtuozzo.com> References: <20240301172858.665135-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @virtuozzo.com) X-ZM-MESSAGEID: 1709314238719100001 Content-Type: text/plain; charset="utf-8" When executing guest commands in *nix environment, we repeat the same fork/exec pattern multiple times. Let's just separate it into a single helper which would also be able to feed input data into the launched process' stdin. This way we can avoid code duplication. To keep the history more bisectable, let's replace qmp commands implementations one by one. Also add G_GNUC_UNUSED attribute to the helper and remove it in the next commit. Originally-by: Yuri Pudgorodskiy Signed-off-by: Andrey Drobyshev --- qga/commands-posix.c | 140 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 8207c4c47e..781498418f 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -76,6 +76,146 @@ static void ga_wait_child(pid_t pid, int *status, Error= **errp) g_assert(rpid =3D=3D pid); } =20 +static void ga_pipe_read_str(int fd[2], char **str, size_t *len) +{ + ssize_t n; + char buf[1024]; + close(fd[1]); + fd[1] =3D -1; + while ((n =3D read(fd[0], buf, sizeof(buf))) !=3D 0) { + if (n < 0) { + if (errno =3D=3D EINTR) { + continue; + } else { + break; + } + } + *str =3D g_realloc(*str, *len + n); + memcpy(*str + *len, buf, n); + *len +=3D n; + } + close(fd[0]); + fd[0] =3D -1; +} + +/* + * Helper to run command with input/output redirection, + * sending string to stdin and taking error message from + * stdout/err. + */ +G_GNUC_UNUSED +static int ga_run_command(const char *argv[], const char *in_str, + const char *action, Error **errp) +{ + pid_t pid; + int status; + int retcode =3D -1; + int infd[2] =3D { -1, -1 }; + int outfd[2] =3D { -1, -1 }; + char *str =3D NULL; + size_t len =3D 0; + + if ((in_str && !g_unix_open_pipe(infd, FD_CLOEXEC, NULL)) || + !g_unix_open_pipe(outfd, FD_CLOEXEC, NULL)) { + error_setg(errp, "cannot create pipe FDs"); + goto out; + } + + pid =3D fork(); + if (pid =3D=3D 0) { + char *cherr =3D NULL; + + setsid(); + + if (in_str) { + /* Redirect stdin to infd. */ + close(infd[1]); + dup2(infd[0], 0); + close(infd[0]); + } else { + reopen_fd_to_null(0); + } + + /* Redirect stdout/stderr to outfd. */ + close(outfd[0]); + dup2(outfd[1], 1); + dup2(outfd[1], 2); + close(outfd[1]); + + execvp(argv[0], (char *const *)argv); + + /* Write the cause of failed exec to pipe for the parent to read i= t. */ + cherr =3D g_strdup_printf("failed to exec '%s'", argv[0]); + perror(cherr); + g_free(cherr); + _exit(EXIT_FAILURE); + } else if (pid < 0) { + error_setg_errno(errp, errno, "failed to create child process"); + goto out; + } + + if (in_str) { + close(infd[0]); + infd[0] =3D -1; + if (qemu_write_full(infd[1], in_str, strlen(in_str)) !=3D + strlen(in_str)) { + error_setg_errno(errp, errno, "%s: cannot write to stdin pipe", + action); + goto out; + } + close(infd[1]); + infd[1] =3D -1; + } + + ga_pipe_read_str(outfd, &str, &len); + + ga_wait_child(pid, &status, errp); + if (*errp) { + goto out; + } + + if (!WIFEXITED(status)) { + if (len) { + error_setg(errp, "child process has terminated abnormally: %s", + str); + } else { + error_setg(errp, "child process has terminated abnormally"); + } + goto out; + } + + retcode =3D WEXITSTATUS(status); + + if (WEXITSTATUS(status)) { + if (len) { + error_setg(errp, "child process has failed to %s: %s", + action, str); + } else { + error_setg(errp, "child process has failed to %s: exit status = %d", + action, WEXITSTATUS(status)); + } + goto out; + } + +out: + g_free(str); + + if (infd[0] !=3D -1) { + close(infd[0]); + } + if (infd[1] !=3D -1) { + close(infd[1]); + } + if (outfd[0] !=3D -1) { + close(outfd[0]); + } + if (outfd[1] !=3D -1) { + close(outfd[1]); + } + + return retcode; +} + void qmp_guest_shutdown(const char *mode, Error **errp) { const char *shutdown_flag; --=20 2.39.3