From 0ebee8818404adb95a0b8a01416aad3a16f64ae1 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 18 Feb 2014 18:50:11 +0100 Subject: build-sys: merge libsystemd-daemon into libsystemd --- src/compat-libs/libsystemd-daemon.pc.in | 19 + src/compat-libs/libsystemd-daemon.sym | 32 ++ src/libsystemd-daemon/.gitignore | 1 - src/libsystemd-daemon/Makefile | 1 - src/libsystemd-daemon/libsystemd-daemon.pc.in | 19 - src/libsystemd-daemon/libsystemd-daemon.sym | 32 -- src/libsystemd-daemon/sd-daemon.c | 587 -------------------------- src/libsystemd/libsystemd.sym | 15 + src/libsystemd/sd-daemon/sd-daemon.c | 537 +++++++++++++++++++++++ src/systemd/sd-daemon.h | 42 +- src/systemd/sd-readahead.h | 2 +- 11 files changed, 609 insertions(+), 678 deletions(-) create mode 100644 src/compat-libs/libsystemd-daemon.pc.in create mode 100644 src/compat-libs/libsystemd-daemon.sym delete mode 100644 src/libsystemd-daemon/.gitignore delete mode 120000 src/libsystemd-daemon/Makefile delete mode 100644 src/libsystemd-daemon/libsystemd-daemon.pc.in delete mode 100644 src/libsystemd-daemon/libsystemd-daemon.sym delete mode 100644 src/libsystemd-daemon/sd-daemon.c create mode 100644 src/libsystemd/sd-daemon/sd-daemon.c (limited to 'src') diff --git a/src/compat-libs/libsystemd-daemon.pc.in b/src/compat-libs/libsystemd-daemon.pc.in new file mode 100644 index 0000000000..8bb3a74c87 --- /dev/null +++ b/src/compat-libs/libsystemd-daemon.pc.in @@ -0,0 +1,19 @@ +# 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: + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: systemd +Description: systemd Daemon Utility Library +URL: @PACKAGE_URL@ +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lsystemd-daemon +Cflags: -I${includedir} diff --git a/src/compat-libs/libsystemd-daemon.sym b/src/compat-libs/libsystemd-daemon.sym new file mode 100644 index 0000000000..aa9be51c6a --- /dev/null +++ b/src/compat-libs/libsystemd-daemon.sym @@ -0,0 +1,32 @@ +/*** + 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: +***/ + +/* Original symbols from systemd v31 */ + +LIBSYSTEMD_DAEMON_31 { +global: + sd_booted; + sd_is_fifo; + sd_is_mq; + sd_is_socket; + sd_is_socket_inet; + sd_is_socket_unix; + sd_is_special; + sd_listen_fds; + sd_notify; + sd_notifyf; +local: + *; +}; + +LIBSYSTEMD_DAEMON_209 { +global: + sd_watchdog_enabled; +} LIBSYSTEMD_DAEMON_31; diff --git a/src/libsystemd-daemon/.gitignore b/src/libsystemd-daemon/.gitignore deleted file mode 100644 index 5184131b28..0000000000 --- a/src/libsystemd-daemon/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/libsystemd-daemon.pc diff --git a/src/libsystemd-daemon/Makefile b/src/libsystemd-daemon/Makefile deleted file mode 120000 index d0b0e8e008..0000000000 --- a/src/libsystemd-daemon/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile \ No newline at end of file diff --git a/src/libsystemd-daemon/libsystemd-daemon.pc.in b/src/libsystemd-daemon/libsystemd-daemon.pc.in deleted file mode 100644 index 8bb3a74c87..0000000000 --- a/src/libsystemd-daemon/libsystemd-daemon.pc.in +++ /dev/null @@ -1,19 +0,0 @@ -# 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: - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: systemd -Description: systemd Daemon Utility Library -URL: @PACKAGE_URL@ -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lsystemd-daemon -Cflags: -I${includedir} diff --git a/src/libsystemd-daemon/libsystemd-daemon.sym b/src/libsystemd-daemon/libsystemd-daemon.sym deleted file mode 100644 index aa9be51c6a..0000000000 --- a/src/libsystemd-daemon/libsystemd-daemon.sym +++ /dev/null @@ -1,32 +0,0 @@ -/*** - 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: -***/ - -/* Original symbols from systemd v31 */ - -LIBSYSTEMD_DAEMON_31 { -global: - sd_booted; - sd_is_fifo; - sd_is_mq; - sd_is_socket; - sd_is_socket_inet; - sd_is_socket_unix; - sd_is_special; - sd_listen_fds; - sd_notify; - sd_notifyf; -local: - *; -}; - -LIBSYSTEMD_DAEMON_209 { -global: - sd_watchdog_enabled; -} LIBSYSTEMD_DAEMON_31; diff --git a/src/libsystemd-daemon/sd-daemon.c b/src/libsystemd-daemon/sd-daemon.c deleted file mode 100644 index 1a713ef2e8..0000000000 --- a/src/libsystemd-daemon/sd-daemon.c +++ /dev/null @@ -1,587 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - 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 -#include - -#if defined(__linux__) && !defined(SD_DAEMON_DISABLE_MQ) -# include -#endif - -#include "util.h" -#include "sd-daemon.h" - -#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; -#else - int r, fd; - const char *e; - char *p = NULL; - unsigned long l; - - e = getenv("LISTEN_PID"); - if (!e) { - r = 0; - goto finish; - } - - errno = 0; - l = strtoul(e, &p, 10); - - if (errno > 0) { - r = -errno; - goto finish; - } - - if (!p || p == e || *p || l <= 0) { - r = -EINVAL; - goto finish; - } - - /* Is this for us? */ - if (getpid() != (pid_t) l) { - r = 0; - goto finish; - } - - e = getenv("LISTEN_FDS"); - if (!e) { - r = 0; - goto finish; - } - - errno = 0; - l = strtoul(e, &p, 10); - - if (errno > 0) { - r = -errno; - goto finish; - } - - if (!p || p == e || *p) { - r = -EINVAL; - goto finish; - } - - for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { - int flags; - - flags = fcntl(fd, F_GETFD); - if (flags < 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 -} - -_sd_export_ int sd_is_fifo(int fd, const char *path) { - struct stat st_fd; - - if (fd < 0) - return -EINVAL; - - if (fstat(fd, &st_fd) < 0) - return -errno; - - if (!S_ISFIFO(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; - } - - return - st_path.st_dev == st_fd.st_dev && - st_path.st_ino == st_fd.st_ino; - } - - 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; - - 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; -}; - -_sd_export_ int sd_is_socket(int fd, int family, int type, int listening) { - int r; - - if (family < 0) - return -EINVAL; - - r = sd_is_socket_internal(fd, type, listening); - if (r <= 0) - return r; - - if (family > 0) { - union sockaddr_union sockaddr = {}; - socklen_t 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; -} - -_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 = sizeof(sockaddr); - int r; - - if (family != 0 && family != AF_INET && family != AF_INET6) - return -EINVAL; - - r = sd_is_socket_internal(fd, type, listening); - if (r <= 0) - return r; - - 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; -} - -_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 = sizeof(sockaddr); - int r; - - r = sd_is_socket_internal(fd, type, listening); - if (r <= 0) - return r; - - 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 == offsetof(struct sockaddr_un, sun_path); - - if (path[0]) - /* Normal path socket */ - return - (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && - memcmp(path, sockaddr.un.sun_path, length+1) == 0; - else - /* Abstract namespace socket */ - return - (l == offsetof(struct sockaddr_un, sun_path) + length) && - memcmp(path, sockaddr.un.sun_path, length) == 0; - } - - return 1; -} - -_sd_export_ int sd_is_mq(int fd, const char *path) { -#if !defined(__linux__) || defined(SD_DAEMON_DISABLE_MQ) - 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 - int fd = -1, r; - struct msghdr msghdr; - struct iovec iovec; - union sockaddr_union sockaddr; - const char *e; - - if (!state) { - r = -EINVAL; - goto finish; - } - - e = getenv("NOTIFY_SOCKET"); - if (!e) - return 0; - - /* Must be an abstract socket, or an absolute path */ - if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { - r = -EINVAL; - goto finish; - } - - fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); - if (fd < 0) { - r = -errno; - goto finish; - } - - memzero(&sockaddr, 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; - - memzero(&iovec, sizeof(iovec)); - iovec.iov_base = (char*) state; - iovec.iov_len = strlen(state); - - memzero(&msghdr, sizeof(msghdr)); - msghdr.msg_name = &sockaddr; - 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); - - msghdr.msg_iov = &iovec; - msghdr.msg_iovlen = 1; - - 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 -} - -_sd_export_ 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 -} - -_sd_export_ int sd_booted(void) { -#if defined(DISABLE_SYSTEMD) || !defined(__linux__) - return 0; -#else - struct stat st; - - /* 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("/run/systemd/system/", &st) < 0) - return 0; - - return !!S_ISDIR(st.st_mode); -#endif -} - -_sd_export_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) { - -#if defined(DISABLE_SYSTEMD) || !defined(__linux__) - return 0; -#else - unsigned long long ll; - unsigned long l; - const char *e; - char *p = NULL; - int r; - - e = getenv("WATCHDOG_PID"); - if (!e) { - r = 0; - goto finish; - } - - errno = 0; - l = strtoul(e, &p, 10); - if (errno > 0) { - r = -errno; - goto finish; - } - if (!p || p == e || *p || l <= 0) { - r = -EINVAL; - goto finish; - } - - /* Is this for us? */ - if (getpid() != (pid_t) l) { - r = 0; - goto finish; - } - - e = getenv("WATCHDOG_USEC"); - if (!e) { - r = -EINVAL; - goto finish; - } - - errno = 0; - ll = strtoull(e, &p, 10); - if (errno > 0) { - r = -errno; - goto finish; - } - if (!p || p == e || *p || l <= 0) { - r = -EINVAL; - goto finish; - } - - if (usec) - *usec = ll; - - r = 1; - -finish: - if (unset_environment) { - unsetenv("WATCHDOG_PID"); - unsetenv("WATCHDOG_USEC"); - } - - return r; -#endif -} diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index b4e4af1f2d..258c932fc3 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -10,6 +10,21 @@ LIBSYSTEMD_209 { global: + /* originally LIBSYSTEMD_DAEMON_31 */ + sd_booted; + sd_is_fifo; + sd_is_mq; + sd_is_socket; + sd_is_socket_inet; + sd_is_socket_unix; + sd_is_special; + sd_listen_fds; + sd_notify; + sd_notifyf; + + /* LIBSYSTEMD_DAEMON_209 */ + sd_watchdog_enabled; + /* originally LIBSYSTEMD_ID128_38 */ sd_id128_to_string; sd_id128_from_string; diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c new file mode 100644 index 0000000000..21fb346bf8 --- /dev/null +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -0,0 +1,537 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "sd-daemon.h" + +_public_ int sd_listen_fds(int unset_environment) { + int r, fd; + const char *e; + char *p = NULL; + unsigned long l; + + e = getenv("LISTEN_PID"); + if (!e) { + r = 0; + goto finish; + } + + errno = 0; + l = strtoul(e, &p, 10); + + if (errno > 0) { + r = -errno; + goto finish; + } + + if (!p || p == e || *p || l <= 0) { + r = -EINVAL; + goto finish; + } + + /* Is this for us? */ + if (getpid() != (pid_t) l) { + r = 0; + goto finish; + } + + e = getenv("LISTEN_FDS"); + if (!e) { + r = 0; + goto finish; + } + + errno = 0; + l = strtoul(e, &p, 10); + + if (errno > 0) { + r = -errno; + goto finish; + } + + if (!p || p == e || *p) { + r = -EINVAL; + goto finish; + } + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { + int flags; + + flags = fcntl(fd, F_GETFD); + if (flags < 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; +} + +_public_ int sd_is_fifo(int fd, const char *path) { + struct stat st_fd; + + if (fd < 0) + return -EINVAL; + + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISFIFO(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; + } + + return + st_path.st_dev == st_fd.st_dev && + st_path.st_ino == st_fd.st_ino; + } + + return 1; +} + +_public_ 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; + + 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; +}; + +_public_ int sd_is_socket(int fd, int family, int type, int listening) { + int r; + + if (family < 0) + return -EINVAL; + + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) + return r; + + if (family > 0) { + union sockaddr_union sockaddr = {}; + socklen_t 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; +} + +_public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); + int r; + + if (family != 0 && family != AF_INET && family != AF_INET6) + return -EINVAL; + + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) + return r; + + 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; +} + +_public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); + int r; + + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) + return r; + + 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 == offsetof(struct sockaddr_un, sun_path); + + if (path[0]) + /* Normal path socket */ + return + (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && + memcmp(path, sockaddr.un.sun_path, length+1) == 0; + else + /* Abstract namespace socket */ + return + (l == offsetof(struct sockaddr_un, sun_path) + length) && + memcmp(path, sockaddr.un.sun_path, length) == 0; + } + + return 1; +} + +_public_ int sd_is_mq(int fd, const char *path) { + 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; +} + +_public_ int sd_notify(int unset_environment, const char *state) { + int fd = -1, r; + struct msghdr msghdr; + struct iovec iovec; + union sockaddr_union sockaddr; + const char *e; + + if (!state) { + r = -EINVAL; + goto finish; + } + + e = getenv("NOTIFY_SOCKET"); + if (!e) + return 0; + + /* Must be an abstract socket, or an absolute path */ + if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { + r = -EINVAL; + goto finish; + } + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) { + r = -errno; + goto finish; + } + + memzero(&sockaddr, 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; + + memzero(&iovec, sizeof(iovec)); + iovec.iov_base = (char*) state; + iovec.iov_len = strlen(state); + + memzero(&msghdr, sizeof(msghdr)); + msghdr.msg_name = &sockaddr; + 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); + + msghdr.msg_iov = &iovec; + msghdr.msg_iovlen = 1; + + 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; +} + +_public_ int sd_notifyf(int unset_environment, const char *format, ...) { + 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; +} + +_public_ int sd_booted(void) { + struct stat st; + + /* 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("/run/systemd/system/", &st) < 0) + return 0; + + return !!S_ISDIR(st.st_mode); +} + +_public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) { + unsigned long long ll; + unsigned long l; + const char *e; + char *p = NULL; + int r; + + e = getenv("WATCHDOG_PID"); + if (!e) { + r = 0; + goto finish; + } + + errno = 0; + l = strtoul(e, &p, 10); + if (errno > 0) { + r = -errno; + goto finish; + } + if (!p || p == e || *p || l <= 0) { + r = -EINVAL; + goto finish; + } + + /* Is this for us? */ + if (getpid() != (pid_t) l) { + r = 0; + goto finish; + } + + e = getenv("WATCHDOG_USEC"); + if (!e) { + r = -EINVAL; + goto finish; + } + + errno = 0; + ll = strtoull(e, &p, 10); + if (errno > 0) { + r = -errno; + goto finish; + } + if (!p || p == e || *p || l <= 0) { + r = -EINVAL; + goto finish; + } + + if (usec) + *usec = ll; + + r = 1; + +finish: + if (unset_environment) { + unsetenv("WATCHDOG_PID"); + unsetenv("WATCHDOG_USEC"); + } + + return r; +} diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h index 43deb8cc7d..f95fb51c25 100644 --- a/src/systemd/sd-daemon.h +++ b/src/systemd/sd-daemon.h @@ -30,17 +30,11 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +#include "_sd-common.h" -/* - Reference implementation of a few systemd related interfaces for - writing daemons. These interfaces are trivial to implement. To - simplify porting we provide this reference implementation. - Applications are welcome to reimplement the algorithms described - here if they do not want to include these two source files. +_SD_BEGIN_DECLARATIONS; +/* The following functionality is provided: - Support for logging with log levels on stderr @@ -48,33 +42,9 @@ extern "C" { - Daemon startup and status notification - Detection of systemd boots - You may compile this with -DDISABLE_SYSTEMD to disable systemd - support. This makes all those calls NOPs that are directly related to - systemd (i.e. only sd_is_xxx() will stay useful). - - Since this is drop-in code we don't want any of our symbols to be - exported in any case. Hence we declare hidden visibility for all of - them. - - You may find an up-to-date version of these source files online: - - http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h - http://cgit.freedesktop.org/systemd/systemd/plain/src/libsystemd-daemon/sd-daemon.c - - This should compile on non-Linux systems, too, but with the - exception of the sd_is_xxx() calls all functions will become NOPs. - See sd-daemon(3) for more information. */ -#ifndef _sd_printf_attr_ -# if __GNUC__ >= 4 -# define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) -# else -# define _sd_printf_attr_(a,b) -# endif -#endif - /* Log levels for usage on stderr: @@ -263,7 +233,7 @@ int sd_notify(int unset_environment, const char *state); See sd_notifyf(3) for more information. */ -int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); +int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_(2,3); /* Returns > 0 if the system was booted with systemd. Returns < 0 on @@ -294,8 +264,6 @@ int sd_booted(void); */ int sd_watchdog_enabled(int unset_environment, uint64_t *usec); -#ifdef __cplusplus -} -#endif +_SD_END_DECLARATIONS; #endif diff --git a/src/systemd/sd-readahead.h b/src/systemd/sd-readahead.h index 2dac104f7a..ed8300c9b3 100644 --- a/src/systemd/sd-readahead.h +++ b/src/systemd/sd-readahead.h @@ -34,7 +34,7 @@ extern "C" { /* Reference implementation of a few boot readahead related interfaces. These interfaces are trivial to implement. To simplify - porting we provide this reference implementation. Applications are + porting, we provide this reference implementation. Applications are welcome to reimplement the algorithms described here if they do not want to include these two source files. -- cgit v1.2.3-54-g00ecf