sysctl: print dotted keys again

When the globbing update was put into sysctl, you could no longer
simply use the keys because one key could potentially be
multiple paths once the glob expansion occured.  Using the path
instead gave a unique output.

Except certain programs, such as salt, expected the output to use
the dotted path "kernel.hostname" and not "kernel/hostname".

We can no longer use the original key, so now for each path:
  Copy the path
  strip off /proc/
  convert all / to .

The sysctl testsuite was also updated to check for a few different
types of conversion failures.

References:
 commit 6389deca5b
 https://www.freelists.org/post/procps/some-procpsn4400-fixes,4
 https://repo.saltproject.io/

Signed-off-by: Craig Small <csmall@dropbear.xyz>
This commit is contained in:
Craig Small 2022-04-09 14:18:28 +10:00
parent 99fed92200
commit a7aaeaef65
4 changed files with 44 additions and 14 deletions

10
NEWS
View File

@ -1,4 +1,14 @@
procps-ng-NEXT procps-ng-NEXT
<<<<<<< HEAD
=======
* library
Re-add elogind support merge #151
* ps: threads again display when -L is used with -q issue #234
* ps: proper aix format string behavior was restored
* sysctl: print dotted keys again
procps-ng-4.0.0
>>>>>>> b159c198 (sysctl: print dotted keys again)
--------------- ---------------
* Rename pwait to pidwait * Rename pwait to pidwait
* sysctl: Add support for systemd glob patterns issue #191 * sysctl: Add support for systemd glob patterns issue #191

View File

@ -152,7 +152,7 @@ static SysctlSetting *setting_new(
strcat(path + proc_len, key+1); strcat(path + proc_len, key+1);
else else
strcat(path + proc_len, key); strcat(path + proc_len, key);
/* change . to / */ /* change . to / for path */
slashdot(path + proc_len, '.', '/'); slashdot(path + proc_len, '.', '/');
s = xmalloc(sizeof(SysctlSetting)); s = xmalloc(sizeof(SysctlSetting));
@ -511,6 +511,7 @@ static int WriteSetting(
int rc = EXIT_SUCCESS; int rc = EXIT_SUCCESS;
FILE *fp; FILE *fp;
struct stat ts; struct stat ts;
char *dotted_key;
if (!key || !path) if (!key || !path)
return rc; return rc;
@ -523,13 +524,22 @@ static int WriteSetting(
return rc; return rc;
} }
/* Convert the globbed path into a dotted key */
if ( (dotted_key = strdup(path + strlen(PROC_PATH))) == NULL) {
xerrx(EXIT_FAILURE, _("strdup key"));
return EXIT_FAILURE;
}
slashdot(dotted_key, '/', '.');
if ((ts.st_mode & S_IWUSR) == 0) { if ((ts.st_mode & S_IWUSR) == 0) {
xwarn(_("setting key \"%s\""), key); xwarn(_("setting key \"%s\""), dotted_key);
free(dotted_key);
return rc; return rc;
} }
if (S_ISDIR(ts.st_mode)) { if (S_ISDIR(ts.st_mode)) {
xwarn(_("setting key \"%s\""), key); xwarn(_("setting key \"%s\""), dotted_key);
free(dotted_key);
return rc; return rc;
} }
@ -539,7 +549,7 @@ static int WriteSetting(
case ENOENT: case ENOENT:
if (!IgnoreError) { if (!IgnoreError) {
xwarnx(_("\"%s\" is an unknown key%s"), xwarnx(_("\"%s\" is an unknown key%s"),
key, (ignore_failure?_(", ignoring"):"")); dotted_key, (ignore_failure?_(", ignoring"):""));
if (!ignore_failure) if (!ignore_failure)
rc = EXIT_FAILURE; rc = EXIT_FAILURE;
} }
@ -548,11 +558,11 @@ static int WriteSetting(
case EROFS: case EROFS:
case EACCES: case EACCES:
xwarnx(_("permission denied on key \"%s\"%s"), xwarnx(_("permission denied on key \"%s\"%s"),
key, (ignore_failure?_(", ignoring"):"")); dotted_key, (ignore_failure?_(", ignoring"):""));
break; break;
default: default:
xwarn(_("setting key \"%s\"%s"), xwarn(_("setting key \"%s\"%s"),
key, (ignore_failure?_(", ignoring"):"")); dotted_key, (ignore_failure?_(", ignoring"):""));
break; break;
} }
if (!ignore_failure && errno != ENOENT) if (!ignore_failure && errno != ENOENT)
@ -561,7 +571,7 @@ static int WriteSetting(
if (0 < fprintf(fp, "%s\n", value)) if (0 < fprintf(fp, "%s\n", value))
rc = EXIT_SUCCESS; rc = EXIT_SUCCESS;
if (close_stream(fp) != 0) { if (close_stream(fp) != 0) {
xwarn(_("setting key \"%s\""), path); xwarn(_("setting key \"%s\""), dotted_key);
return rc; return rc;
} }
} }
@ -571,7 +581,7 @@ static int WriteSetting(
printf("%s\n", value); printf("%s\n", value);
} else { } else {
if (PrintName) { if (PrintName) {
printf("%s = %s\n", path, value); printf("%s = %s\n", dotted_key, value);
} else { } else {
if (PrintNewline) if (PrintNewline)
printf("%s\n", value); printf("%s\n", value);
@ -580,6 +590,7 @@ static int WriteSetting(
} }
} }
} }
free(dotted_key);
return rc; return rc;
} }

View File

@ -3,11 +3,19 @@ set sysctl ${topdir}sysctl
set test "sysctl write from command line" set test "sysctl write from command line"
spawn $sysctl --dry-run kernel.hostname=procps-test spawn $sysctl --dry-run kernel.hostname=procps-test
expect_pass "$test" "/proc/sys/kernel/hostname = procps-test" expect_pass "$test" "kernel.hostname = procps-test"
set test "sysctl write from command line using slash"
spawn $sysctl --dry-run kernel/hostname=procps-test
expect_pass "$test" "kernel.hostname = procps-test"
set test "sysctl write from configuration file" set test "sysctl write from configuration file"
spawn $sysctl --dry-run -f ${topdir}testsuite/sysctl_glob_test.conf spawn $sysctl --dry-run -f ${topdir}testsuite/sysctl_glob_test.conf
expect_pass "$test" "/proc/sys/fs/protected_fifos = 2\\s+/proc/sys/fs/protected_symlinks = 2\\s+/proc/sys/fs/protected_hardlinks = 1" expect_pass "$test" "fs.protected_fifos = 2\\s+fs.protected_symlinks = 2\\s+fs.protected_hardlinks = 1"
set test "sysctl write from file with slashes"
spawn $sysctl --dry-run -f ${topdir}testsuite/sysctl_slash_test.conf
expect_pass "$test" "kernel.hostname = procps-test"
set hostname_file "/proc/sys/kernel/hostname" set hostname_file "/proc/sys/kernel/hostname"
if {[file exists ${hostname_file}]} { if {[file exists ${hostname_file}]} {
@ -25,5 +33,5 @@ if {[file exists ${hostname_file}]} {
expect_spawn_retval "$test" 0 expect_spawn_retval "$test" 0
} }
} else { } else {
unsupported "sysctl write: hostname file doe not exist" unsupported "sysctl write: hostname file does not exist"
} }

View File

@ -0,0 +1 @@
kernel/hostname = procps-test