]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/fdset.c
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/>.
26 #include "sd-daemon.h"
28 #include "dirent-util.h"
32 #include "parse-util.h"
36 #define MAKE_SET(s) ((Set*) s)
37 #define MAKE_FDSET(s) ((FDSet*) s)
39 /* Make sure we can distinguish fd 0 and NULL */
40 #define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
41 #define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
43 FDSet
*fdset_new(void) {
44 return MAKE_FDSET(set_new(NULL
));
47 int fdset_new_array(FDSet
**ret
, int *fds
, unsigned n_fds
) {
58 for (i
= 0; i
< n_fds
; i
++) {
60 r
= fdset_put(s
, fds
[i
]);
62 set_free(MAKE_SET(s
));
71 FDSet
* fdset_free(FDSet
*s
) {
74 while ((p
= set_steal_first(MAKE_SET(s
)))) {
75 /* Valgrind's fd might have ended up in this set here,
76 * due to fdset_new_fill(). We'll ignore all failures
77 * here, so that the EBADFD that valgrind will return
78 * us on close() doesn't influence us */
80 /* When reloading duplicates of the private bus
81 * connection fds and suchlike are closed here, which
82 * has no effect at all, since they are only
83 * duplicates. So don't be surprised about these log
86 log_debug("Closing left-over fd %i", PTR_TO_FD(p
));
87 close_nointr(PTR_TO_FD(p
));
90 set_free(MAKE_SET(s
));
94 int fdset_put(FDSet
*s
, int fd
) {
98 return set_put(MAKE_SET(s
), FD_TO_PTR(fd
));
101 int fdset_consume(FDSet
*s
, int fd
) {
107 r
= fdset_put(s
, fd
);
114 int fdset_put_dup(FDSet
*s
, int fd
) {
120 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
124 r
= fdset_put(s
, copy
);
133 bool fdset_contains(FDSet
*s
, int fd
) {
137 return !!set_get(MAKE_SET(s
), FD_TO_PTR(fd
));
140 int fdset_remove(FDSet
*s
, int fd
) {
144 return set_remove(MAKE_SET(s
), FD_TO_PTR(fd
)) ? fd
: -ENOENT
;
147 int fdset_new_fill(FDSet
**_s
) {
148 _cleanup_closedir_
DIR *d
= NULL
;
155 /* Creates an fdset and fills in all currently open file
158 d
= opendir("/proc/self/fd");
168 while ((de
= readdir(d
))) {
171 if (hidden_file(de
->d_name
))
174 r
= safe_atoi(de
->d_name
, &fd
);
184 r
= fdset_put(s
, fd
);
194 /* We won't close the fds here! */
196 set_free(MAKE_SET(s
));
201 int fdset_cloexec(FDSet
*fds
, bool b
) {
208 SET_FOREACH(p
, MAKE_SET(fds
), i
) {
209 r
= fd_cloexec(PTR_TO_FD(p
), b
);
217 int fdset_new_listen_fds(FDSet
**_s
, bool unset
) {
223 /* Creates an fdset and fills in all passed file descriptors */
231 n
= sd_listen_fds(unset
);
232 for (fd
= SD_LISTEN_FDS_START
; fd
< SD_LISTEN_FDS_START
+ n
; fd
++) {
233 r
= fdset_put(s
, fd
);
244 set_free(MAKE_SET(s
));
249 int fdset_close_others(FDSet
*fds
) {
255 j
= 0, m
= fdset_size(fds
);
256 a
= alloca(sizeof(int) * m
);
257 SET_FOREACH(e
, MAKE_SET(fds
), i
)
258 a
[j
++] = PTR_TO_FD(e
);
262 return close_all_fds(a
, j
);
265 unsigned fdset_size(FDSet
*fds
) {
266 return set_size(MAKE_SET(fds
));
269 bool fdset_isempty(FDSet
*fds
) {
270 return set_isempty(MAKE_SET(fds
));
273 int fdset_iterate(FDSet
*s
, Iterator
*i
) {
276 if (!set_iterate(MAKE_SET(s
), i
, &p
))
282 int fdset_steal_first(FDSet
*fds
) {
285 p
= set_steal_first(MAKE_SET(fds
));