chiark / gitweb /
sd-daemon: turn sd-daemon.c into a shared library
[elogind.git] / src / sd-daemon.c
index 3bb258d3418570fe6c5ac8540c47c089a77b703e..e68b70875c749a22dcbbfc6d7338d2c848f3a317 100644 (file)
@@ -1,4 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 
 /***
   Copyright 2010 Lennart Poettering
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <stddef.h>
+#include <limits.h>
+
+#if defined(__linux__)
+#include <mqueue.h>
+#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;
@@ -124,7 +142,7 @@ 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)
@@ -157,6 +175,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,7 +262,7 @@ 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)
@@ -236,7 +290,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;
@@ -281,7 +335,7 @@ 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;
@@ -307,36 +361,68 @@ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t
 
                 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) {
-#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
+_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
         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,27 +455,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(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);
 
         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;
@@ -409,7 +483,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
@@ -431,7 +505,7 @@ 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
@@ -441,10 +515,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;