[PATCH 01/22] util: command: Introduce virCommandToStringBuf

Peter Krempa pkrempa at redhat.com
Fri Jun 11 14:48:52 UTC 2021


The new version allows passing a virBuffer to format the string into.
This will be helpful in solving a memory lean in wrong usage of
virCommandToString and also in tests where we need to add a newline
after the command in certain cases.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/libvirt_private.syms |  1 +
 src/util/vircommand.c    | 50 +++++++++++++++++++++++++---------------
 src/util/vircommand.h    |  4 ++++
 3 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0ced2a7990..9700e14def 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2037,6 +2037,7 @@ virCommandSetUID;
 virCommandSetUmask;
 virCommandSetWorkingDirectory;
 virCommandToString;
+virCommandToStringBuf;
 virCommandToStringFull;
 virCommandWait;
 virCommandWriteArgLog;
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 6e01e4cb62..8e372c3152 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -2053,8 +2053,9 @@ virCommandWriteArgLog(virCommand *cmd, int logfd)


 /**
- * virCommandToStringFull:
+ * virCommandToStringBuf:
  * @cmd: the command to convert
+ * @buf: buffer to format @cmd into
  * @linebreaks: true to break line after each env var or option
  * @stripCommandPath: strip the path leading to the binary of @cmd
  *
@@ -2062,16 +2063,15 @@ virCommandWriteArgLog(virCommand *cmd, int logfd)
  * before Run/RunAsync, to return a string representation of the
  * environment and arguments of cmd, suitably quoted for pasting into
  * a shell.  If virCommandRun cannot succeed (because of an
- * out-of-memory condition while building cmd), NULL will be returned.
- * Caller is responsible for freeing the resulting string.
+ * out-of-memory condition while building cmd), -1 will be returned.
  */
-char *
-virCommandToStringFull(virCommand *cmd,
-                       bool linebreaks,
-                       bool stripCommandPath)
+int
+virCommandToStringBuf(virCommand *cmd,
+                      virBuffer *buf,
+                      bool linebreaks,
+                      bool stripCommandPath)
 {
     size_t i;
-    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
     const char *command = cmd->args[0];
     g_autofree char *basename = NULL;
     bool had_option = false;
@@ -2080,7 +2080,7 @@ virCommandToStringFull(virCommand *cmd,
      * now.  If virCommandRun is called, it will report the same error. */
     if (virCommandHasError(cmd)) {
         virCommandRaiseError(cmd);
-        return NULL;
+        return -1;
     }

     for (i = 0; i < cmd->nenv; i++) {
@@ -2091,22 +2091,22 @@ virCommandToStringFull(virCommand *cmd,
         if (!eq) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("invalid use of command API"));
-            return NULL;
+            return -1;
         }
         eq++;
-        virBufferAdd(&buf, cmd->env[i], eq - cmd->env[i]);
-        virBufferEscapeShell(&buf, eq);
-        virBufferAddChar(&buf, ' ');
+        virBufferAdd(buf, cmd->env[i], eq - cmd->env[i]);
+        virBufferEscapeShell(buf, eq);
+        virBufferAddChar(buf, ' ');
         if (linebreaks)
-            virBufferAddLit(&buf, "\\\n");
+            virBufferAddLit(buf, "\\\n");
     }

     if (stripCommandPath)
         command = basename = g_path_get_basename(command);

-    virBufferEscapeShell(&buf, command);
+    virBufferEscapeShell(buf, command);
     for (i = 1; i < cmd->nargs; i++) {
-        virBufferAddChar(&buf, ' ');
+        virBufferAddChar(buf, ' ');

         if (linebreaks) {
             /* we don't want a linebreak only if
@@ -2131,11 +2131,25 @@ virCommandToStringFull(virCommand *cmd,
             }

             if (linebreak)
-                virBufferAddLit(&buf, "\\\n");
+                virBufferAddLit(buf, "\\\n");
         }
-        virBufferEscapeShell(&buf, cmd->args[i]);
+        virBufferEscapeShell(buf, cmd->args[i]);
     }

+    return 0;
+}
+
+
+char *
+virCommandToStringFull(virCommand *cmd,
+                       bool linebreaks,
+                       bool stripCommandPath)
+{
+    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+
+    if (virCommandToStringBuf(cmd, &buf, linebreaks, stripCommandPath))
+        return NULL;
+
     return virBufferContentAndReset(&buf);
 }

diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index 77cf8c8ec9..fb6c3b5d12 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -173,6 +173,10 @@ char *virCommandToString(virCommand *cmd, bool linebreaks) G_GNUC_WARN_UNUSED_RE
 char *virCommandToStringFull(virCommand *cmd,
                              bool linebreaks,
                              bool stripCommandPath);
+int virCommandToStringBuf(virCommand *cmd,
+                          virBuffer *buf,
+                          bool linebreaks,
+                          bool stripCommandPath);

 int virCommandGetArgList(virCommand *cmd, char ***args, size_t *nargs);

-- 
2.31.1




More information about the libvir-list mailing list