unit-name.c revision ede3a7967560506486e1e25d09ef4e74600851ff
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt This file is part of systemd.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Copyright 2010 Lennart Poettering
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is free software; you can redistribute it and/or modify it
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt under the terms of the GNU Lesser General Public License as published by
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt the Free Software Foundation; either version 2.1 of the License, or
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (at your option) any later version.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is distributed in the hope that it will be useful, but
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Lesser General Public License for more details.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt You should have received a copy of the GNU Lesser General Public License
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt "0123456789" \
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt "abcdefghijklmnopqrstuvwxyz" \
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flyktstatic const char* const unit_type_table[_UNIT_TYPE_MAX] = {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik FlyktDEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
a276e6d68606861b552140cbcc003f4af10626fcTom GundersenDEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersenbool unit_name_is_valid(const char *n, bool template_ok) {
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen const char *e, *i, *at;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* Valid formats:
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt * string@instance.suffix
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return false;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!e || e == n)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return false;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return false;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return false;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return false;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt return false;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return true;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktbool unit_instance_is_valid(const char *i) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* The max length depends on the length of the string, so we
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * don't really check this here. */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (i[0] == 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return false;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* We allow additional @ in the instance string, we do not
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * allow them in the prefix! */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt for (; *i; i++)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return false;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return true;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktbool unit_prefix_is_valid(const char *p) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* We don't allow additional @ in the instance string */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (p[0] == 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return false;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt for (; *p; p++)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return false;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt return true;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flyktint unit_name_to_instance(const char *n, char **instance) {
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt const char *p, *d;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt /* Everything past the first @ and before the last . is the instance */
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktchar *unit_name_to_prefix_and_instance(const char *n) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt const char *d;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return strndup(n, d - n);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktchar *unit_name_to_prefix(const char *n) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt const char *p;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return strndup(n, p - n);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktchar *unit_name_change_suffix(const char *n, const char *suffix) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt char *e, *r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktchar *unit_name_build(const char *prefix, const char *instance, const char *suffix) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(!instance || unit_instance_is_valid(instance));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return strjoin(prefix, "@", instance, suffix, NULL);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic char *do_escape_char(char c, char *t) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt *(t++) = '\\';
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt *(t++) = 'x';
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flyktstatic char *do_escape(const char *f, char *t) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt /* do not create units with a leading '.', like for "/.dotdir" mount points */
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (*f == '.') {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt for (; *f; f++) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (*f == '/')
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt *(t++) = '-';
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f))
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt *(t++) = *f;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktchar *unit_name_escape(const char *f) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt char *r, *t;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktchar *unit_name_unescape(const char *f) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt char *r, *t;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt for (t = r; *f; f++) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (*f == '-')
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt *(t++) = '/';
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (*f == '\\') {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt /* Invalid escape code, let's take it literal then */
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt *(t++) = '\\';
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt *(t++) = (char) ((a << 4) | b);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt *(t++) = *f;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktchar *unit_name_path_escape(const char *f) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt char *p, *e;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktchar *unit_name_path_unescape(const char *f) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (e[0] != '/') {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktbool unit_name_is_template(const char *n) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt const char *p;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return false;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktbool unit_name_is_instance(const char *n) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt const char *p;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return false;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktchar *unit_name_replace_instance(const char *f, const char *i) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt const char *p, *e;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt char *r, *k;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt k = mempcpy(k, i, b);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktchar *unit_name_template(const char *f) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt const char *p, *e;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt a = p - f + 1;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktchar *unit_name_from_path(const char *path, const char *suffix) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt char *p, *r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktchar *unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt char *p, *r;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt char *w, *e;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flyktchar *unit_dbus_path_from_name(const char *name) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return strappend("/org/freedesktop/systemd1/unit/", e);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flyktint unit_name_from_dbus_path(const char *path, char **name) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt const char *e;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt e = startswith(path, "/org/freedesktop/systemd1/unit/");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt char *r, *t;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt const char *f;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* Try to turn a string that might not be a unit name into a
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * sensible unit name. */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* We'll only escape the obvious characters here, to play
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = new(char, strlen(name) * 4 + 1 + sizeof(".service")-1);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt for (f = name, t = r; *f; f++) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (*f == '/')
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt *(t++) = '-';
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt *(t++) = *f;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktchar *unit_name_mangle_with_suffix(const char *name, const char *suffix) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt char *r, *t;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt const char *f;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* Similar to unit_name_mangle(), but is called when we know
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * that this is about snapshot units. */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = new(char, strlen(name) * 4 + strlen(suffix) + 1);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt for (f = name, t = r; *f; f++) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (*f == '/')
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt *(t++) = '-';
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt *(t++) = *f;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt const char *e;