]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/unit-name.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "path-util.h"
28 #include "unit-name.h"
32 "abcdefghijklmnopqrstuvwxyz" \
33 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
36 bool unit_name_is_valid_no_type(const char *n
, bool template_ok
) {
37 const char *e
, *i
, *at
;
41 * string@instance.suffix
47 if (strlen(n
) >= UNIT_NAME_MAX
)
54 for (i
= n
, at
= NULL
; i
< e
; i
++) {
59 if (!strchr("@" VALID_CHARS
, *i
))
67 if (!template_ok
&& at
+1 == e
)
74 bool unit_instance_is_valid(const char *i
) {
77 /* The max length depends on the length of the string, so we
78 * don't really check this here. */
83 /* We allow additional @ in the instance string, we do not
84 * allow them in the prefix! */
87 if (!strchr("@" VALID_CHARS
, *i
))
93 bool unit_prefix_is_valid(const char *p
) {
95 /* We don't allow additional @ in the instance string */
101 if (!strchr(VALID_CHARS
, *p
))
107 int unit_name_to_instance(const char *n
, char **instance
) {
114 /* Everything past the first @ and before the last . is the instance */
115 if (!(p
= strchr(n
, '@'))) {
120 assert_se(d
= strrchr(n
, '.'));
123 if (!(i
= strndup(p
+1, d
-p
-1)))
130 char *unit_name_to_prefix_and_instance(const char *n
) {
135 assert_se(d
= strrchr(n
, '.'));
137 return strndup(n
, d
- n
);
140 char *unit_name_to_prefix(const char *n
) {
145 return strndup(n
, p
- n
);
147 return unit_name_to_prefix_and_instance(n
);
150 char *unit_name_change_suffix(const char *n
, const char *suffix
) {
155 assert(unit_name_is_valid_no_type(n
, true));
158 assert_se(e
= strrchr(n
, '.'));
162 r
= new(char, a
+ b
+ 1);
167 memcpy(r
+a
, suffix
, b
+1);
172 char *unit_name_build(const char *prefix
, const char *instance
, const char *suffix
) {
174 assert(unit_prefix_is_valid(prefix
));
175 assert(!instance
|| unit_instance_is_valid(instance
));
179 return strappend(prefix
, suffix
);
181 return join(prefix
, "@", instance
, suffix
, NULL
);
184 static char *do_escape_char(char c
, char *t
) {
187 *(t
++) = hexchar(c
>> 4);
192 static char *do_escape(const char *f
, char *t
) {
196 /* do not create units with a leading '.', like for "/.dotdir" mount points */
198 t
= do_escape_char(*f
, t
);
205 else if (*f
== '-' || *f
== '\\' || !strchr(VALID_CHARS
, *f
))
206 t
= do_escape_char(*f
, t
);
214 char *unit_name_build_escape(const char *prefix
, const char *instance
, const char *suffix
) {
221 /* Takes a arbitrary string for prefix and instance plus a
222 * suffix and makes a nice string suitable as unit name of it,
223 * escaping all weird chars on the way.
225 * / becomes -, and all chars not allowed in a unit name get
226 * escaped as \xFF, including \ and -, of course. This
227 * escaping is hence reversible.
229 * This is primarily useful to make nice unit names from
230 * strings, but is actually useful for any kind of string.
237 b
= strlen(instance
);
239 r
= new(char, a
*4 + 1 + b
*4 + c
+ 1);
243 t
= do_escape(prefix
, r
);
245 t
= do_escape(instance
, t
);
248 if (!(r
= new(char, a
*4 + c
+ 1)))
251 t
= do_escape(prefix
, r
);
258 char *unit_name_escape(const char *f
) {
261 r
= new(char, strlen(f
)*4+1);
271 char *unit_name_unescape(const char *f
) {
280 for (t
= r
; *f
; f
++) {
283 else if (*f
== '\\') {
287 (a
= unhexchar(f
[2])) < 0 ||
288 (b
= unhexchar(f
[3])) < 0) {
289 /* Invalid escape code, let's take it literal then */
292 *(t
++) = (char) ((a
<< 4) | b
);
304 bool unit_name_is_template(const char *n
) {
309 if (!(p
= strchr(n
, '@')))
315 char *unit_name_replace_instance(const char *f
, const char *i
) {
323 assert_se(e
= strrchr(f
, '.'));
332 if (!(r
= new(char, a
+ 1 + b
+ strlen(e
) + 1)))
335 k
= mempcpy(r
, f
, a
+ 1);
336 k
= mempcpy(k
, i
, b
);
339 if (!(r
= new(char, a
+ strlen(e
) + 1)))
342 k
= mempcpy(r
, f
, a
);
349 char *unit_name_template(const char *f
) {
358 assert_se(e
= strrchr(f
, '.'));
361 r
= new(char, a
+ strlen(e
) + 1);
365 strcpy(mempcpy(r
, f
, a
), e
);
370 char *unit_name_from_path(const char *path
, const char *suffix
) {
380 path_kill_slashes(p
);
382 path
= p
[0] == '/' ? p
+ 1 : p
;
386 return strappend("-", suffix
);
389 r
= unit_name_build_escape(path
, NULL
, suffix
);
395 char *unit_name_from_path_instance(const char *prefix
, const char *path
, const char *suffix
) {
401 if (!(p
= strdup(path
)))
404 path_kill_slashes(p
);
406 path
= p
[0] == '/' ? p
+ 1 : p
;
410 return unit_name_build_escape(prefix
, "-", suffix
);
413 r
= unit_name_build_escape(prefix
, path
, suffix
);
419 char *unit_name_to_path(const char *name
) {
424 w
= unit_name_to_prefix(name
);
428 e
= unit_name_unescape(w
);
435 w
= strappend("/", e
);
447 char *unit_name_path_unescape(const char *f
) {
452 e
= unit_name_unescape(f
);
459 w
= strappend("/", e
);
471 char *unit_dbus_path_from_name(const char *name
) {
474 e
= bus_path_escape(name
);
478 p
= strappend("/org/freedesktop/systemd1/unit/", e
);
484 char *unit_name_mangle(const char *name
) {
490 /* Try to turn a string that might not be a unit name into a
491 * sensible unit name. */
493 if (path_startswith(name
, "/dev/") ||
494 path_startswith(name
, "/sys/"))
495 return unit_name_from_path(name
, ".device");
497 if (path_is_absolute(name
))
498 return unit_name_from_path(name
, ".mount");
500 /* We'll only escape the obvious characters here, to play
503 r
= new(char, strlen(name
) * 4 + 1);
507 for (f
= name
, t
= r
; *f
; f
++) {
511 else if (!strchr("@" VALID_CHARS
, *f
))
512 t
= do_escape_char(*f
, t
);