[git commit] sysctl: fix compatibility with procps sysctl

Denys Vlasenko vda.linux at googlemail.com
Fri Feb 8 15:52:51 UTC 2019


commit: https://git.busybox.net/busybox/commit/?id=c89764c0633670ef28166c70d03bc593f4a1179f
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Busybox sysctl is incompatible with procps when '.' appears in
directory name, mostly happens with VLANs.

        busybox syntax (since 2008): net.ipv4.conf.eth0.100.mc_forwarding
         procps syntax (since 2002): net.ipv4.conf.eth0/100.mc_forwarding
                 (supported by both: net/ipv4/conf/eth0.100/mc_forwarding)

Use procps syntax for output; for input, allow both.

function                                             old     new   delta
sysctl_dots_to_slashes                                86     143     +57
sysctl_act_on_setting                                443     453     +10
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 67/0)               Total: 67 bytes

Signed-off-by: Aaro Koskinen <aaro.koskinen at nokia.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 procps/sysctl.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/procps/sysctl.c b/procps/sysctl.c
index 5303460f9..6d77185ca 100644
--- a/procps/sysctl.c
+++ b/procps/sysctl.c
@@ -56,9 +56,32 @@ enum {
 
 static void sysctl_dots_to_slashes(char *name)
 {
-	char *cptr, *last_good, *end;
+	char *cptr, *last_good, *end, *slash;
 	char end_ch;
 
+	end = strchrnul(name, '=');
+
+	slash = strchrnul(name, '/');
+	if (slash < end
+	 && strchrnul(name, '.') < slash
+	) {
+		/* There are both dots and slashes, and 1st dot is
+		 * before 1st slash.
+		 * (IOW: not raw, unmangled a/b/c.d format)
+		 *
+		 * procps supports this syntax for names with dots:
+		 *  net.ipv4.conf.eth0/100.mc_forwarding
+		 * (dots and slashes are simply swapped)
+		 */
+		while (end != name) {
+			end--;
+			if (*end == '.') *end = '/';
+			else if (*end == '/') *end = '.';
+		}
+		return;
+	}
+	/* else: use our old behavior: */
+
 	/* Convert minimum number of '.' to '/' so that
 	 * we end up with existing file's name.
 	 *
@@ -77,7 +100,6 @@ static void sysctl_dots_to_slashes(char *name)
 	 *
 	 * To set up testing: modprobe 8021q; vconfig add eth0 100
 	 */
-	end = strchrnul(name, '=');
 	end_ch = *end;
 	*end = '.'; /* trick the loop into trying full name too */
 
@@ -114,6 +136,8 @@ static int sysctl_act_on_setting(char *setting)
 	while (*cptr) {
 		if (*cptr == '/')
 			*cptr = '.';
+		else if (*cptr == '.')
+			*cptr = '/';
 		cptr++;
 	}
 


More information about the busybox-cvs mailing list