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>
31 # include <systemd/sd-bus.h>
32 # include <systemd/sd-bus-protocol.h>
35 # define sd_bus_default_user(p) ((*(p)=NULL),(-ENOTSUP))
36 # define sd_bus_default_system(p) ((*(p)=NULL),(-ENOTSUP))
37 # define sd_bus_call_method(...) (-ENOTSUP)
40 #include "utils-systemd.h"
42 #if !defined(SYSTEMD_UNITS_ROOT)
43 # define SYSTEMD_UNITS_ROOT "/usr/local/lib/systemd"
46 static const char sdb_path[] = "/org/freedesktop/systemd1";
47 static const char sdb_destination[] = "org.freedesktop.systemd1";
48 static const char sdbi_manager[] = "org.freedesktop.systemd1.Manager";
49 static const char sdbm_reload[] = "Reload";
51 static struct sd_bus *sysbus;
52 static struct sd_bus *usrbus;
55 * Translate systemd errors to errno errors
57 static int seterrno(int value)
63 static int sderr2errno(int rc)
65 return rc < 0 ? seterrno(-rc) : rc;
68 static int errno2sderr(int rc)
70 return rc < 0 ? -errno : rc;
73 /* Returns in 'ret' either the system bus (if isuser==0)
74 * or the user bus (if isuser!=0).
75 * Returns 0 in case of success or -1 in case of error
77 static int get_bus(int isuser, struct sd_bus **ret)
82 bus = isuser ? usrbus : sysbus;
87 rc = sd_bus_default_user(ret);
91 rc = sd_bus_default_system(ret);
95 return sderr2errno(rc);
97 static int check_snprintf_result(int rc, size_t buflen)
99 return (rc >= 0 && (size_t)rc >= buflen) ? seterrno(ENAMETOOLONG) : rc;
102 int systemd_get_units_dir(char *path, size_t pathlen, int isuser)
104 int rc = snprintf(path, pathlen, "%s/%s",
106 isuser ? "user" : "system");
108 return check_snprintf_result(rc, pathlen);
111 int systemd_get_unit_path(char *path, size_t pathlen, int isuser, const char *unit, const char *uext)
113 int rc = snprintf(path, pathlen, "%s/%s/%s.%s",
115 isuser ? "user" : "system",
119 return check_snprintf_result(rc, pathlen);
122 int systemd_get_wants_path(char *path, size_t pathlen, int isuser, const char *wanter, const char *unit, const char *uext)
124 int rc = snprintf(path, pathlen, "%s/%s/%s.wants/%s.%s",
126 isuser ? "user" : "system",
131 return check_snprintf_result(rc, pathlen);
134 int systemd_get_wants_target(char *path, size_t pathlen, const char *unit, const char *uext)
136 int rc = snprintf(path, pathlen, "../%s.%s", unit, uext);
138 return check_snprintf_result(rc, pathlen);
141 int systemd_daemon_reload(int isuser)
146 rc = get_bus(isuser, &bus);
148 /* TODO: asynchronous bind... */
149 /* TODO: more diagnostic... */
150 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_reload, NULL, NULL, NULL);
155 int systemd_unit_list(int isuser, int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
158 char path[PATH_MAX + 1];
165 rc = systemd_get_units_dir(path, sizeof path - 1, isuser);
170 /* open the directory */
176 path[offset++] = '/';
178 /* read the directory */
190 if (dent->d_type == DT_REG)
192 else if (dent->d_type != DT_UNKNOWN)
195 rc = fstatat(dirfd(dir), dent->d_name, &st, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT);
198 isfile = S_ISREG(st.st_mode);
201 /* calls the callback if is a file */
203 len = strlen(dent->d_name);
204 if (offset + len >= sizeof path) {
205 rc = seterrno(ENAMETOOLONG);
208 memcpy(&path[offset], dent->d_name, 1 + len);
209 rc = callback(closure, &path[offset], path, isuser);
218 int systemd_unit_list_all(int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
220 return systemd_unit_list(1, callback, closure) ? : systemd_unit_list(0, callback, closure);