diff options
| author | Lennart Poettering <lennart@poettering.net> | 2011-07-22 21:01:15 +0200 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2011-07-22 21:01:15 +0200 | 
| commit | 034a2a52ac0ec83e0229941d635d310b23eb04df (patch) | |
| tree | 37cca83098579cc56d30b1bab1a4c48134586796 | |
| parent | bccc1d8859175f0927652d694796892c9e9c21d6 (diff) | |
sd-login: beef up login api, to add monitoring and enumerating
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | src/install.c | 2 | ||||
| -rw-r--r-- | src/libsystemd-login.sym | 12 | ||||
| -rw-r--r-- | src/logind-user.c | 38 | ||||
| -rw-r--r-- | src/sd-login.c | 422 | ||||
| -rw-r--r-- | src/sd-login.h | 69 | ||||
| -rw-r--r-- | src/test-login.c | 86 | ||||
| -rw-r--r-- | src/util.c | 84 | ||||
| -rw-r--r-- | src/util.h | 3 | ||||
| -rw-r--r-- | tmpfiles.d/systemd.conf | 3 | 
10 files changed, 684 insertions, 37 deletions
| @@ -20,6 +20,8 @@ F15 External:  Features: +* move PAM code into its own binary +  * logind: ensure ACLs are updated on login and logout  * warn if the user stops a service but not its associated socket diff --git a/src/install.c b/src/install.c index e1c69444f9..9f415edc2e 100644 --- a/src/install.c +++ b/src/install.c @@ -1462,7 +1462,7 @@ int unit_file_disable(          q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);          if (r == 0) -                r = 1; +                r = q;  finish:          install_context_done(&c); diff --git a/src/libsystemd-login.sym b/src/libsystemd-login.sym index 708ef6ff25..cd5f52c341 100644 --- a/src/libsystemd-login.sym +++ b/src/libsystemd-login.sym @@ -11,13 +11,23 @@  LIBSYSTEMD_LOGIN_31 {  global: +        sd_get_seats; +        sd_get_sessions; +        sd_get_uids; +        sd_login_monitor_flush; +        sd_login_monitor_get_fd; +        sd_login_monitor_new; +        sd_login_monitor_unref; +        sd_pid_get_owner_uid;          sd_pid_get_session;          sd_seat_get_active; +        sd_seat_get_sessions;          sd_session_get_seat;          sd_session_get_uid;          sd_session_is_active; +        sd_uid_get_seats; +        sd_uid_get_sessions;          sd_uid_get_state; -        sd_uid_is_active_on_seat;          sd_uid_is_on_seat;  local:          *; diff --git a/src/logind-user.c b/src/logind-user.c index 3a677ff707..3c245c0927 100644 --- a/src/logind-user.c +++ b/src/logind-user.c @@ -134,6 +134,44 @@ int user_save(User *u) {                          "DISPLAY=%s\n",                          u->display->id); +        if (u->sessions) { +                Session *i; + +                fputs("SESSIONS=", f); +                LIST_FOREACH(sessions_by_user, i, u->sessions) { +                        fprintf(f, +                                "%s%c", +                                i->id, +                                i->sessions_by_seat_next ? ' ' : '\n'); +                } + +                fputs("SEATS=", f); +                LIST_FOREACH(sessions_by_user, i, u->sessions) { +                        if (i->seat) +                                fprintf(f, +                                        "%s%c", +                                        i->seat->id, +                                        i->sessions_by_seat_next ? ' ' : '\n'); +                } + +                fputs("ACTIVE_SESSIONS=", f); +                LIST_FOREACH(sessions_by_user, i, u->sessions) +                        if (session_is_active(i)) +                                fprintf(f, +                                        "%lu%c", +                                        (unsigned long) i->user->uid, +                                        i->sessions_by_seat_next ? ' ' : '\n'); + +                fputs("ACTIVE_SEATS=", f); +                LIST_FOREACH(sessions_by_user, i, u->sessions) { +                        if (session_is_active(i) && i->seat) +                                fprintf(f, +                                        "%s%c", +                                        i->seat->id, +                                        i->sessions_by_seat_next ? ' ' : '\n'); +                } +        } +          fflush(f);          if (ferror(f) || rename(temp_path, u->state_file) < 0) { diff --git a/src/sd-login.c b/src/sd-login.c index 3ae850d801..6dfc2d086e 100644 --- a/src/sd-login.c +++ b/src/sd-login.c @@ -22,15 +22,17 @@  #include <unistd.h>  #include <string.h>  #include <errno.h> +#include <sys/inotify.h>  #include "util.h"  #include "cgroup-util.h"  #include "macro.h"  #include "sd-login.h" +#include "strv.h" -_public_ int sd_pid_get_session(pid_t pid, char **session) { -        int r; +static int pid_get_cgroup(pid_t pid, char **root, char **cgroup) {          char *cg_process, *cg_init, *p; +        int r;          if (pid == 0)                  pid = getpid(); @@ -38,9 +40,6 @@ _public_ int sd_pid_get_session(pid_t pid, char **session) {          if (pid <= 0)                  return -EINVAL; -        if (!session) -                return -EINVAL; -          r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);          if (r < 0)                  return r; @@ -63,26 +62,57 @@ _public_ int sd_pid_get_session(pid_t pid, char **session) {          free(cg_init); -        if (!startswith(p, "/user/")) { -                free(cg_process); -                return -ENOENT; +        if (cgroup) { +                char* c; + +                c = strdup(p); +                if (!c) { +                        free(cg_process); +                        return -ENOMEM; +                } + +                *cgroup = c;          } -        p += 6; -        if (startswith(p, "shared/") || streq(p, "shared")) { +        if (root) { +                cg_process[p-cg_process] = 0; +                *root = cg_process; +        } else                  free(cg_process); + +        return 0; +} + +_public_ int sd_pid_get_session(pid_t pid, char **session) { +        int r; +        char *cgroup, *p; + +        if (!session) +                return -EINVAL; + +        r = pid_get_cgroup(pid, NULL, &cgroup); +        if (r < 0) +                return r; + +        if (!startswith(cgroup, "/user/")) { +                free(cgroup);                  return -ENOENT;          } -        p = strchr(p, '/'); +        p = strchr(cgroup + 6, '/');          if (!p) { -                free(cg_process); +                free(cgroup);                  return -ENOENT;          }          p++; +        if (startswith(p, "shared/") || streq(p, "shared")) { +                free(cgroup); +                return -ENOENT; +        } +          p = strndup(p, strcspn(p, "/")); -        free(cg_process); +        free(cgroup);          if (!p)                  return -ENOMEM; @@ -91,6 +121,54 @@ _public_ int sd_pid_get_session(pid_t pid, char **session) {          return 0;  } +_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { +        int r; +        char *root, *cgroup, *p, *cc; +        struct stat st; + +        if (!uid) +                return -EINVAL; + +        r = pid_get_cgroup(pid, &root, &cgroup); +        if (r < 0) +                return r; + +        if (!startswith(cgroup, "/user/")) { +                free(cgroup); +                free(root); +                return -ENOENT; +        } + +        p = strchr(cgroup + 6, '/'); +        if (!p) { +                free(cgroup); +                return -ENOENT; +        } + +        p++; +        p += strcspn(p, "/"); +        *p = 0; + +        r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, cgroup, &cc); +        free(root); +        free(cgroup); + +        if (r < 0) +                return -ENOMEM; + +        r = lstat(cc, &st); +        free(cc); + +        if (r < 0) +                return -errno; + +        if (!S_ISDIR(st.st_mode)) +                return -ENOTDIR; + +        *uid = st.st_uid; +        return 0; +} +  _public_ int sd_uid_get_state(uid_t uid, char**state) {          char *p, *s = NULL;          int r; @@ -122,19 +200,22 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) {          return 0;  } -static int uid_is_on_seat_internal(uid_t uid, const char *seat, const char *variable) { +_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {          char *p, *w, *t, *state, *s = NULL;          size_t l;          int r; +        const char *variable;          if (!seat)                  return -EINVAL; +        variable = require_active ? "ACTIVE_UID" : "UIDS"; +          p = strappend("/run/systemd/seats/", seat);          if (!p)                  return -ENOMEM; -        r = parse_env_file(p, NEWLINE, "UIDS", &s, NULL); +        r = parse_env_file(p, NEWLINE, variable, &s, NULL);          free(p);          if (r < 0) { @@ -165,12 +246,54 @@ static int uid_is_on_seat_internal(uid_t uid, const char *seat, const char *vari          return 0;  } -_public_ int sd_uid_is_on_seat(uid_t uid, const char *seat) { -        return uid_is_on_seat_internal(uid, seat, "UIDS"); +static int uid_get_array(uid_t uid, const char *variable, char ***array) { +        char *p, *s = NULL; +        char **a; +        int r; + +        if (!array) +                return -EINVAL; + +        if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0) +                return -ENOMEM; + +        r = parse_env_file(p, NEWLINE, +                           variable, &s, +                           NULL); +        free(p); + +        if (r < 0) { +                free(s); + +                if (r == -ENOENT) { +                        *array = NULL; +                        return 0; +                } + +                return r; +        } + +        if (!s) { +                *array = NULL; +                return 0; +        } + +        a = strv_split(s, " "); +        free(s); + +        if (!a) +                return -ENOMEM; + +        *array = a; +        return 0; +} + +_public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) { +        return uid_get_array(uid, require_active ? "ACTIVE_SESSIONS" : "SESSIONS", sessions);  } -_public_ int sd_uid_is_active_on_seat(uid_t uid, const char *seat) { -        return uid_is_on_seat_internal(uid, seat, "ACTIVE_UID"); +_public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) { +        return uid_get_array(uid, require_active ? "ACTIVE_SEATS" : "SEATS", seats);  }  _public_ int sd_session_is_active(const char *session) { @@ -291,25 +414,21 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {          if (session && !s)  {                  free(t); -                return -EIO; +                return -ENOENT;          }          if (uid && !t) {                  free(s); -                return -EIO; +                return -ENOENT;          }          if (uid && t) { -                unsigned long ul; - -                r = safe_atolu(t, &ul); +                r = parse_uid(t, uid);                  if (r < 0) {                          free(t);                          free(s);                          return r;                  } - -                *uid = (uid_t) ul;          }          free(t); @@ -321,3 +440,254 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {          return 0;  } + +_public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) { +        char *p, *s = NULL, *t = NULL, **a = NULL; +        uid_t *b = NULL; +        unsigned n = 0; +        int r; + +        if (!seat) +                return -EINVAL; + +        if (!sessions && !uids) +                return -EINVAL; + +        p = strappend("/run/systemd/seats/", seat); +        if (!p) +                return -ENOMEM; + +        r = parse_env_file(p, NEWLINE, +                           "SESSIONS", &s, +                           "ACTIVE_SESSIONS", &t, +                           NULL); +        free(p); + +        if (r < 0) { +                free(s); +                free(t); +                return r; +        } + +        if (sessions && s) { +                a = strv_split(s, " "); +                if (!a) { +                        free(s); +                        free(t); +                        return -ENOMEM; +                } +        } + +        free(s); + +        if (uids && t) { +                char *w, *state; +                size_t l; +                unsigned i = 0; + +                FOREACH_WORD(w, l, t, state) +                        n++; + +                b = new(uid_t, n); +                if (!b) { +                        strv_free(a); +                        return -ENOMEM; +                } + +                FOREACH_WORD(w, l, t, state) { +                        char *k; + +                        k = strndup(w, l); +                        if (!k) { +                                free(t); +                                free(b); +                                return -ENOMEM; +                        } + +                        r = parse_uid(k, b + i); +                        free(k); +                        if (r < 0) +                                continue; + +                        i++; +                } +        } + +        free(t); + +        if (sessions) +                *sessions = a; + +        if (uids) +                *uids = b; + +        if (n_uids) +                *n_uids = n; + +        return 0; +} + +_public_ int sd_get_seats(char ***seats) { + +        if (!seats) +                return -EINVAL; + +        return get_files_in_directory("/run/systemd/seats/", seats); +} + +_public_ int sd_get_sessions(char ***sessions) { + +        if (!sessions) +                return -EINVAL; + +        return get_files_in_directory("/run/systemd/sessions/", sessions); +} + +_public_ int sd_get_uids(uid_t **users) { +        DIR *d; +        int r = 0; +        unsigned n = 0; +        uid_t *l = NULL; + +        if (!users) +                return -EINVAL; + +        d = opendir("/run/systemd/users/"); +        for (;;) { +                struct dirent buffer, *de; +                int k; +                uid_t uid; + +                k = readdir_r(d, &buffer, &de); +                if (k != 0) { +                        r = -k; +                        goto finish; +                } + +                if (!de) +                        break; + +                dirent_ensure_type(d, de); + +                if (!dirent_is_file(de)) +                        continue; + +                k = parse_uid(de->d_name, &uid); +                if (k < 0) +                        continue; + +                if ((unsigned) r >= n) { +                        uid_t *t; + +                        n = MAX(16, 2*r); +                        t = realloc(l, sizeof(uid_t) * n); +                        if (!t) { +                                r = -ENOMEM; +                                goto finish; +                        } + +                        l = t; +                } + +                assert((unsigned) r < n); +                l[r++] = uid; +        } + +finish: +        if (d) +                closedir(d); + +        if (r >= 0) +                *users = l; +        else +                free(l); + +        return r; +} + +static inline int MONITOR_TO_FD(sd_login_monitor *m) { +        return (int) (unsigned long) m - 1; +} + +static inline sd_login_monitor* FD_TO_MONITOR(int fd) { +        return (sd_login_monitor*) (unsigned long) (fd + 1); +} + +_public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) { +        const char *path; +        int fd, k; +        bool good = false; + +        if (!m) +                return -EINVAL; + +        fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); +        if (fd < 0) +                return errno; + +        if (!category || streq(category, "seat")) { +                k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE); +                if (k < 0) { +                        close_nointr_nofail(fd); +                        return -errno; +                } + +                good = true; +        } + +        if (!category || streq(category, "session")) { +                k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE); +                if (k < 0) { +                        close_nointr_nofail(fd); +                        return -errno; +                } + +                good = true; +        } + +        if (!category || streq(category, "uid")) { +                k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE); +                if (k < 0) { +                        close_nointr_nofail(fd); +                        return -errno; +                } + +                good = true; +        } + +        if (!good) { +                close_nointr(fd); +                return -EINVAL; +        } + +        *m = FD_TO_MONITOR(fd); +        return 0; +} + +_public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) { +        int fd; + +        if (!m) +                return NULL; + +        fd = MONITOR_TO_FD(m); +        close_nointr(fd); + +        return NULL; +} + +_public_ int sd_login_monitor_flush(sd_login_monitor *m) { + +        if (!m) +                return -EINVAL; + +        return flush_fd(MONITOR_TO_FD(m)); +} + +_public_ int sd_login_monitor_get_fd(sd_login_monitor *m) { + +        if (!m) +                return -EINVAL; + +        return MONITOR_TO_FD(m); +} diff --git a/src/sd-login.h b/src/sd-login.h index f23ac80526..c6835e1235 100644 --- a/src/sd-login.h +++ b/src/sd-login.h @@ -24,17 +24,48 @@  #include <sys/types.h> -/* Get session from PID */ +/* + * A few points: + * + * Instead of returning an empty string array or empty uid array, we + * may return NULL. + * + * Free the data we return with libc free(). + * + * We return error codes as negative errno, kernel-style. + * + * These functions access data in /proc, /sys/fs/cgroup and /run. All + * of these are virtual file systems, hence the accesses are + * relatively cheap. + */ + +/* Get session from PID. Note that 'shared' processes of a user are + * not attached to a session, but only attached to a user. This will + * return an error for system processes and 'shared' processes of a + * user. */  int sd_pid_get_session(pid_t pid, char **session); +/* Get UID of the owner of the session of the PID (or in case the + * process is a 'shared' user process the UID of that user is + * returned). This will not return the UID of the process, but rather + * the UID of the owner of the cgroup the process is in. This will + * return an error for system processes. */ +int sd_pid_get_owner_uid(pid_t pid, uid_t *uid); +  /* Get state from uid. Possible states: offline, lingering, online, active */  int sd_uid_get_state(uid_t uid, char**state); -/* Return 1 if uid has session on seat */ -int sd_uid_is_on_seat(uid_t uid, const char *seat); +/* Return 1 if uid has session on seat. If require_active is true will + * look for active sessions only. */ +int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat); + +/* Return sessions of user. If require_active is true will look + * for active sessions only. */ +int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions); -/* Return 1 if uid has active session on seat */ -int sd_uid_is_active_on_seat(uid_t uid, const char *seat); +/* Return seats of user is on. If require_active is true will look for + * active seats only.  */ +int sd_uid_get_seats(uid_t uid, int require_active, char ***seats);  /* Return 1 if the session is a active */  int sd_session_is_active(const char *session); @@ -48,4 +79,32 @@ int sd_session_get_seat(const char *session, char **seat);  /* Return active session and user of seat */  int sd_seat_get_active(const char *seat, char **session, uid_t *uid); +/* Return sessions and users on seat */ +int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids); + +/* Get all seats */ +int sd_get_seats(char ***seats); + +/* Get all sessions */ +int sd_get_sessions(char ***sessions); + +/* Get all logged in users */ +int sd_get_uids(uid_t **users); + +/* Monitor object */ +typedef struct sd_login_monitor sd_login_monitor; + +/* Create a new monitor. Category must be NULL, "seat", "session", + * "uid" to get monitor events for the specific category (or all). */ +int sd_login_monitor_new(const char *category, sd_login_monitor** ret); + +/* Destroys the passed monitor. Returns NULL. */ +sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m); + +/* Flushes the monitor */ +int sd_login_monitor_flush(sd_login_monitor *m); + +/* Get FD from monitor */ +int sd_login_monitor_get_fd(sd_login_monitor *m); +  #endif diff --git a/src/test-login.c b/src/test-login.c index 97313fcbcb..21cd3a1900 100644 --- a/src/test-login.c +++ b/src/test-login.c @@ -19,26 +19,54 @@    along with systemd; If not, see <http://www.gnu.org/licenses/>.  ***/ +#include <sys/poll.h> +#include <string.h> +  #include "sd-login.h"  #include "util.h" +#include "strv.h"  int main(int argc, char* argv[]) { -    int r, k; -    uid_t u, u2; +        int r, k; +        uid_t u, u2;          char *seat;          char *session;          char *state;          char *session2; +        char *t; +        char **seats, **sessions; +        uid_t *uids; +        unsigned n; +        struct pollfd pollfd; +        sd_login_monitor *m;          assert_se(sd_pid_get_session(0, &session) == 0);          printf("session = %s\n", session); +        assert_se(sd_pid_get_owner_uid(0, &u2) == 0); +        printf("user = %lu\n", (unsigned long) u2); + +        r = sd_uid_get_sessions(u2, false, &sessions); +        assert_se(r >= 0); +        assert_se(t = strv_join(sessions, ", ")); +        strv_free(sessions); +        printf("sessions = %s\n", t); +        free(t); + +        r = sd_uid_get_seats(u2, false, &seats); +        assert_se(r >= 0); +        assert_se(t = strv_join(seats, ", ")); +        strv_free(seats); +        printf("seats = %s\n", t); +        free(t); +          r = sd_session_is_active(session);          assert_se(r >= 0);          printf("active = %s\n", yes_no(r));          assert_se(sd_session_get_uid(session, &u) >= 0);          printf("uid = %lu\n", (unsigned long) u); +        assert_se(u == u2);          assert_se(sd_session_get_seat(session, &seat) >= 0);          printf("seat = %s\n", seat); @@ -46,9 +74,9 @@ int main(int argc, char* argv[]) {          assert_se(sd_uid_get_state(u, &state) >= 0);          printf("state = %s\n", state); -        assert_se(sd_uid_is_on_seat(u, seat) > 0); +        assert_se(sd_uid_is_on_seat(u, 0, seat) > 0); -        k = sd_uid_is_active_on_seat(u, seat); +        k = sd_uid_is_on_seat(u, 1, seat);          assert_se(k >= 0);          assert_se(!!r == !!r); @@ -56,10 +84,60 @@ int main(int argc, char* argv[]) {          printf("session2 = %s\n", session2);          printf("uid2 = %lu\n", (unsigned long) u2); +        assert_se(sd_seat_get_sessions(seat, &sessions, &uids, &n) >= 0); +        assert_se(t = strv_join(sessions, ", ")); +        strv_free(sessions); +        printf("sessions = %s\n", t); +        free(t); +        printf("uids ="); +        for (k = 0; k < (int) n; k++) +                printf(" %lu", (unsigned long) uids[k]); +        printf("\n"); +        free(uids); +          free(session);          free(state);          free(session2);          free(seat); +        assert_se(sd_get_seats(&seats) >= 0); +        assert_se(t = strv_join(seats, ", ")); +        strv_free(seats); +        printf("seats = %s\n", t); +        free(t); + +        assert_se(sd_get_sessions(&sessions) >= 0); +        assert_se(t = strv_join(sessions, ", ")); +        strv_free(sessions); +        printf("sessions = %s\n", t); +        free(t); + +        r = sd_get_uids(&uids); +        assert_se(r >= 0); + +        printf("uids ="); +        for (k = 0; k < r; k++) +                printf(" %lu", (unsigned long) uids[k]); +        printf("\n"); + +        free(uids); + +        r = sd_login_monitor_new("session", &m); +        assert_se(r >= 0); + +        zero(pollfd); +        pollfd.fd = sd_login_monitor_get_fd(m); +        pollfd.events = POLLIN; + +        for (n = 0; n < 5; n++) { +                r = poll(&pollfd, 1, -1); +                assert_se(r >= 0); + +                sd_login_monitor_flush(m); +                printf("Wake!\n"); +        } + +        sd_login_monitor_unref(m); +          return 0;  } diff --git a/src/util.c b/src/util.c index 328a1ead92..2d4f229193 100644 --- a/src/util.c +++ b/src/util.c @@ -317,6 +317,26 @@ int parse_pid(const char *s, pid_t* ret_pid) {          return 0;  } +int parse_uid(const char *s, uid_t* ret_uid) { +        unsigned long ul = 0; +        uid_t uid; +        int r; + +        assert(s); +        assert(ret_uid); + +        if ((r = safe_atolu(s, &ul)) < 0) +                return r; + +        uid = (uid_t) ul; + +        if ((unsigned long) uid != ul) +                return -ERANGE; + +        *ret_uid = uid; +        return 0; +} +  int safe_atou(const char *s, unsigned *ret_u) {          char *x = NULL;          unsigned long l; @@ -5357,6 +5377,70 @@ int in_search_path(const char *path, char **search) {          return r;  } +int get_files_in_directory(const char *path, char ***list) { +        DIR *d; +        int r = 0; +        unsigned n = 0; +        char **l = NULL; + +        assert(path); +        assert(list); + +        d = opendir(path); +        for (;;) { +                struct dirent buffer, *de; +                int k; + +                k = readdir_r(d, &buffer, &de); +                if (k != 0) { +                        r = -k; +                        goto finish; +                } + +                if (!de) +                        break; + +                dirent_ensure_type(d, de); + +                if (!dirent_is_file(de)) +                        continue; + +                if ((unsigned) r >= n) { +                        char **t; + +                        n = MAX(16, 2*r); +                        t = realloc(l, sizeof(char*) * n); +                        if (!t) { +                                r = -ENOMEM; +                                goto finish; +                        } + +                        l = t; +                } + +                assert((unsigned) r < n); + +                l[r] = strdup(de->d_name); +                if (!l[r]) { +                        r = -ENOMEM; +                        goto finish; +                } + +                l[++r] = NULL; +        } + +finish: +        if (d) +                closedir(d); + +        if (r >= 0) +                *list = l; +        else +                strv_free(l); + +        return r; +} +  static const char *const ioprio_class_table[] = {          [IOPRIO_CLASS_NONE] = "none",          [IOPRIO_CLASS_RT] = "realtime", diff --git a/src/util.h b/src/util.h index f39c01fbd7..9537d130d3 100644 --- a/src/util.h +++ b/src/util.h @@ -136,6 +136,8 @@ void close_many(const int fds[], unsigned n_fd);  int parse_boolean(const char *v);  int parse_usec(const char *t, usec_t *usec);  int parse_pid(const char *s, pid_t* ret_pid); +int parse_uid(const char *s, uid_t* ret_uid); +#define parse_gid(s, ret_uid) parse_uid(s, ret_uid)  int safe_atou(const char *s, unsigned *ret_u);  int safe_atoi(const char *s, int *ret_i); @@ -453,6 +455,7 @@ int glob_exists(const char *path);  int dirent_ensure_type(DIR *d, struct dirent *de);  int in_search_path(const char *path, char **search); +int get_files_in_directory(const char *path, char ***list);  #define NULSTR_FOREACH(i, l)                                    \          for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf index 5e8ed99916..7d4b356a12 100644 --- a/tmpfiles.d/systemd.conf +++ b/tmpfiles.d/systemd.conf @@ -23,3 +23,6 @@ r /forcequotacheck  r /fastboot  d /run/systemd/ask-password 0755 root root - +d /run/systemd/seats 0755 root root - +d /run/systemd/sessions 0755 root root - +d /run/systemd/users 0755 root root - | 
