]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/sysctl-util.c
tree-wide: always drop unnecessary dot in path
[thirdparty/systemd.git] / src / basic / sysctl-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <unistd.h>
7
8 #include "fd-util.h"
9 #include "fileio.h"
10 #include "log.h"
11 #include "macro.h"
12 #include "path-util.h"
13 #include "string-util.h"
14 #include "sysctl-util.h"
15
16 char *sysctl_normalize(char *s) {
17 char *n;
18
19 n = strpbrk(s, "/.");
20
21 /* If the first separator is a slash, the path is
22 * assumed to be normalized and slashes remain slashes
23 * and dots remains dots. */
24
25 if (n && *n == '.')
26 /* Dots become slashes and slashes become dots. Fun. */
27 do {
28 if (*n == '.')
29 *n = '/';
30 else
31 *n = '.';
32
33 n = strpbrk(n + 1, "/.");
34 } while (n);
35
36 path_simplify(s);
37
38 /* Kill the leading slash, but keep the first character of the string in the same place. */
39 if (*s == '/' && *(s+1))
40 memmove(s, s+1, strlen(s));
41
42 return s;
43 }
44
45 int sysctl_write(const char *property, const char *value) {
46 char *p;
47 _cleanup_close_ int fd = -1;
48
49 assert(property);
50 assert(value);
51
52 log_debug("Setting '%s' to '%.*s'.", property, (int) strcspn(value, NEWLINE), value);
53
54 p = strjoina("/proc/sys/", property);
55 fd = open(p, O_WRONLY|O_CLOEXEC);
56 if (fd < 0)
57 return -errno;
58
59 if (!endswith(value, "\n"))
60 value = strjoina(value, "\n");
61
62 if (write(fd, value, strlen(value)) < 0)
63 return -errno;
64
65 return 0;
66 }
67
68 int sysctl_writef(const char *property, const char *format, ...) {
69 _cleanup_free_ char *v = NULL;
70 va_list ap;
71 int r;
72
73 va_start(ap, format);
74 r = vasprintf(&v, format, ap);
75 va_end(ap);
76
77 if (r < 0)
78 return -ENOMEM;
79
80 return sysctl_write(property, v);
81 }
82
83 int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value) {
84 const char *p;
85
86 assert(IN_SET(af, AF_INET, AF_INET6));
87 assert(property);
88 assert(value);
89
90 p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6",
91 ifname ? "/conf/" : "", strempty(ifname),
92 property[0] == '/' ? "" : "/", property);
93
94 log_debug("Setting '%s' to '%s'", p, value);
95
96 return write_string_file(p, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
97 }
98
99 int sysctl_read(const char *property, char **ret) {
100 char *p;
101
102 assert(property);
103 assert(ret);
104
105 p = strjoina("/proc/sys/", property);
106 return read_full_virtual_file(p, ret, NULL);
107 }
108
109 int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret) {
110 _cleanup_free_ char *value = NULL;
111 const char *p;
112 int r;
113
114 assert(IN_SET(af, AF_INET, AF_INET6));
115 assert(property);
116
117 p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6",
118 ifname ? "/conf/" : "", strempty(ifname),
119 property[0] == '/' ? "" : "/", property);
120
121 r = read_full_virtual_file(p, &value, NULL);
122 if (r < 0)
123 return r;
124
125 truncate_nl(value);
126 if (ret)
127 *ret = TAKE_PTR(value);
128
129 return r;
130 }