From 3e2d011e8c1c42801194d387b75ca4f4a175ae5d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 7 Sep 2010 14:19:05 +0200 Subject: added forgotten files --- runtime/sd-daemon.c | 448 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 448 insertions(+) create mode 100644 runtime/sd-daemon.c (limited to 'runtime/sd-daemon.c') diff --git a/runtime/sd-daemon.c b/runtime/sd-daemon.c new file mode 100644 index 00000000..5df70e38 --- /dev/null +++ b/runtime/sd-daemon.c @@ -0,0 +1,448 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +/*** + Copyright 2010 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" + +int sd_listen_fds(int unset_environment) { + +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) + return 0; +#else + int r, fd; + const char *e; + char *p = NULL; + unsigned long l; + + if (!(e = getenv("LISTEN_PID"))) { + r = 0; + goto finish; + } + + errno = 0; + l = strtoul(e, &p, 10); + + if (errno != 0) { + r = -errno; + goto finish; + } + + if (!p || *p || l <= 0) { + r = -EINVAL; + goto finish; + } + + /* Is this for us? */ + if (getpid() != (pid_t) l) { + r = 0; + goto finish; + } + + if (!(e = getenv("LISTEN_FDS"))) { + r = 0; + goto finish; + } + + errno = 0; + l = strtoul(e, &p, 10); + + if (errno != 0) { + r = -errno; + goto finish; + } + + if (!p || *p) { + r = -EINVAL; + goto finish; + } + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { + int flags; + + if ((flags = fcntl(fd, F_GETFD)) < 0) { + r = -errno; + goto finish; + } + + if (flags & FD_CLOEXEC) + continue; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { + r = -errno; + goto finish; + } + } + + r = (int) l; + +finish: + if (unset_environment) { + unsetenv("LISTEN_PID"); + unsetenv("LISTEN_FDS"); + } + + return r; +#endif +} + +int sd_is_fifo(int fd, const char *path) { + struct stat st_fd; + + if (fd < 0) + return -EINVAL; + + memset(&st_fd, 0, sizeof(st_fd)); + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISFIFO(st_fd.st_mode)) + return 0; + + if (path) { + struct stat st_path; + + memset(&st_path, 0, sizeof(st_path)); + if (stat(path, &st_path) < 0) { + + if (errno == ENOENT || errno == ENOTDIR) + return 0; + + return -errno; + } + + return + st_path.st_dev == st_fd.st_dev && + st_path.st_ino == st_fd.st_ino; + } + + return 1; +} + +static int sd_is_socket_internal(int fd, int type, int listening) { + struct stat st_fd; + + if (fd < 0 || type < 0) + return -EINVAL; + + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISSOCK(st_fd.st_mode)) + return 0; + + if (type != 0) { + int other_type = 0; + socklen_t l = sizeof(other_type); + + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) + return -errno; + + if (l != sizeof(other_type)) + return -EINVAL; + + if (other_type != type) + return 0; + } + + if (listening >= 0) { + int accepting = 0; + socklen_t l = sizeof(accepting); + + if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) + return -errno; + + if (l != sizeof(accepting)) + return -EINVAL; + + if (!accepting != !listening) + return 0; + } + + return 1; +} + +union sockaddr_union { + struct sockaddr sa; + struct sockaddr_in in4; + struct sockaddr_in6 in6; + struct sockaddr_un un; + struct sockaddr_storage storage; +}; + +int sd_is_socket(int fd, int family, int type, int listening) { + int r; + + if (family < 0) + return -EINVAL; + + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + return r; + + if (family > 0) { + union sockaddr_union sockaddr; + socklen_t l; + + memset(&sockaddr, 0, sizeof(sockaddr)); + l = sizeof(sockaddr); + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + return sockaddr.sa.sa_family == family; + } + + return 1; +} + +int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { + union sockaddr_union sockaddr; + socklen_t l; + int r; + + if (family != 0 && family != AF_INET && family != AF_INET6) + return -EINVAL; + + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + return r; + + memset(&sockaddr, 0, sizeof(sockaddr)); + l = sizeof(sockaddr); + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + if (sockaddr.sa.sa_family != AF_INET && + sockaddr.sa.sa_family != AF_INET6) + return 0; + + if (family > 0) + if (sockaddr.sa.sa_family != family) + return 0; + + if (port > 0) { + if (sockaddr.sa.sa_family == AF_INET) { + if (l < sizeof(struct sockaddr_in)) + return -EINVAL; + + return htons(port) == sockaddr.in4.sin_port; + } else { + if (l < sizeof(struct sockaddr_in6)) + return -EINVAL; + + return htons(port) == sockaddr.in6.sin6_port; + } + } + + return 1; +} + +int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { + union sockaddr_union sockaddr; + socklen_t l; + int r; + + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + return r; + + memset(&sockaddr, 0, sizeof(sockaddr)); + l = sizeof(sockaddr); + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + if (sockaddr.sa.sa_family != AF_UNIX) + return 0; + + if (path) { + if (length <= 0) + length = strlen(path); + + if (length <= 0) + /* Unnamed socket */ + return l == sizeof(sa_family_t); + + if (path[0]) + /* Normal path socket */ + return + (l >= sizeof(sa_family_t) + length + 1) && + memcmp(path, sockaddr.un.sun_path, length+1) == 0; + else + /* Abstract namespace socket */ + return + (l == sizeof(sa_family_t) + length) && + memcmp(path, sockaddr.un.sun_path, length) == 0; + } + + return 1; +} + +int sd_notify(int unset_environment, const char *state) { +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) + return 0; +#else + int fd = -1, r; + struct msghdr msghdr; + struct iovec iovec; + union sockaddr_union sockaddr; + struct ucred *ucred; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + } control; + const char *e; + + if (!state) { + r = -EINVAL; + goto finish; + } + + if (!(e = getenv("NOTIFY_SOCKET"))) + return 0; + + /* Must be an abstract socket, or an absolute path */ + if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { + r = -EINVAL; + goto finish; + } + + if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { + r = -errno; + goto finish; + } + + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sa.sa_family = AF_UNIX; + strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); + + if (sockaddr.un.sun_path[0] == '@') + sockaddr.un.sun_path[0] = 0; + + memset(&iovec, 0, sizeof(iovec)); + iovec.iov_base = (char*) state; + iovec.iov_len = strlen(state); + + memset(&control, 0, sizeof(control)); + control.cmsghdr.cmsg_level = SOL_SOCKET; + control.cmsghdr.cmsg_type = SCM_CREDENTIALS; + control.cmsghdr.cmsg_len = CMSG_LEN(sizeof(struct ucred)); + + ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr); + ucred->pid = getpid(); + ucred->uid = getuid(); + ucred->gid = getgid(); + + memset(&msghdr, 0, sizeof(msghdr)); + msghdr.msg_name = &sockaddr; + msghdr.msg_namelen = sizeof(struct sockaddr_un); + msghdr.msg_iov = &iovec; + msghdr.msg_iovlen = 1; + msghdr.msg_control = &control; + msghdr.msg_controllen = control.cmsghdr.cmsg_len; + + if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { + r = -errno; + goto finish; + } + + r = 1; + +finish: + if (unset_environment) + unsetenv("NOTIFY_SOCKET"); + + if (fd >= 0) + close(fd); + + return r; +#endif +} + +int sd_notifyf(int unset_environment, const char *format, ...) { +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) + return 0; +#else + va_list ap; + char *p = NULL; + int r; + + va_start(ap, format); + r = vasprintf(&p, format, ap); + va_end(ap); + + if (r < 0 || !p) + return -ENOMEM; + + r = sd_notify(unset_environment, p); + free(p); + + return r; +#endif +} + +int sd_booted(void) { +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) + return 0; +#else + + struct stat a, b; + + /* We simply test whether the systemd cgroup hierarchy is + * mounted */ + + if (lstat("/cgroup", &a) < 0) + return 0; + + if (lstat("/cgroup/systemd", &b) < 0) + return 0; + + return a.st_dev != b.st_dev; +#endif +} -- cgit v1.2.3 From 21a2672222a1b403ff0811154dec156676bed732 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 8 Sep 2010 12:46:03 +0200 Subject: moved systemd interface to rsyslog convenience lib Mostly a refresh of sd-daemon.[ch] from its source plus some make file changes. We now have systemd interfaces inside rsyslog, so that all plugins interested can call the interfaces. Seems not to be totally necessary right now, but will help in the long term. --- runtime/sd-daemon.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) (limited to 'runtime/sd-daemon.c') diff --git a/runtime/sd-daemon.c b/runtime/sd-daemon.c index 5df70e38..9c23b917 100644 --- a/runtime/sd-daemon.c +++ b/runtime/sd-daemon.c @@ -1,4 +1,4 @@ -/*-*- Mode: C; c-basic-offset: 8 -*-*/ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ /*** Copyright 2010 Lennart Poettering @@ -325,18 +325,13 @@ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t } int sd_notify(int unset_environment, const char *state) { -#if defined(DISABLE_SYSTEMD) || !defined(__linux__) +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) return 0; #else int fd = -1, r; struct msghdr msghdr; struct iovec iovec; union sockaddr_union sockaddr; - struct ucred *ucred; - union { - struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; - } control; const char *e; if (!state) { @@ -369,23 +364,15 @@ int sd_notify(int unset_environment, const char *state) { iovec.iov_base = (char*) state; iovec.iov_len = strlen(state); - memset(&control, 0, sizeof(control)); - control.cmsghdr.cmsg_level = SOL_SOCKET; - control.cmsghdr.cmsg_type = SCM_CREDENTIALS; - control.cmsghdr.cmsg_len = CMSG_LEN(sizeof(struct ucred)); - - ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr); - ucred->pid = getpid(); - ucred->uid = getuid(); - ucred->gid = getgid(); - memset(&msghdr, 0, sizeof(msghdr)); msghdr.msg_name = &sockaddr; - msghdr.msg_namelen = sizeof(struct sockaddr_un); + msghdr.msg_namelen = sizeof(sa_family_t) + strlen(e); + + if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) + msghdr.msg_namelen = sizeof(struct sockaddr_un); + msghdr.msg_iov = &iovec; msghdr.msg_iovlen = 1; - msghdr.msg_control = &control; - msghdr.msg_controllen = control.cmsghdr.cmsg_len; if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { r = -errno; @@ -437,10 +424,10 @@ int sd_booted(void) { /* We simply test whether the systemd cgroup hierarchy is * mounted */ - if (lstat("/cgroup", &a) < 0) + if (lstat("/sys/fs/cgroup", &a) < 0) return 0; - if (lstat("/cgroup/systemd", &b) < 0) + if (lstat("/sys/fs/cgroup/systemd", &b) < 0) return 0; return a.st_dev != b.st_dev; -- cgit v1.2.3 From d6b86f8b9fde1e2aa39353c36e413540649067b6 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 21 Mar 2013 18:51:31 +0100 Subject: update systemd files to match current systemd source --- runtime/sd-daemon.c | 172 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 135 insertions(+), 37 deletions(-) (limited to 'runtime/sd-daemon.c') diff --git a/runtime/sd-daemon.c b/runtime/sd-daemon.c index 9c23b917..79d8ca37 100644 --- a/runtime/sd-daemon.c +++ b/runtime/sd-daemon.c @@ -25,14 +25,18 @@ ***/ #ifndef _GNU_SOURCE -#define _GNU_SOURCE +# define _GNU_SOURCE #endif #include #include #include #include -#include +#ifdef __BIONIC__ +# include +#else +# include +#endif #include #include #include @@ -40,10 +44,28 @@ #include #include #include +#include +#include + +#if defined(__linux__) +# include +#endif #include "sd-daemon.h" -int sd_listen_fds(int unset_environment) { +#if (__GNUC__ >= 4) +# ifdef SD_EXPORT_SYMBOLS +/* Export symbols */ +# define _sd_export_ __attribute__ ((visibility("default"))) +# else +/* Don't export the symbols */ +# define _sd_export_ __attribute__ ((visibility("hidden"))) +# endif +#else +# define _sd_export_ +#endif + +_sd_export_ int sd_listen_fds(int unset_environment) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; @@ -53,7 +75,8 @@ int sd_listen_fds(int unset_environment) { char *p = NULL; unsigned long l; - if (!(e = getenv("LISTEN_PID"))) { + e = getenv("LISTEN_PID"); + if (!e) { r = 0; goto finish; } @@ -66,7 +89,7 @@ int sd_listen_fds(int unset_environment) { goto finish; } - if (!p || *p || l <= 0) { + if (!p || p == e || *p || l <= 0) { r = -EINVAL; goto finish; } @@ -77,7 +100,8 @@ int sd_listen_fds(int unset_environment) { goto finish; } - if (!(e = getenv("LISTEN_FDS"))) { + e = getenv("LISTEN_FDS"); + if (!e) { r = 0; goto finish; } @@ -90,7 +114,7 @@ int sd_listen_fds(int unset_environment) { goto finish; } - if (!p || *p) { + if (!p || p == e || *p) { r = -EINVAL; goto finish; } @@ -98,7 +122,8 @@ int sd_listen_fds(int unset_environment) { for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { int flags; - if ((flags = fcntl(fd, F_GETFD)) < 0) { + flags = fcntl(fd, F_GETFD); + if (flags < 0) { r = -errno; goto finish; } @@ -124,13 +149,12 @@ finish: #endif } -int sd_is_fifo(int fd, const char *path) { +_sd_export_ int sd_is_fifo(int fd, const char *path) { struct stat st_fd; if (fd < 0) return -EINVAL; - memset(&st_fd, 0, sizeof(st_fd)); if (fstat(fd, &st_fd) < 0) return -errno; @@ -140,7 +164,6 @@ int sd_is_fifo(int fd, const char *path) { if (path) { struct stat st_path; - memset(&st_path, 0, sizeof(st_path)); if (stat(path, &st_path) < 0) { if (errno == ENOENT || errno == ENOTDIR) @@ -157,6 +180,42 @@ int sd_is_fifo(int fd, const char *path) { return 1; } +_sd_export_ int sd_is_special(int fd, const char *path) { + struct stat st_fd; + + if (fd < 0) + return -EINVAL; + + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) + return 0; + + if (path) { + struct stat st_path; + + if (stat(path, &st_path) < 0) { + + if (errno == ENOENT || errno == ENOTDIR) + return 0; + + return -errno; + } + + if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) + return + st_path.st_dev == st_fd.st_dev && + st_path.st_ino == st_fd.st_ino; + else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) + return st_path.st_rdev == st_fd.st_rdev; + else + return 0; + } + + return 1; +} + static int sd_is_socket_internal(int fd, int type, int listening) { struct stat st_fd; @@ -208,13 +267,14 @@ union sockaddr_union { struct sockaddr_storage storage; }; -int sd_is_socket(int fd, int family, int type, int listening) { +_sd_export_ int sd_is_socket(int fd, int family, int type, int listening) { int r; if (family < 0) return -EINVAL; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; if (family > 0) { @@ -236,7 +296,7 @@ int sd_is_socket(int fd, int family, int type, int listening) { return 1; } -int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { +_sd_export_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { union sockaddr_union sockaddr; socklen_t l; int r; @@ -244,7 +304,8 @@ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port if (family != 0 && family != AF_INET && family != AF_INET6) return -EINVAL; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; memset(&sockaddr, 0, sizeof(sockaddr)); @@ -281,12 +342,13 @@ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port return 1; } -int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { +_sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { union sockaddr_union sockaddr; socklen_t l; int r; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; memset(&sockaddr, 0, sizeof(sockaddr)); @@ -302,29 +364,66 @@ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t return 0; if (path) { - if (length <= 0) + if (length == 0) length = strlen(path); - if (length <= 0) + if (length == 0) /* Unnamed socket */ - return l == sizeof(sa_family_t); + return l == offsetof(struct sockaddr_un, sun_path); if (path[0]) /* Normal path socket */ return - (l >= sizeof(sa_family_t) + length + 1) && + (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && memcmp(path, sockaddr.un.sun_path, length+1) == 0; else /* Abstract namespace socket */ return - (l == sizeof(sa_family_t) + length) && + (l == offsetof(struct sockaddr_un, sun_path) + length) && memcmp(path, sockaddr.un.sun_path, length) == 0; } return 1; } -int sd_notify(int unset_environment, const char *state) { +_sd_export_ int sd_is_mq(int fd, const char *path) { +#if !defined(__linux__) + return 0; +#else + struct mq_attr attr; + + if (fd < 0) + return -EINVAL; + + if (mq_getattr(fd, &attr) < 0) + return -errno; + + if (path) { + char fpath[PATH_MAX]; + struct stat a, b; + + if (path[0] != '/') + return -EINVAL; + + if (fstat(fd, &a) < 0) + return -errno; + + strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); + fpath[sizeof(fpath)-1] = 0; + + if (stat(fpath, &b) < 0) + return -errno; + + if (a.st_dev != b.st_dev || + a.st_ino != b.st_ino) + return 0; + } + + return 1; +#endif +} + +_sd_export_ int sd_notify(int unset_environment, const char *state) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) return 0; #else @@ -339,7 +438,8 @@ int sd_notify(int unset_environment, const char *state) { goto finish; } - if (!(e = getenv("NOTIFY_SOCKET"))) + e = getenv("NOTIFY_SOCKET"); + if (!e) return 0; /* Must be an abstract socket, or an absolute path */ @@ -348,7 +448,8 @@ int sd_notify(int unset_environment, const char *state) { goto finish; } - if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) { r = -errno; goto finish; } @@ -366,7 +467,7 @@ int sd_notify(int unset_environment, const char *state) { memset(&msghdr, 0, sizeof(msghdr)); msghdr.msg_name = &sockaddr; - msghdr.msg_namelen = sizeof(sa_family_t) + strlen(e); + msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) msghdr.msg_namelen = sizeof(struct sockaddr_un); @@ -392,7 +493,7 @@ finish: #endif } -int sd_notifyf(int unset_environment, const char *format, ...) { +_sd_export_ int sd_notifyf(int unset_environment, const char *format, ...) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; #else @@ -414,22 +515,19 @@ int sd_notifyf(int unset_environment, const char *format, ...) { #endif } -int sd_booted(void) { +_sd_export_ int sd_booted(void) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; #else + struct stat st; - struct stat a, b; - - /* We simply test whether the systemd cgroup hierarchy is - * mounted */ - - if (lstat("/sys/fs/cgroup", &a) < 0) - return 0; + /* We test whether the runtime unit file directory has been + * created. This takes place in mount-setup.c, so is + * guaranteed to happen very early during boot. */ - if (lstat("/sys/fs/cgroup/systemd", &b) < 0) + if (lstat("/run/systemd/system/", &st) < 0) return 0; - return a.st_dev != b.st_dev; + return !!S_ISDIR(st.st_mode); #endif } -- cgit v1.2.3