4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
27 #include <sys/types.h>
30 #include <systemd/sd-bus.h>
31 #include <systemd/sd-bus-protocol.h>
33 #include "utils-systemd.h"
35 #if !defined(SYSTEMD_UNITS_ROOT)
36 # define SYSTEMD_UNITS_ROOT "/usr/local/lib/systemd"
39 static const char sdb_path[] = "/org/freedesktop/systemd1";
40 static const char sdb_destination[] = "org.freedesktop.systemd1";
41 static const char sdbi_manager[] = "org.freedesktop.systemd1.Manager";
42 static const char sdbm_reload[] = "Reload";
44 static struct sd_bus *sysbus;
45 static struct sd_bus *usrbus;
48 * Translate systemd errors to errno errors
50 static int seterrno(int value)
56 static int sderr2errno(int rc)
58 return rc < 0 ? seterrno(-rc) : rc;
61 static int errno2sderr(int rc)
63 return rc < 0 ? -errno : rc;
66 /* Returns in 'ret' either the system bus (if isuser==0)
67 * or the user bus (if isuser!=0).
68 * Returns 0 in case of success or -1 in case of error
70 static int get_bus(int isuser, struct sd_bus **ret)
75 bus = isuser ? usrbus : sysbus;
80 rc = sd_bus_default_user(ret);
84 rc = sd_bus_default_system(ret);
88 return sderr2errno(rc);
90 static int check_snprintf_result(int rc, size_t buflen)
92 return (rc >= 0 && (size_t)rc >= buflen) ? seterrno(ENAMETOOLONG) : rc;
95 int systemd_get_units_dir(char *path, size_t pathlen, int isuser)
97 int rc = snprintf(path, pathlen, "%s/%s",
99 isuser ? "user" : "system");
101 return check_snprintf_result(rc, pathlen);
104 int systemd_get_unit_path(char *path, size_t pathlen, int isuser, const char *unit, const char *uext)
106 int rc = snprintf(path, pathlen, "%s/%s/%s.%s",
108 isuser ? "user" : "system",
112 return check_snprintf_result(rc, pathlen);
115 int systemd_get_wants_path(char *path, size_t pathlen, int isuser, const char *wanter, const char *unit, const char *uext)
117 int rc = snprintf(path, pathlen, "%s/%s/%s.wants/%s.%s",
119 isuser ? "user" : "system",
124 return check_snprintf_result(rc, pathlen);
127 int systemd_get_wants_target(char *path, size_t pathlen, const char *unit, const char *uext)
129 int rc = snprintf(path, pathlen, "../%s.%s", unit, uext);
131 return check_snprintf_result(rc, pathlen);
134 int systemd_daemon_reload(int isuser)
139 rc = get_bus(isuser, &bus);
141 /* TODO: asynchronous bind... */
142 /* TODO: more diagnostic... */
143 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_reload, NULL, NULL, NULL);
148 int systemd_unit_list(int isuser, int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
151 char path[PATH_MAX + 1];
158 rc = systemd_get_units_dir(path, sizeof path - 1, isuser);
163 /* open the directory */
169 path[offset++] = '/';
171 /* read the directory */
183 if (dent->d_type == DT_REG)
185 else if (dent->d_type != DT_UNKNOWN)
188 rc = fstatat(dirfd(dir), dent->d_name, &st, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT);
191 isfile = S_ISREG(st.st_mode);
194 /* calls the callback if is a file */
196 len = strlen(dent->d_name);
197 if (offset + len >= sizeof path) {
198 rc = seterrno(ENAMETOOLONG);
201 memcpy(&path[offset], dent->d_name, 1 + len);
202 rc = callback(closure, &path[offset], path, isuser);
211 int systemd_unit_list_all(int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
213 return systemd_unit_list(1, callback, closure) ? : systemd_unit_list(0, callback, closure);