43fe83
From 640ff93b2835c02f2f317912e7e2abb20cf3c35d Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <640ff93b2835c02f2f317912e7e2abb20cf3c35d.1375465853.git.jdenemar@redhat.com>
43fe83
From: "Daniel P. Berrange" <berrange@redhat.com>
43fe83
Date: Wed, 31 Jul 2013 19:48:17 +0100
43fe83
Subject: [PATCH] Add APIs for formatting systemd slice/scope names
43fe83
43fe83
https://bugzilla.redhat.com/show_bug.cgi?id=980929
43fe83
43fe83
There are some interesting escaping rules to consider when dealing
43fe83
with systemd slice/scope names. Thus it is helpful to have APIs
43fe83
for formatting names
43fe83
43fe83
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
43fe83
43fe83
(cherry picked from commit 4574b475df830da437aa6384fd1452cecbb4b7d2)
43fe83
---
43fe83
 src/libvirt_private.syms |  2 ++
43fe83
 src/util/virsystemd.c    | 91 ++++++++++++++++++++++++++++++++++++++++++++++--
43fe83
 src/util/virsystemd.h    |  5 +++
43fe83
 tests/virsystemdtest.c   | 49 ++++++++++++++++++++++++++
43fe83
 4 files changed, 145 insertions(+), 2 deletions(-)
43fe83
43fe83
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
43fe83
index d9615ea..0247a46 100644
43fe83
--- a/src/libvirt_private.syms
43fe83
+++ b/src/libvirt_private.syms
43fe83
@@ -1935,6 +1935,8 @@ virSysinfoSetup;
43fe83
 
43fe83
 # util/virsystemd.h
43fe83
 virSystemdCreateMachine;
43fe83
+virSystemdMakeScopeName;
43fe83
+virSystemdMakeSliceName;
43fe83
 
43fe83
 
43fe83
 # util/virthread.h
43fe83
diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
43fe83
index 11d1153..251b846 100644
43fe83
--- a/src/util/virsystemd.c
43fe83
+++ b/src/util/virsystemd.c
43fe83
@@ -27,9 +27,96 @@
43fe83
 #include "viralloc.h"
43fe83
 #include "virutil.h"
43fe83
 #include "virlog.h"
43fe83
+#include "virerror.h"
43fe83
 
43fe83
 #define VIR_FROM_THIS VIR_FROM_SYSTEMD
43fe83
 
