X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Futils-systemd.c;h=b8c3c0bd9fc2b75d3471cc750f2c029e6d58e4d8;hb=600a5cde310c62e4c6ed1845cf0234ba04fb6f90;hp=48fb3d8fa9040716adb1d9c90624e52b27a4d49f;hpb=fb0f81a1d8b5369842269fa1bdb9ad8d52882491;p=src%2Fapp-framework-main.git diff --git a/src/utils-systemd.c b/src/utils-systemd.c index 48fb3d8..b8c3c0b 100644 --- a/src/utils-systemd.c +++ b/src/utils-systemd.c @@ -20,9 +20,12 @@ #include #include #include +#include +#include +#include #include -#include -#include +#include +#include #include #include @@ -41,6 +44,29 @@ 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; @@ -51,15 +77,28 @@ static int get_bus(int isuser, struct sd_bus **ret) *ret = bus; rc = 0; } else if (isuser) { - rc = sd_bus_open_user(ret); + rc = sd_bus_default_user(ret); if (!rc) usrbus = *ret; } else { - rc = sd_bus_open_system(ret); + rc = sd_bus_default_system(ret); if (!rc) sysbus = *ret; } - return rc; + 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) @@ -70,11 +109,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) @@ -86,22 +121,14 @@ 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 rc; + return check_snprintf_result(rc, pathlen); } int systemd_daemon_reload(int isuser) @@ -111,8 +138,78 @@ int systemd_daemon_reload(int isuser) 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); +} +