]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/fdset.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / shared / fdset.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a16e1123
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
a16e1123
LP
10 (at your option) any later version.
11
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
5430f7f2 15 Lesser General Public License for more details.
a16e1123 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
a16e1123
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
11c3a366 21#include <alloca.h>
cf0fbc49 22#include <errno.h>
a16e1123 23#include <fcntl.h>
11c3a366 24#include <stddef.h>
a16e1123 25
07630cea
LP
26#include "sd-daemon.h"
27
8fb3f009 28#include "dirent-util.h"
3ffd4af2
LP
29#include "fd-util.h"
30#include "fdset.h"
93cc7779 31#include "log.h"
3ffd4af2 32#include "macro.h"
6bedfcbb 33#include "parse-util.h"
11c3a366 34#include "path-util.h"
93cc7779 35#include "set.h"
a16e1123
LP
36
37#define MAKE_SET(s) ((Set*) s)
38#define MAKE_FDSET(s) ((FDSet*) s)
39
a16e1123 40FDSet *fdset_new(void) {
d5099efc 41 return MAKE_FDSET(set_new(NULL));
a16e1123
LP
42}
43
96d66d89 44int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds) {
a354329f
LP
45 unsigned i;
46 FDSet *s;
47 int r;
48
49 assert(ret);
50
51 s = fdset_new();
52 if (!s)
53 return -ENOMEM;
54
55 for (i = 0; i < n_fds; i++) {
56
57 r = fdset_put(s, fds[i]);
58 if (r < 0) {
59 set_free(MAKE_SET(s));
60 return r;
61 }
62 }
63
64 *ret = s;
65 return 0;
66}
67
68FDSet* fdset_free(FDSet *s) {
a16e1123
LP
69 void *p;
70
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 */
76
a7556052
LP
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
81 * messages. */
82
b23de6af 83 log_debug("Closing left-over fd %i", PTR_TO_FD(p));
a16e1123
LP
84 close_nointr(PTR_TO_FD(p));
85 }
86
87 set_free(MAKE_SET(s));
a354329f 88 return NULL;
a16e1123
LP
89}
90
91int fdset_put(FDSet *s, int fd) {
92 assert(s);
93 assert(fd >= 0);
94
95 return set_put(MAKE_SET(s), FD_TO_PTR(fd));
96}
97
98int fdset_put_dup(FDSet *s, int fd) {
99 int copy, r;
100
101 assert(s);
102 assert(fd >= 0);
103
e83c7163
LP
104 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
105 if (copy < 0)
a16e1123
LP
106 return -errno;
107
e83c7163
LP
108 r = fdset_put(s, copy);
109 if (r < 0) {
03e334a1 110 safe_close(copy);
a16e1123
LP
111 return r;
112 }
113
114 return copy;
115}
116
117bool fdset_contains(FDSet *s, int fd) {
118 assert(s);
119 assert(fd >= 0);
120
121 return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
122}
123
124int fdset_remove(FDSet *s, int fd) {
125 assert(s);
126 assert(fd >= 0);
127
128 return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
129}
130
131int fdset_new_fill(FDSet **_s) {
e1d75803 132 _cleanup_closedir_ DIR *d = NULL;
a16e1123
LP
133 struct dirent *de;
134 int r = 0;
135 FDSet *s;
136
137 assert(_s);
138
e83c7163 139 /* Creates an fdset and fills in all currently open file
a16e1123
LP
140 * descriptors. */
141
e83c7163
LP
142 d = opendir("/proc/self/fd");
143 if (!d)
a16e1123
LP
144 return -errno;
145
e83c7163
LP
146 s = fdset_new();
147 if (!s) {
a16e1123
LP
148 r = -ENOMEM;
149 goto finish;
150 }
151
8fb3f009 152 FOREACH_DIRENT(de, d, return -errno) {
a16e1123
LP
153 int fd = -1;
154
e83c7163
LP
155 r = safe_atoi(de->d_name, &fd);
156 if (r < 0)
a16e1123
LP
157 goto finish;
158
159 if (fd < 3)
160 continue;
161
162 if (fd == dirfd(d))
163 continue;
164
e83c7163
LP
165 r = fdset_put(s, fd);
166 if (r < 0)
a16e1123
LP
167 goto finish;
168 }
169
170 r = 0;
171 *_s = s;
172 s = NULL;
173
174finish:
a16e1123
LP
175 /* We won't close the fds here! */
176 if (s)
177 set_free(MAKE_SET(s));
178
179 return r;
a16e1123
LP
180}
181
182int fdset_cloexec(FDSet *fds, bool b) {
183 Iterator i;
184 void *p;
185 int r;
186
187 assert(fds);
188
3cc2aff1
LP
189 SET_FOREACH(p, MAKE_SET(fds), i) {
190 r = fd_cloexec(PTR_TO_FD(p), b);
191 if (r < 0)
a16e1123 192 return r;
3cc2aff1 193 }
a16e1123
LP
194
195 return 0;
196}
e83c7163
LP
197
198int fdset_new_listen_fds(FDSet **_s, bool unset) {
199 int n, fd, r;
200 FDSet *s;
201
202 assert(_s);
203
204 /* Creates an fdset and fills in all passed file descriptors */
205
206 s = fdset_new();
207 if (!s) {
208 r = -ENOMEM;
209 goto fail;
210 }
211
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);
215 if (r < 0)
216 goto fail;
217 }
218
219 *_s = s;
220 return 0;
221
222
223fail:
224 if (s)
225 set_free(MAKE_SET(s));
226
227 return r;
228}
229
230int fdset_close_others(FDSet *fds) {
231 void *e;
232 Iterator i;
233 int *a;
234 unsigned j, m;
235
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);
240
241 assert(j == m);
242
243 return close_all_fds(a, j);
244}
245
246unsigned fdset_size(FDSet *fds) {
247 return set_size(MAKE_SET(fds));
248}
249
a354329f
LP
250bool fdset_isempty(FDSet *fds) {
251 return set_isempty(MAKE_SET(fds));
252}
253
e83c7163
LP
254int fdset_iterate(FDSet *s, Iterator *i) {
255 void *p;
256
8927b1da 257 if (!set_iterate(MAKE_SET(s), i, &p))
e83c7163
LP
258 return -ENOENT;
259
260 return PTR_TO_FD(p);
261}
a354329f
LP
262
263int fdset_steal_first(FDSet *fds) {
264 void *p;
265
266 p = set_steal_first(MAKE_SET(fds));
267 if (!p)
268 return -ENOENT;
269
270 return PTR_TO_FD(p);
271}