static void test_fdset_cloexec(void) { int fd = -1; _cleanup_fdset_free_ FDSet *fdset = NULL; int flags = -1; char name[] = "/tmp/test-fdset_cloexec.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); assert_se(fdset_put(fdset, fd)); assert_se(fdset_cloexec(fdset, false) >= 0); flags = fcntl(fd, F_GETFD); assert_se(flags >= 0); assert_se(!(flags & FD_CLOEXEC)); assert_se(fdset_cloexec(fdset, true) >= 0); flags = fcntl(fd, F_GETFD); assert_se(flags >= 0); assert_se(flags & FD_CLOEXEC); unlink(name); }
int fdset_new_listen_fds(FDSet **_s, bool unset) { int n, fd, r; FDSet *s; assert(_s); /* Creates an fdset and fills in all passed file descriptors */ s = fdset_new(); if (!s) { r = -ENOMEM; goto fail; } n = sd_listen_fds(unset); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { r = fdset_put(s, fd); if (r < 0) goto fail; } *_s = s; return 0; fail: if (s) set_free(MAKE_SET(s)); return r; }
int fdset_new_fill(FDSet **_s) { DIR *d; struct dirent *de; int r = 0; FDSet *s; assert(_s); /* Creates an fdset and fills in all currently open file * descriptors. */ d = opendir("/proc/self/fd"); if (!d) return -errno; s = fdset_new(); if (!s) { r = -ENOMEM; goto finish; } while ((de = readdir(d))) { int fd = -1; if (ignore_file(de->d_name)) continue; r = safe_atoi(de->d_name, &fd); if (r < 0) goto finish; if (fd < 3) continue; if (fd == dirfd(d)) continue; r = fdset_put(s, fd); if (r < 0) goto finish; } r = 0; *_s = s; s = NULL; finish: closedir(d); /* We won't close the fds here! */ if (s) set_free(MAKE_SET(s)); return r; }
int fdset_consume(FDSet *s, int fd) { int r; assert(s); assert(fd >= 0); r = fdset_put(s, fd); if (r <= 0) safe_close(fd); return r; }
static void test_fdset_iterate(void) { int fd = -1; FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_iterate.XXXXXX"; Iterator i; int c = 0; int a; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); assert_se(fdset_put(fdset, fd) >= 0); assert_se(fdset_put(fdset, fd) >= 0); assert_se(fdset_put(fdset, fd) >= 0); FDSET_FOREACH(a, fdset, i) { c++; assert_se(a == fd); }
int fdset_put_dup(FDSet *s, int fd) { int copy, r; assert(s); assert(fd >= 0); if ((copy = fcntl(fd, F_DUPFD_CLOEXEC, 3)) < 0) return -errno; if ((r = fdset_put(s, copy)) < 0) { close_nointr_nofail(copy); return r; } return copy; }
int fdset_put_dup(FDSet *s, int fd) { int copy, r; assert(s); assert(fd >= 0); copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (copy < 0) return -errno; r = fdset_put(s, copy); if (r < 0) { safe_close(copy); return r; } return copy; }
static void test_fdset_remove(void) { _cleanup_close_ int fd = -1; FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_remove.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); assert_se(fdset_put(fdset, fd) >= 0); assert_se(fdset_remove(fdset, fd) >= 0); assert_se(!fdset_contains(fdset, fd)); fdset_free(fdset); assert_se(fcntl(fd, F_GETFD) >= 0); unlink(name); }
int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds) { unsigned i; FDSet *s; int r; assert(ret); s = fdset_new(); if (!s) return -ENOMEM; for (i = 0; i < n_fds; i++) { r = fdset_put(s, fds[i]); if (r < 0) { set_free(MAKE_SET(s)); return r; } } *ret = s; return 0; }
static int server_init(Server *s, unsigned n_sockets) { int r; unsigned i; struct epoll_event ev; sigset_t mask; assert(s); assert(n_sockets > 0); zero(*s); s->kmsg_fd = s->signal_fd = -1; if ((s->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0) { r = -errno; log_error("Failed to create epoll object: %s", strerror(errno)); goto fail; } if (!(s->syslog_fds = fdset_new())) { r = -ENOMEM; log_error("Failed to allocate file descriptor set: %s", strerror(errno)); goto fail; } for (i = 0; i < n_sockets; i++) { int fd, one = 1; fd = SD_LISTEN_FDS_START+i; if ((r = sd_is_socket(fd, AF_UNSPEC, SOCK_DGRAM, -1)) < 0) { log_error("Failed to determine file descriptor type: %s", strerror(-r)); goto fail; } if (!r) { log_error("Wrong file descriptor type."); r = -EINVAL; goto fail; } if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) log_error("SO_PASSCRED failed: %m"); zero(ev); ev.events = EPOLLIN; ev.data.fd = fd; if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { r = -errno; log_error("Failed to add server fd to epoll object: %s", strerror(errno)); goto fail; } if ((r = fdset_put(s->syslog_fds, fd)) < 0) { log_error("Failed to store file descriptor in set: %s", strerror(-r)); goto fail; } } if ((s->kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) { log_error("Failed to open /dev/kmsg for logging: %m"); return -errno; } assert_se(sigemptyset(&mask) == 0); sigset_add_many(&mask, SIGINT, SIGTERM, -1); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); if ((s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) { log_error("signalfd(): %m"); return -errno; } zero(ev); ev.events = EPOLLIN; ev.data.fd = s->signal_fd; if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->signal_fd, &ev) < 0) { log_error("epoll_ctl(): %m"); return -errno; } return 0; fail: server_done(s); return r; }