1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #define MAKE_SET(s) ((Set*) s)
33 #define MAKE_FDSET(s) ((FDSet*) s)
35 /* Make sure we can distuingish fd 0 and NULL */
36 #define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
37 #define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
39 FDSet *fdset_new(void) {
40 return MAKE_FDSET(set_new(trivial_hash_func, trivial_compare_func));
43 void fdset_free(FDSet *s) {
46 while ((p = set_steal_first(MAKE_SET(s)))) {
47 /* Valgrind's fd might have ended up in this set here,
48 * due to fdset_new_fill(). We'll ignore all failures
49 * here, so that the EBADFD that valgrind will return
50 * us on close() doesn't influence us */
52 /* When reloading duplicates of the private bus
53 * connection fds and suchlike are closed here, which
54 * has no effect at all, since they are only
55 * duplicates. So don't be surprised about these log
58 log_debug("Closing left-over fd %i", PTR_TO_FD(p));
59 close_nointr(PTR_TO_FD(p));
62 set_free(MAKE_SET(s));
65 int fdset_put(FDSet *s, int fd) {
69 return set_put(MAKE_SET(s), FD_TO_PTR(fd));
72 int fdset_put_dup(FDSet *s, int fd) {
78 if ((copy = fcntl(fd, F_DUPFD_CLOEXEC, 3)) < 0)
81 if ((r = fdset_put(s, copy)) < 0) {
82 close_nointr_nofail(copy);
89 bool fdset_contains(FDSet *s, int fd) {
93 return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
96 int fdset_remove(FDSet *s, int fd) {
100 return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
103 int fdset_new_fill(FDSet **_s) {
111 /* Creates an fdsets and fills in all currently open file
114 if (!(d = opendir("/proc/self/fd")))
117 if (!(s = fdset_new())) {
122 while ((de = readdir(d))) {
125 if (ignore_file(de->d_name))
128 if ((r = safe_atoi(de->d_name, &fd)) < 0)
137 if ((r = fdset_put(s, fd)) < 0)
148 /* We won't close the fds here! */
150 set_free(MAKE_SET(s));
155 int fdset_cloexec(FDSet *fds, bool b) {
162 SET_FOREACH(p, MAKE_SET(fds), i)
163 if ((r = fd_cloexec(PTR_TO_FD(p), b)) < 0)