X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Futils-systemd.c;h=d80414489083c83c8dc94250a8b4708a7c6a7cc0;hb=3d3964b1190c03ff7463aaae9f712dfc67291c91;hp=757a52cab386c8132b392b712e6a90ce0b78f0c0;hpb=2a8b46d16ea5d0c99831e95b47cab037f220f7af;p=src%2Fapp-framework-main.git diff --git a/src/utils-systemd.c b/src/utils-systemd.c index 757a52c..d804144 100644 --- a/src/utils-systemd.c +++ b/src/utils-systemd.c @@ -20,12 +20,22 @@ #include #include #include +#include +#include +#include #include -#include -#include +#include +#include -#include -#include +#ifndef NO_LIBSYSTEMD +# include +# include +#else + struct sd_bus; +# define sd_bus_default_user(p) ((*(p)=NULL),(-ENOTSUP)) +# define sd_bus_default_system(p) ((*(p)=NULL),(-ENOTSUP)) +# define sd_bus_call_method(...) (-ENOTSUP) +#endif #include "utils-systemd.h" @@ -33,6 +43,71 @@ # define SYSTEMD_UNITS_ROOT "/usr/local/lib/systemd" #endif +static const char sdb_path[] = "/org/freedesktop/systemd1"; +static const char sdb_destination[] = "org.freedesktop.systemd1"; +static const char sdbi_manager[] = "org.freedesktop.systemd1.Manager"; +static const char sdbm_reload[] = "Reload"; + +static struct sd_bus *sysbus; +static struct sd_bus *usrbus; + +/* + * Translate systemd errors to errno errors + */ +static int seterrno(int value) +{ + errno = value; + return -1; +} + +static int sderr2errno(int rc) +{ + return rc < 0 ? seterrno(-rc) : rc; +} + +static int errno2sderr(int rc) +{ + return rc < 0 ? -errno : rc; +} + +/* Returns in 'ret' either the system bus (if isuser==0) + * or the user bus (if isuser!=0). + * Returns 0 in case of success or -1 in case of error + */ +static int get_bus(int isuser, struct sd_bus **ret) +{ + int rc; + struct sd_bus *bus; + + bus = isuser ? usrbus : sysbus; + if (bus) { + *ret = bus; + rc = 0; + } else if (isuser) { + rc = sd_bus_default_user(ret); + if (!rc) + usrbus = *ret; + } else { + rc = sd_bus_default_system(ret); + if (!rc) + sysbus = *ret; + } + return sderr2errno(rc); +} +static int check_snprintf_result(int rc, size_t buflen) +{ + return (rc >= 0 && (size_t)rc >= buflen) ? seterrno(ENAMETOOLONG) : rc; +} + +int systemd_get_units_dir(char *path, size_t pathlen, int isuser) +{ + int rc = snprintf(path, pathlen, "%s/%s", + SYSTEMD_UNITS_ROOT, + isuser ? "user" : "system"); + + return check_snprintf_result(rc, pathlen); +} + int systemd_get_unit_path(char *path, size_t pathlen, int isuser, const char *unit, const char *uext) { int rc = snprintf(path, pathlen, "%s/%s/%s.%s", @@ -41,11 +116,7 @@ int systemd_get_unit_path(char *path, size_t pathlen, int isuser, const char *un unit, uext); - if (rc >= 0 && (size_t)rc >= pathlen) { - errno = ENAMETOOLONG; - rc = -1; - } - return rc; + return check_snprintf_result(rc, pathlen); } int systemd_get_wants_path(char *path, size_t pathlen, int isuser, const char *wanter, const char *unit, const char *uext) @@ -57,21 +128,95 @@ int systemd_get_wants_path(char *path, size_t pathlen, int isuser, const char *w unit, uext); - if (rc >= 0 && (size_t)rc >= pathlen) { - errno = ENAMETOOLONG; - rc = -1; - } - return rc; + return check_snprintf_result(rc, pathlen); } int systemd_get_wants_target(char *path, size_t pathlen, const char *unit, const char *uext) { int rc = snprintf(path, pathlen, "../%s.%s", unit, uext); - if (rc >= 0 && (size_t)rc >= pathlen) { - errno = ENAMETOOLONG; - rc = -1; + return check_snprintf_result(rc, pathlen); +} + +int systemd_daemon_reload(int isuser) +{ + int rc; + struct sd_bus *bus; + + rc = get_bus(isuser, &bus); + if (!rc) { + /* TODO: asynchronous bind... */ + /* TODO: more diagnostic... */ + rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_reload, NULL, NULL, NULL); } return rc; } +int systemd_unit_list(int isuser, int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure) +{ + DIR *dir; + char path[PATH_MAX + 1]; + struct dirent *dent; + int rc, isfile; + size_t offset, len; + struct stat st; + + /* get the path */ + rc = systemd_get_units_dir(path, sizeof path - 1, isuser); + if (rc < 0) + return rc; + offset = (size_t)rc; + + /* open the directory */ + dir = opendir(path); + if (!dir) + return -1; + + /* prepare path */ + path[offset++] = '/'; + + /* read the directory */ + for(;;) { + /* get next entry */ + errno = 0; + dent = readdir(dir); + if (dent == NULL) { + /* end or error */ + rc = (!errno) - 1; + break; + } + + /* is a file? */ + if (dent->d_type == DT_REG) + isfile = 1; + else if (dent->d_type != DT_UNKNOWN) + isfile = 0; + else { + rc = fstatat(dirfd(dir), dent->d_name, &st, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT); + if (rc < 0) + break; + isfile = S_ISREG(st.st_mode); + } + + /* calls the callback if is a file */ + if (isfile) { + len = strlen(dent->d_name); + if (offset + len >= sizeof path) { + rc = seterrno(ENAMETOOLONG); + break; + } + memcpy(&path[offset], dent->d_name, 1 + len); + rc = callback(closure, &path[offset], path, isuser); + if (rc) + break; + } + } + closedir(dir); + return rc; +} + +int systemd_unit_list_all(int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure) +{ + return systemd_unit_list(1, callback, closure) ? : systemd_unit_list(0, callback, closure); +} +