3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering/***
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering This file is part of systemd.
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering Copyright 2010 Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering systemd is free software; you can redistribute it and/or modify it
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering under the terms of the GNU Lesser General Public License as published by
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering (at your option) any later version.
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering systemd is distributed in the hope that it will be useful, but
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering Lesser General Public License for more details.
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering You should have received a copy of the GNU Lesser General Public License
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering***/
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <errno.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <fcntl.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <sys/resource.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <sys/socket.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <sys/stat.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <unistd.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "macro.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "missing.h"
93cc7779e0c121b75183920173f37cd1ee9d59cfThomas Hindoe Paaboel Andersen#include "parse-util.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "path-util.h"
93cc7779e0c121b75183920173f37cd1ee9d59cfThomas Hindoe Paaboel Andersen#include "socket-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringint close_nointr(int fd) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(fd >= 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (close(fd) >= 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /*
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * Just ignore EINTR; a retry loop is the wrong thing to do on
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * Linux.
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering *
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * https://bugzilla.gnome.org/show_bug.cgi?id=682819
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (errno == EINTR)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringint safe_close(int fd) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /*
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * Like close_nointr() but cannot fail. Guarantees errno is
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * unchanged. Is a NOP with negative fds passed, and returns
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * -1, so that it can be used in this syntax:
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering *
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * fd = safe_close(fd);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fd >= 0) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering PROTECT_ERRNO;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* The kernel might return pretty much any error code
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * via close(), but the fd will be closed anyway. The
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * only condition we want to check for here is whether
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * the fd was invalid at all... */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert_se(close_nointr(fd) != -EBADF);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering }
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -1;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringvoid safe_close_pair(int p[]) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(p);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (p[0] == p[1]) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* Special case pairs which use the same fd in both
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * directions... */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering p[0] = p[1] = safe_close(p[0]);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering }
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering p[0] = safe_close(p[0]);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering p[1] = safe_close(p[1]);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringvoid close_many(const int fds[], unsigned n_fd) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering unsigned i;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(fds || n_fd <= 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering for (i = 0; i < n_fd; i++)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering safe_close(fds[i]);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringint fclose_nointr(FILE *f) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(f);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* Same as close_nointr(), but for fclose() */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fclose(f) == 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (errno == EINTR)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart PoetteringFILE* safe_fclose(FILE *f) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* Same as safe_close(), but for fclose() */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (f) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering PROTECT_ERRNO;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert_se(fclose_nointr(f) != EBADF);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering }
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return NULL;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart PoetteringDIR* safe_closedir(DIR *d) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (d) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering PROTECT_ERRNO;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert_se(closedir(d) >= 0 || errno != EBADF);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering }
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return NULL;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringint fd_nonblock(int fd, bool nonblock) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering int flags, nflags;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(fd >= 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering flags = fcntl(fd, F_GETFL, 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (flags < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (nonblock)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering nflags = flags | O_NONBLOCK;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering else
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering nflags = flags & ~O_NONBLOCK;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (nflags == flags)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fcntl(fd, F_SETFL, nflags) < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringint fd_cloexec(int fd, bool cloexec) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering int flags, nflags;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(fd >= 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering flags = fcntl(fd, F_GETFD, 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (flags < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (cloexec)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering nflags = flags | FD_CLOEXEC;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering else
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering nflags = flags & ~FD_CLOEXEC;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (nflags == flags)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fcntl(fd, F_SETFD, nflags) < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering unsigned i;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(n_fdset == 0 || fdset);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering for (i = 0; i < n_fdset; i++)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fdset[i] == fd)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return true;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return false;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringint close_all_fds(const int except[], unsigned n_except) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering _cleanup_closedir_ DIR *d = NULL;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering struct dirent *de;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering int r = 0;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(n_except == 0 || except);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering d = opendir("/proc/self/fd");
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (!d) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering int fd;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering struct rlimit rl;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* When /proc isn't available (for example in chroots)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * the fallback is brute forcing through the fd
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * table */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fd_in_set(fd, except, n_except))
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering continue;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (close_nointr(fd) < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (errno != EBADF && r == 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering r = -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering }
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return r;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering }
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering while ((de = readdir(d))) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering int fd = -1;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (hidden_file(de->d_name))
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering continue;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (safe_atoi(de->d_name, &fd) < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* Let's better ignore this, just in case */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering continue;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fd < 3)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering continue;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fd == dirfd(d))
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering continue;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fd_in_set(fd, except, n_except))
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering continue;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (close_nointr(fd) < 0) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* Valgrind has its own FD and doesn't want to have it closed */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (errno != EBADF && r == 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering r = -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering }
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering }
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return r;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringint same_fd(int a, int b) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering struct stat sta, stb;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering pid_t pid;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering int r, fa, fb;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(a >= 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(b >= 0);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* Compares two file descriptors. Note that semantics are
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * quite different depending on whether we have kcmp() or we
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * don't. If we have kcmp() this will only return true for
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * dup()ed file descriptors, but not otherwise. If we don't
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * have kcmp() this will also return true for two fds of the same
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * file, created by separate open() calls. Since we use this
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * call mostly for filtering out duplicates in the fd store
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * this difference hopefully doesn't matter too much. */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (a == b)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return true;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* Try to use kcmp() if we have it. */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering pid = getpid();
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering r = kcmp(pid, pid, KCMP_FILE, a, b);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (r == 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return true;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (r > 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return false;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (errno != ENOSYS)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* We don't have kcmp(), use fstat() instead. */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fstat(a, &sta) < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fstat(b, &stb) < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return false;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* We consider all device fds different, since two device fds
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * might refer to quite different device contexts even though
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * they share the same inode and backing dev_t. */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return false;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return false;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering /* The fds refer to the same inode on disk, let's also check
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * if they have the same fd flags. This is useful to
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * distinguish the read and write side of a pipe created with
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering * pipe(). */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering fa = fcntl(a, F_GETFL);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fa < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering fb = fcntl(b, F_GETFL);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (fb < 0)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return -errno;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return fa == fb;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringvoid cmsg_close_all(struct msghdr *mh) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering struct cmsghdr *cmsg;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering assert(mh);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering CMSG_FOREACH(cmsg, mh)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering}
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poetteringbool fdname_is_valid(const char *s) {
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering const char *p;
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering /* Validates a name for $LISTEN_FDNAMES. We basically allow
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering * everything ASCII that's not a control character. Also, as
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering * special exception the ":" character is not allowed, as we
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering * use that as field separator in $LISTEN_FDNAMES.
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering *
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering * Note that the empty string is explicitly allowed
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering * here. However, we limit the length of the names to 255
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering * characters. */
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering if (!s)
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering return false;
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering for (p = s; *p; p++) {
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering if (*p < ' ')
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering return false;
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering if (*p >= 127)
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering return false;
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering if (*p == ':')
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering return false;
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering }
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering return p - s < 256;
4fee397531c97d22e41fb3f02452e82d412fe2b5Lennart Poettering}