84b277
From 5024f01fec5e6c8fd05ca5451176878084e3f18f Mon Sep 17 00:00:00 2001
84b277
From: David Herrmann <dh.herrmann@gmail.com>
84b277
Date: Wed, 17 Sep 2014 09:06:49 +0200
84b277
Subject: [PATCH] sysctl: make --prefix allow all kinds of sysctl paths
84b277
84b277
Currently, we save arguments passed as --prefix directly and compare them
84b277
later to absolute sysctl file-system paths. That is, you are required to
84b277
specify arguments to --prefix with leading /proc/sys/. This is kinda
84b277
uselesss. Furthermore, we replace dots by slashes in the name, which makes
84b277
it impossible to match on specific sysfs paths that have dots in their
84b277
name (like netdev names). The intention of this argument is clear, but it
84b277
never worked as expected.
84b277
84b277
This patch modifies --prefix to accept any kind of sysctl paths. It
84b277
supports paths prefixed with /proc/sys for compatibility (but drops the
84b277
erroneous dot->slash conversion), but instead applies normalize_sysctl()
84b277
which turns any name or path into a proper path. It then appends
84b277
/proc/sys/ so we can properly use it in matches.
84b277
84b277
Thanks to Jan Synacek <jsynacek@redhat.com> for catching this!
84b277
84b277
Conflicts:
84b277
	src/sysctl/sysctl.c
84b277
84b277
(cherry picked from commit 0e1f579227b08832437a7ac2227c7e4007a89d23)
84b277
84b277
Resolves: #1138591
84b277
---
84b277
 src/sysctl/sysctl.c | 40 +++++++++++++++++++++++++++++-----------
84b277
 1 file changed, 29 insertions(+), 11 deletions(-)
84b277
84b277
diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
84b277
index a9d4d53..d6f48dd 100644
84b277
--- a/src/sysctl/sysctl.c
84b277
+++ b/src/sysctl/sysctl.c
84b277
@@ -51,9 +51,23 @@ static const char conf_file_dirs[] =
84b277
 static char *normalize_sysctl(char *s) {
84b277
         char *n;
84b277
 
84b277
-        for (n = s; *n; n++)
84b277
+        n = strpbrk(s, "/.");
84b277
+        /* If the first separator is a slash, the path is
84b277
+         * assumed to be normalized and slashes remain slashes
84b277
+         * and dots remains dots. */
84b277
+        if (!n || *n == '/')
84b277
+                return s;
84b277
+
84b277
+        /* Otherwise, dots become slashes and slashes become
84b277
+         * dots. Fun. */
84b277
+        while (n) {
84b277
                 if (*n == '.')
84b277
                         *n = '/';
84b277
+                else
84b277
+                        *n = '.';
84b277
+
84b277
+                n = strpbrk(n + 1, "/.");
84b277
+        }
84b277
 
84b277
         return s;
84b277
 }
84b277
@@ -205,7 +219,7 @@ static int help(void) {
84b277
         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
84b277
                "Applies kernel sysctl settings.\n\n"
84b277
                "  -h --help             Show this help\n"
84b277
-               "     --prefix=PATH      Only apply rules that apply to paths with the specified prefix\n",
84b277
+               "     --prefix=PATH      Only apply rules with the specified prefix\n",
84b277
                program_invocation_short_name);
84b277
 
84b277
         return 0;
84b277
@@ -238,18 +252,22 @@ static int parse_argv(int argc, char *argv[]) {
84b277
 
84b277
                 case ARG_PREFIX: {
84b277
                         char *p;
84b277
-                        char **l;
84b277
 
84b277
-                        for (p = optarg; *p; p++)
84b277
-                                if (*p == '.')
84b277
-                                        *p = '/';
84b277
-
84b277
-                        l = strv_append(arg_prefixes, optarg);
84b277
-                        if (!l)
84b277
+                        /* We used to require people to specify absolute paths
84b277
+                         * in /proc/sys in the past. This is kinda useless, but
84b277
+                         * we need to keep compatibility. We now support any
84b277
+                         * sysctl name available. */
84b277
+                        normalize_sysctl(optarg);
84b277
+                        if (startswith(optarg, "/proc/sys"))
84b277
+                                p = strdup(optarg);
84b277
+                        else
84b277
+                                p = strappend("/proc/sys/", optarg);
84b277
+
84b277
+                        if (!p)
84b277
                                 return log_oom();
84b277
 
84b277
-                        strv_free(arg_prefixes);
84b277
-                        arg_prefixes = l;
84b277
+                        if (strv_push(&arg_prefixes, p) < 0)
84b277
+                                return log_oom();
84b277
 
84b277
                         break;
84b277
                 }