]>
git.ipfire.org Git - people/ms/systemd.git/blob - unit-name.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
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 General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "unit-name.h"
30 "abcdefghijklmnopqrstuvwxyz" \
31 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
34 UnitType
unit_name_to_type(const char *n
) {
39 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++)
40 if (endswith(n
, unit_vtable
[t
]->suffix
))
43 return _UNIT_TYPE_INVALID
;
46 bool unit_name_is_valid(const char *n
) {
48 const char *e
, *i
, *at
;
52 * string@instance.suffix
58 if (strlen(n
) >= UNIT_NAME_MAX
)
61 t
= unit_name_to_type(n
);
62 if (t
< 0 || t
>= _UNIT_TYPE_MAX
)
65 assert_se(e
= strrchr(n
, '.'));
70 for (i
= n
, at
= NULL
; i
< e
; i
++) {
75 if (!strchr("@" VALID_CHARS
, *i
))
90 bool unit_instance_is_valid(const char *i
) {
93 /* The max length depends on the length of the string, so we
94 * don't really check this here. */
99 /* We allow additional @ in the instance string, we do not
100 * allow them in the prefix! */
103 if (!strchr("@" VALID_CHARS
, *i
))
109 bool unit_prefix_is_valid(const char *p
) {
111 /* We don't allow additional @ in the instance string */
117 if (!strchr(VALID_CHARS
, *p
))
123 int unit_name_to_instance(const char *n
, char **instance
) {
130 /* Everything past the first @ and before the last . is the instance */
131 if (!(p
= strchr(n
, '@'))) {
136 assert_se(d
= strrchr(n
, '.'));
139 if (!(i
= strndup(p
+1, d
-p
-1)))
146 char *unit_name_to_prefix_and_instance(const char *n
) {
151 assert_se(d
= strrchr(n
, '.'));
153 return strndup(n
, d
- n
);
156 char *unit_name_to_prefix(const char *n
) {
159 if ((p
= strchr(n
, '@')))
160 return strndup(n
, p
- n
);
162 return unit_name_to_prefix_and_instance(n
);
165 char *unit_name_change_suffix(const char *n
, const char *suffix
) {
170 assert(unit_name_is_valid(n
));
173 assert_se(e
= strrchr(n
, '.'));
177 if (!(r
= new(char, a
+ b
+ 1)))
181 memcpy(r
+a
, suffix
, b
+1);
186 char *unit_name_build(const char *prefix
, const char *instance
, const char *suffix
) {
190 assert(unit_prefix_is_valid(prefix
));
191 assert(!instance
|| unit_instance_is_valid(instance
));
193 assert(unit_name_to_type(suffix
) >= 0);
196 return strappend(prefix
, suffix
);
198 if (asprintf(&r
, "%s@%s%s", prefix
, instance
, suffix
) < 0)
204 static char* do_escape(const char *f
, char *t
) {
211 else if (*f
== '-' || *f
== '\\' || !strchr(VALID_CHARS
, *f
)) {
214 *(t
++) = hexchar(*f
> 4);
215 *(t
++) = hexchar(*f
);
223 char *unit_name_build_escape(const char *prefix
, const char *instance
, const char *suffix
) {
229 assert(unit_name_to_type(suffix
) >= 0);
231 /* Takes a arbitrary string for prefix and instance plus a
232 * suffix and makes a nice string suitable as unit name of it,
233 * escaping all weird chars on the way.
235 * / becomes ., and all chars not alloweed in a unit name get
236 * escaped as \xFF, including \ and ., of course. This
237 * escaping is hence reversible.
239 * This is primarily useful to make nice unit names from
240 * strings, but is actually useful for any kind of string.
247 b
= strlen(instance
);
249 if (!(r
= new(char, a
*4 + 1 + b
*4 + c
+ 1)))
252 t
= do_escape(prefix
, r
);
254 t
= do_escape(instance
, t
);
257 if (!(r
= new(char, a
*4 + c
+ 1)))
260 t
= do_escape(prefix
, r
);
267 char *unit_name_escape(const char *f
) {
270 if (!(r
= new(char, strlen(f
)*4+1)))
280 char *unit_name_unescape(const char *f
) {
285 if (!(r
= strdup(f
)))
288 for (t
= r
; *f
; f
++) {
291 else if (*f
== '\\') {
294 if ((a
= unhexchar(f
[1])) < 0 ||
295 (b
= unhexchar(f
[2])) < 0) {
296 /* Invalid escape code, let's take it literal then */
299 *(t
++) = (char) ((a
<< 4) | b
);
311 bool unit_name_is_template(const char *n
) {
316 if (!(p
= strchr(n
, '@')))
322 char *unit_name_replace_instance(const char *f
, const char *i
) {
330 assert_se(e
= strrchr(f
, '.'));
339 if (!(r
= new(char, a
+ 1 + b
+ strlen(e
) + 1)))
342 k
= mempcpy(r
, f
, a
+ 1);
343 k
= mempcpy(k
, i
, b
);
346 if (!(r
= new(char, a
+ strlen(e
) + 1)))
349 k
= mempcpy(r
, f
, a
);
356 char *unit_name_template(const char *f
) {
361 if (!(p
= strchr(f
, '@')))
364 assert_se(e
= strrchr(f
, '.'));
367 if (!(r
= new(char, a
+ strlen(e
) + 1)))
370 strcpy(mempcpy(r
, f
, a
), e
);