[libvirt] [PATCH 3/5] virStorageBackendIQNFound: Rework iscsiadm output parsing

Michal Privoznik mprivozn at redhat.com
Fri Jun 29 15:01:49 UTC 2018


Firstly, we can utilize virCommandSetOutputBuffer() API which
will collect the command output for us. Secondly, sscanf()-ing
through each line is easier to understand (and more robust) than
jumping over a string with strchr().

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/util/viriscsi.c | 85 +++++++++++++++++++++--------------------------------
 1 file changed, 34 insertions(+), 51 deletions(-)

diff --git a/src/util/viriscsi.c b/src/util/viriscsi.c
index 2e55b3c10b..44788056fd 100644
--- a/src/util/viriscsi.c
+++ b/src/util/viriscsi.c
@@ -108,7 +108,6 @@ virISCSIGetSession(const char *devpath,
 
 
 
-#define LINE_SIZE 4096
 #define IQN_FOUND 1
 #define IQN_MISSING 0
 #define IQN_ERROR -1
@@ -117,71 +116,56 @@ static int
 virStorageBackendIQNFound(const char *initiatoriqn,
                           char **ifacename)
 {
-    int ret = IQN_ERROR, fd = -1;
-    char ebuf[64];
-    FILE *fp = NULL;
-    char *line = NULL, *newline = NULL, *iqn = NULL, *token = NULL;
+    int ret = IQN_ERROR;
+    char *outbuf = NULL;
+    char *line = NULL;
+    char *iface = NULL;
+    char *iqn = NULL;
     virCommandPtr cmd = virCommandNewArgList(ISCSIADM,
                                              "--mode", "iface", NULL);
 
     *ifacename = NULL;
 
-    if (VIR_ALLOC_N(line, LINE_SIZE) != 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Could not allocate memory for output of '%s'"),
-                       ISCSIADM);
+    virCommandSetOutputBuffer(cmd, &outbuf);
+    if (virCommandRun(cmd, NULL) < 0)
         goto cleanup;
-    }
 
-    memset(line, 0, LINE_SIZE);
+    /* Example of data we are dealing with:
+     * default tcp,<empty>,<empty>,<empty>,<empty>
+     * iser iser,<empty>,<empty>,<empty>,<empty>
+     * libvirt-iface-253db048 tcp,<empty>,<empty>,<empty>,iqn.2017-03.com.user:client
+     */
 
-    virCommandSetOutputFD(cmd, &fd);
-    if (virCommandRunAsync(cmd, NULL) < 0)
-        goto cleanup;
+    line = outbuf;
+    while (line) {
+        char *newline;
+        int num;
 
-    if ((fp = VIR_FDOPEN(fd, "r")) == NULL) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Failed to open stream for file descriptor "
-                         "when reading output from '%s': '%s'"),
-                       ISCSIADM, virStrerror(errno, ebuf, sizeof(ebuf)));
-        goto cleanup;
-    }
+        if (!(newline = strchr(line, '\n')))
+            break;
 
-    while (fgets(line, LINE_SIZE, fp) != NULL) {
-        newline = strrchr(line, '\n');
-        if (newline == NULL) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unexpected line > %d characters "
-                             "when parsing output of '%s'"),
-                           LINE_SIZE, ISCSIADM);
-            goto cleanup;
-        }
         *newline = '\0';
 
-        iqn = strrchr(line, ',');
-        if (iqn == NULL)
-            continue;
-        iqn++;
+        VIR_FREE(iface);
+        VIR_FREE(iqn);
+        num = sscanf(line, "%ms %*[^,],%*[^,],%*[^,],%*[^,],%ms", &iface, &iqn);
+
+        if (num != 2) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("malformed output of %s: %s"),
+                           ISCSIADM, line);
+            goto cleanup;
+        }
 
         if (STREQ(iqn, initiatoriqn)) {
-            token = strchr(line, ' ');
-            if (!token) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Missing space when parsing output "
-                                 "of '%s'"), ISCSIADM);
-                goto cleanup;
-            }
-
-            if (VIR_STRNDUP(*ifacename, line, token - line) < 0)
-                goto cleanup;
+            VIR_STEAL_PTR(*ifacename, iface);
 
             VIR_DEBUG("Found interface '%s' with IQN '%s'", *ifacename, iqn);
             break;
         }
-    }
 
-    if (virCommandWait(cmd, NULL) < 0)
-        goto cleanup;
+        line = newline + 1;
+    }
 
     ret = *ifacename ? IQN_FOUND : IQN_MISSING;
 
@@ -189,11 +173,10 @@ virStorageBackendIQNFound(const char *initiatoriqn,
     if (ret != IQN_FOUND)
         VIR_DEBUG("Could not find interface with IQN '%s'", iqn);
 
-    VIR_FREE(line);
-    VIR_FORCE_FCLOSE(fp);
-    VIR_FORCE_CLOSE(fd);
+    VIR_FREE(iqn);
+    VIR_FREE(iface);
+    VIR_FREE(outbuf);
     virCommandFree(cmd);
-
     return ret;
 }
 
-- 
2.16.4




More information about the libvir-list mailing list