mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-10 00:58:20 +03:00
shared/sysctl-util: normalize repeated slashes or dots to a single value
We use those strings as hash keys. While writing "a...b" looks strange, "a///b" does not look so strange. Both syntaxes would actually result in the value being correctly written to the file, but they would confuse our de-deplication over keys. So let's normalize. Output also becomes nicer. Add test.
This commit is contained in:
parent
c16460cf78
commit
f3b136a484
@ -9,6 +9,7 @@
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
#include "sysctl-util.h"
|
||||
|
||||
@ -16,22 +17,27 @@ char *sysctl_normalize(char *s) {
|
||||
char *n;
|
||||
|
||||
n = strpbrk(s, "/.");
|
||||
|
||||
/* If the first separator is a slash, the path is
|
||||
* assumed to be normalized and slashes remain slashes
|
||||
* and dots remains dots. */
|
||||
if (!n || *n == '/')
|
||||
return s;
|
||||
|
||||
/* Otherwise, dots become slashes and slashes become
|
||||
* dots. Fun. */
|
||||
while (n) {
|
||||
if (*n == '.')
|
||||
*n = '/';
|
||||
else
|
||||
*n = '.';
|
||||
if (n && *n == '.')
|
||||
/* Dots become slashes and slashes become dots. Fun. */
|
||||
do {
|
||||
if (*n == '.')
|
||||
*n = '/';
|
||||
else
|
||||
*n = '.';
|
||||
|
||||
n = strpbrk(n + 1, "/.");
|
||||
}
|
||||
n = strpbrk(n + 1, "/.");
|
||||
} while (n);
|
||||
|
||||
path_simplify(s, true);
|
||||
|
||||
/* Kill the leading slash, but keep the first character of the string in the same place. */
|
||||
if (*s == '/' && *(s+1))
|
||||
memmove(s, s+1, strlen(s));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -325,6 +325,10 @@ tests += [
|
||||
[],
|
||||
[]],
|
||||
|
||||
[['src/test/test-sysctl-util.c'],
|
||||
[],
|
||||
[]],
|
||||
|
||||
[['src/test/test-user-util.c'],
|
||||
[],
|
||||
[]],
|
||||
|
44
src/test/test-sysctl-util.c
Normal file
44
src/test/test-sysctl-util.c
Normal file
@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "strv.h"
|
||||
#include "sysctl-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
static const char* cases[] = {
|
||||
"a.b.c", "a/b/c",
|
||||
"a/b/c", "a/b/c",
|
||||
"a/b.c/d", "a/b.c/d",
|
||||
"a.b/c.d", "a/b.c/d",
|
||||
|
||||
"net.ipv4.conf.enp3s0/200.forwarding", "net/ipv4/conf/enp3s0.200/forwarding",
|
||||
"net/ipv4/conf/enp3s0.200/forwarding", "net/ipv4/conf/enp3s0.200/forwarding",
|
||||
|
||||
"a...b...c", "a/b/c",
|
||||
"a///b///c", "a/b/c",
|
||||
".a...b...c", "a/b/c",
|
||||
"/a///b///c", "a/b/c",
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void test_sysctl_normalize(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
const char **s, **expected;
|
||||
STRV_FOREACH_PAIR(s, expected, cases) {
|
||||
_cleanup_free_ char *t;
|
||||
|
||||
assert_se(t = strdup(*s));
|
||||
assert_se(sysctl_normalize(t) == t);
|
||||
|
||||
log_info("\"%s\" → \"%s\", expected \"%s\"", *s, t, *expected);
|
||||
assert_se(streq(t, *expected));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
test_sysctl_normalize();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user