]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virdnsmasq: Lookup DNSMASQ in PATH
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 10 Jan 2022 15:19:31 +0000 (16:19 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 18 Jan 2022 14:19:47 +0000 (15:19 +0100)
While it's true that our virCommand subsystem is happy with
non-absolute paths, the dnsmasq capability code is not. It stores
the path to dnsmasq within and makes it accessible via
dnsmasqCapsGetBinaryPath(). While strictly speaking no caller
necessarily needs canonicalized path, let's find dnsmasq once and
cache the result.

Therefore, when constructing the capabilities structure look up
the binary path. If DNSMASQ already contains an absolute path
then virFindFileInPath() will simply return a copy.

With this code in place, the virFileIsExecutable() check can be
removed from dnsmasqCapsRefreshInternal() because
virFindFileInPath() already made sure the binary is executable.

But introducing virFindFileInPath() means we have to mock it in
test suite because dnsmasqCaps are created in
networkxml2conftest.

Moreover, we don't need to check for dnsmasq in configure.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
meson.build
src/util/virdnsmasq.c
tests/meson.build
tests/networkxml2conftest.c
tests/virdnsmasqmock.c [new file with mode: 0644]

index c2e9619f1f4729f6829fcd4a0ba13aed7b3013db..70843afcd546537dc626b94961fad9bb643ec9ee 100644 (file)
@@ -813,7 +813,6 @@ endforeach
 optional_programs = [
   'augparse',
   'dmidecode',
-  'dnsmasq',
   'ebtables',
   'flake8',
   'ip',
index 5bed8817e5d0ca7d88aad78f0c9d5ca60964f205..579c67d86a2047b798df9cc8bedfeaa4137a2fbe 100644 (file)
@@ -46,6 +46,7 @@
 
 VIR_LOG_INIT("util.dnsmasq");
 
+#define DNSMASQ "dnsmasq"
 #define DNSMASQ_HOSTSFILE_SUFFIX "hostsfile"
 #define DNSMASQ_ADDNHOSTSFILE_SUFFIX "addnhosts"
 
@@ -650,16 +651,6 @@ dnsmasqCapsRefreshInternal(dnsmasqCaps *caps)
     g_autoptr(virCommand) vercmd = NULL;
     g_autofree char *version = NULL;
 
-    /* Make sure the binary we are about to try exec'ing exists.
-     * Technically we could catch the exec() failure, but that's
-     * in a sub-process so it's hard to feed back a useful error.
-     */
-    if (!virFileIsExecutable(caps->binaryPath)) {
-        virReportSystemError(errno, _("dnsmasq binary %s is not executable"),
-                             caps->binaryPath);
-        return -1;
-    }
-
     vercmd = virCommandNewArgList(caps->binaryPath, "--version", NULL);
     virCommandSetOutputBuffer(vercmd, &version);
     virCommandAddEnvPassCommon(vercmd);
@@ -679,7 +670,13 @@ dnsmasqCapsNewEmpty(void)
         return NULL;
     if (!(caps = virObjectNew(dnsmasqCapsClass)))
         return NULL;
-    caps->binaryPath = g_strdup(DNSMASQ);
+
+    if (!(caps->binaryPath = virFindFileInPath(DNSMASQ))) {
+        virReportSystemError(ENOENT, "%s",
+                             _("Unable to find 'dnsmasq' binary in $PATH"));
+        return NULL;
+    }
+
     return g_steal_pointer(&caps);
 }
 
index 4792220b48d68710cda1fa97adecc6c337634902..8f92f2033f63eff7192d486af859102eedf43eb9 100644 (file)
@@ -59,6 +59,7 @@ mock_libs = [
   { 'name': 'domaincapsmock' },
   { 'name': 'shunload', 'sources': [ 'shunloadhelper.c' ] },
   { 'name': 'vircgroupmock' },
+  { 'name': 'virdnsmasqmock' },
   { 'name': 'virfilecachemock' },
   { 'name': 'virfirewallmock' },
   { 'name': 'virgdbusmock' },
index 6a2c70ead19d65e792f6307457e2b0e09cd46351..13257c749b2142430e57184d9eac8f2f5f50fbb5 100644 (file)
@@ -158,4 +158,5 @@ mymain(void)
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
-VIR_TEST_MAIN(mymain)
+VIR_TEST_MAIN_PRELOAD(mymain,
+                      VIR_TEST_MOCK("virdnsmasq"))
diff --git a/tests/virdnsmasqmock.c b/tests/virdnsmasqmock.c
new file mode 100644 (file)
index 0000000..448332e
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include "virfile.h"
+
+char *
+virFindFileInPath(const char *file)
+{
+    if (STREQ_NULLABLE(file, "dnsmasq"))
+        return g_strdup("/usr/sbin/dnsmasq");
+
+    /* We should not need any other binaries so return NULL. */
+    return NULL;
+}