]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/fdset.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "sd-daemon.h"
28 #include "dirent-util.h"
33 #include "parse-util.h"
34 #include "path-util.h"
37 #define MAKE_SET(s) ((Set*) s)
38 #define MAKE_FDSET(s) ((FDSet*) s)
40 FDSet
*fdset_new(void) {
41 return MAKE_FDSET(set_new(NULL
));
44 int fdset_new_array(FDSet
**ret
, const int *fds
, unsigned n_fds
) {
55 for (i
= 0; i
< n_fds
; i
++) {
57 r
= fdset_put(s
, fds
[i
]);
59 set_free(MAKE_SET(s
));
68 FDSet
* fdset_free(FDSet
*s
) {
71 while ((p
= set_steal_first(MAKE_SET(s
)))) {
72 /* Valgrind's fd might have ended up in this set here,
73 * due to fdset_new_fill(). We'll ignore all failures
74 * here, so that the EBADFD that valgrind will return
75 * us on close() doesn't influence us */
77 /* When reloading duplicates of the private bus
78 * connection fds and suchlike are closed here, which
79 * has no effect at all, since they are only
80 * duplicates. So don't be surprised about these log
83 log_debug("Closing left-over fd %i", PTR_TO_FD(p
));
84 close_nointr(PTR_TO_FD(p
));
87 set_free(MAKE_SET(s
));
91 int fdset_put(FDSet
*s
, int fd
) {
95 return set_put(MAKE_SET(s
), FD_TO_PTR(fd
));
98 int fdset_put_dup(FDSet
*s
, int fd
) {
104 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
108 r
= fdset_put(s
, copy
);
117 bool fdset_contains(FDSet
*s
, int fd
) {
121 return !!set_get(MAKE_SET(s
), FD_TO_PTR(fd
));
124 int fdset_remove(FDSet
*s
, int fd
) {
128 return set_remove(MAKE_SET(s
), FD_TO_PTR(fd
)) ? fd
: -ENOENT
;
131 int fdset_new_fill(FDSet
**_s
) {
132 _cleanup_closedir_
DIR *d
= NULL
;
139 /* Creates an fdset and fills in all currently open file
142 d
= opendir("/proc/self/fd");
152 FOREACH_DIRENT(de
, d
, return -errno
) {
155 r
= safe_atoi(de
->d_name
, &fd
);
165 r
= fdset_put(s
, fd
);
175 /* We won't close the fds here! */
177 set_free(MAKE_SET(s
));
182 int fdset_cloexec(FDSet
*fds
, bool b
) {
189 SET_FOREACH(p
, MAKE_SET(fds
), i
) {
190 r
= fd_cloexec(PTR_TO_FD(p
), b
);
198 int fdset_new_listen_fds(FDSet
**_s
, bool unset
) {
204 /* Creates an fdset and fills in all passed file descriptors */
212 n
= sd_listen_fds(unset
);
213 for (fd
= SD_LISTEN_FDS_START
; fd
< SD_LISTEN_FDS_START
+ n
; fd
++) {
214 r
= fdset_put(s
, fd
);
225 set_free(MAKE_SET(s
));
230 int fdset_close_others(FDSet
*fds
) {
236 j
= 0, m
= fdset_size(fds
);
237 a
= alloca(sizeof(int) * m
);
238 SET_FOREACH(e
, MAKE_SET(fds
), i
)
239 a
[j
++] = PTR_TO_FD(e
);
243 return close_all_fds(a
, j
);
246 unsigned fdset_size(FDSet
*fds
) {
247 return set_size(MAKE_SET(fds
));
250 bool fdset_isempty(FDSet
*fds
) {
251 return set_isempty(MAKE_SET(fds
));
254 int fdset_iterate(FDSet
*s
, Iterator
*i
) {
257 if (!set_iterate(MAKE_SET(s
), i
, &p
))
263 int fdset_steal_first(FDSet
*fds
) {
266 p
= set_steal_first(MAKE_SET(fds
));