43fe83
+
43fe83
+static void virSystemdEscapeName(virBufferPtr buf,
43fe83
+                                 const char *name)
43fe83
+{
43fe83
+    static const char hextable[16] = "0123456789abcdef";
43fe83
+
43fe83
+#define ESCAPE(c)                                                       \
43fe83
+    do {                                                                \
43fe83
+        virBufferAddChar(buf, '\\');                                    \
43fe83
+        virBufferAddChar(buf, 'x');                                     \
43fe83
+        virBufferAddChar(buf, hextable[(c >> 4) & 15]);                 \
43fe83
+        virBufferAddChar(buf, hextable[c & 15]);                        \
43fe83
+    } while (0)
43fe83
+
43fe83
+#define VALID_CHARS                             \
43fe83
+        "0123456789"                            \
43fe83
+        "abcdefghijklmnopqrstuvwxyz"            \
43fe83
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"            \
43fe83
+        ":-_.\\"
43fe83
+
43fe83
+    if (*name == '.') {
43fe83
+        ESCAPE(*name);
43fe83
+        name++;
43fe83
+    }
43fe83
+
43fe83
+    while (*name) {
43fe83
+        if (*name == '/')
43fe83
+            virBufferAddChar(buf, '-');
43fe83
+        else if (*name == '-' ||
43fe83
+                 *name == '\\' ||
43fe83
+                 !strchr(VALID_CHARS, *name))
43fe83
+            ESCAPE(*name);
43fe83
+        else
43fe83
+            virBufferAddChar(buf, *name);
43fe83
+        name++;
43fe83
+    }
43fe83
+
43fe83
+#undef ESCAPE
43fe83
+#undef VALID_CHARS
43fe83
+}
43fe83
+
43fe83
+
43fe83
+char *virSystemdMakeScopeName(const char *name,
43fe83
+                              const char *drivername,
43fe83
+                              const char *partition)
43fe83
+{
43fe83
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
43fe83
+
43fe83
+    if (*partition == '/')
43fe83
+        partition++;
43fe83
+
43fe83
+    virSystemdEscapeName(&buf, partition);
43fe83
+    virBufferAddChar(&buf, '-');
43fe83
+    virSystemdEscapeName(&buf, drivername);
43fe83
+    virBufferAddLit(&buf, "\\x2d");
43fe83
+    virSystemdEscapeName(&buf, name);
43fe83
+    virBufferAddLit(&buf, ".scope");
43fe83
+
43fe83
+    if (virBufferError(&buf)) {
43fe83
+        virReportOOMError();
43fe83
+        return NULL;
43fe83
+    }
43fe83
+
43fe83
+    return virBufferContentAndReset(&buf;;
43fe83
+}
43fe83
+
43fe83
+
43fe83
+char *virSystemdMakeSliceName(const char *partition)
43fe83
+{
43fe83
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
43fe83
+
43fe83
+    if (*partition == '/')
43fe83
+        partition++;
43fe83
+
43fe83
+    virSystemdEscapeName(&buf, partition);
43fe83
+    virBufferAddLit(&buf, ".slice");
43fe83
+
43fe83
+    if (virBufferError(&buf)) {
43fe83
+        virReportOOMError();
43fe83
+        return NULL;
43fe83
+    }
43fe83
+
43fe83
+    return virBufferContentAndReset(&buf;;
43fe83
+}
43fe83
+
43fe83
+
43fe83
 /**
43fe83
  * virSystemdCreateMachine:
43fe83
  * @name: driver unique name of the machine
43fe83
@@ -75,8 +162,8 @@ int virSystemdCreateMachine(const char *name,
43fe83
         goto cleanup;
43fe83
 
43fe83
     if (partition) {
43fe83
-        if (virAsprintf(&slicename, "%s.slice", partition) < 0)
43fe83
-            goto cleanup;
43fe83
+        if (!(slicename = virSystemdMakeSliceName(partition)))
43fe83
+             goto cleanup;
43fe83
     } else {
43fe83
         if (VIR_STRDUP(slicename, "") < 0)
43fe83
             goto cleanup;
43fe83
diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h
43fe83
index 9ca4e0b..414ae5a 100644
43fe83
--- a/src/util/virsystemd.h
43fe83
+++ b/src/util/virsystemd.h
43fe83
@@ -24,6 +24,11 @@
43fe83
 
43fe83
 # include "internal.h"
43fe83
 
43fe83
+char *virSystemdMakeScopeName(const char *name,
43fe83
+                              const char *drivername,
43fe83
+                              const char *slicename);
43fe83
+char *virSystemdMakeSliceName(const char *partition);
43fe83
+
43fe83
 int virSystemdCreateMachine(const char *name,
43fe83
                             const char *drivername,
43fe83
                             bool privileged,
43fe83
diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c
43fe83
index bcf3ad3..a9c6d32 100644
43fe83
--- a/tests/virsystemdtest.c
43fe83
+++ b/tests/virsystemdtest.c
43fe83
@@ -138,6 +138,38 @@ static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED)
43fe83
     return 0;
43fe83
 }
43fe83
 
43fe83
+
43fe83
+struct testScopeData {
43fe83
+    const char *name;
43fe83
+    const char *partition;
43fe83
+    const char *expected;
43fe83
+};
43fe83
+
43fe83
+static int
43fe83
+testScopeName(const void *opaque)
43fe83
+{
43fe83
+    const struct testScopeData *data = opaque;
43fe83
+    int ret = -1;
43fe83
+    char *actual = NULL;
43fe83
+
43fe83
+    if (!(actual = virSystemdMakeScopeName(data->name,
43fe83
+                                           "lxc",
43fe83
+                                           data->partition)))
43fe83
+        goto cleanup;
43fe83
+
43fe83
+    if (STRNEQ(actual, data->expected)) {
43fe83
+        fprintf(stderr, "Expected '%s' but got '%s'\n",
43fe83
+                data->expected, actual);
43fe83
+        goto cleanup;
43fe83
+    }
43fe83
+
43fe83
+    ret = 0;
43fe83
+
43fe83
+ cleanup:
43fe83
+    VIR_FREE(actual);
43fe83
+    return ret;
43fe83
+}
43fe83
+
43fe83
 static int
43fe83
 mymain(void)
43fe83
 {
43fe83
@@ -152,6 +184,23 @@ mymain(void)
43fe83
     if (virtTestRun("Test create bad systemd ", 1, testCreateBadSystemd, NULL) < 0)
43fe83
         ret = -1;
43fe83
 
43fe83
+#define TEST_SCOPE(name, partition, unitname)                           \
43fe83
+    do {                                                                \
43fe83
+        struct testScopeData data = {                                   \
43fe83
+            name, partition, unitname                                   \
43fe83
+        };                                                              \
43fe83
+        if (virtTestRun("Test scopename", 1, testScopeName, &data) < 0) \
43fe83
+            ret = -1;                                                   \
43fe83
+    } while (0)
43fe83
+
43fe83
+    TEST_SCOPE("demo", "/machine", "machine-lxc\\x2ddemo.scope");
43fe83
+    TEST_SCOPE("demo-name", "/machine", "machine-lxc\\x2ddemo\\x2dname.scope");
43fe83
+    TEST_SCOPE("demo!name", "/machine", "machine-lxc\\x2ddemo\\x21name.scope");
43fe83
+    TEST_SCOPE(".demo", "/machine", "machine-lxc\\x2d\\x2edemo.scope");
43fe83
+    TEST_SCOPE("demo", "/machine/eng-dept", "machine-eng\\x2ddept-lxc\\x2ddemo.scope");
43fe83
+    TEST_SCOPE("demo", "/machine/eng-dept/testing!stuff",
43fe83
+               "machine-eng\\x2ddept-testing\\x21stuff-lxc\\x2ddemo.scope");
43fe83
+
43fe83
     return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
43fe83
 }
43fe83
 
43fe83
-- 
43fe83
1.8.3.2
43fe83