]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/fdset.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / shared / fdset.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a16e1123 2
11c3a366 3#include <alloca.h>
cf0fbc49 4#include <errno.h>
a16e1123 5#include <fcntl.h>
11c3a366 6#include <stddef.h>
a16e1123 7
07630cea
LP
8#include "sd-daemon.h"
9
ae2a15bc 10#include "alloc-util.h"
8fb3f009 11#include "dirent-util.h"
3ffd4af2
LP
12#include "fd-util.h"
13#include "fdset.h"
93cc7779 14#include "log.h"
3ffd4af2 15#include "macro.h"
6bedfcbb 16#include "parse-util.h"
11c3a366 17#include "path-util.h"
93cc7779 18#include "set.h"
a16e1123
LP
19
20#define MAKE_SET(s) ((Set*) s)
21#define MAKE_FDSET(s) ((FDSet*) s)
22
a16e1123 23FDSet *fdset_new(void) {
d5099efc 24 return MAKE_FDSET(set_new(NULL));
a16e1123
LP
25}
26
da6053d0
LP
27int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds) {
28 size_t i;
a354329f
LP
29 FDSet *s;
30 int r;
31
32 assert(ret);
33
34 s = fdset_new();
35 if (!s)
36 return -ENOMEM;
37
38 for (i = 0; i < n_fds; i++) {
39
40 r = fdset_put(s, fds[i]);
41 if (r < 0) {
42 set_free(MAKE_SET(s));
43 return r;
44 }
45 }
46
47 *ret = s;
48 return 0;
49}
50
51FDSet* fdset_free(FDSet *s) {
a16e1123
LP
52 void *p;
53
54 while ((p = set_steal_first(MAKE_SET(s)))) {
55 /* Valgrind's fd might have ended up in this set here,
56 * due to fdset_new_fill(). We'll ignore all failures
57 * here, so that the EBADFD that valgrind will return
58 * us on close() doesn't influence us */
59
a7556052
LP
60 /* When reloading duplicates of the private bus
61 * connection fds and suchlike are closed here, which
62 * has no effect at all, since they are only
63 * duplicates. So don't be surprised about these log
64 * messages. */
65
b23de6af 66 log_debug("Closing left-over fd %i", PTR_TO_FD(p));
a16e1123
LP
67 close_nointr(PTR_TO_FD(p));
68 }
69
70 set_free(MAKE_SET(s));
a354329f 71 return NULL;
a16e1123
LP
72}
73
74int fdset_put(FDSet *s, int fd) {
75 assert(s);
76 assert(fd >= 0);
77
78 return set_put(MAKE_SET(s), FD_TO_PTR(fd));
79}
80
81int fdset_put_dup(FDSet *s, int fd) {
82 int copy, r;
83
84 assert(s);
85 assert(fd >= 0);
86
e83c7163
LP
87 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
88 if (copy < 0)
a16e1123
LP
89 return -errno;
90
e83c7163
LP
91 r = fdset_put(s, copy);
92 if (r < 0) {
03e334a1 93 safe_close(copy);
a16e1123
LP
94 return r;
95 }
96
97 return copy;
98}
99
100bool fdset_contains(FDSet *s, int fd) {
101 assert(s);
102 assert(fd >= 0);
103
104 return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
105}
106
107int fdset_remove(FDSet *s, int fd) {
108 assert(s);
109 assert(fd >= 0);
110
111 return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
112}
113
114int fdset_new_fill(FDSet **_s) {
e1d75803 115 _cleanup_closedir_ DIR *d = NULL;
a16e1123
LP
116 struct dirent *de;
117 int r = 0;
118 FDSet *s;
119
120 assert(_s);
121
e83c7163 122 /* Creates an fdset and fills in all currently open file
a16e1123
LP
123 * descriptors. */
124
e83c7163
LP
125 d = opendir("/proc/self/fd");
126 if (!d)
a16e1123
LP
127 return -errno;
128
e83c7163
LP
129 s = fdset_new();
130 if (!s) {
a16e1123
LP
131 r = -ENOMEM;
132 goto finish;
133 }
134
8fb3f009 135 FOREACH_DIRENT(de, d, return -errno) {
a16e1123
LP
136 int fd = -1;
137
e83c7163
LP
138 r = safe_atoi(de->d_name, &fd);
139 if (r < 0)
a16e1123
LP
140 goto finish;
141
142 if (fd < 3)
143 continue;
144
145 if (fd == dirfd(d))
146 continue;
147
e83c7163
LP
148 r = fdset_put(s, fd);
149 if (r < 0)
a16e1123
LP
150 goto finish;
151 }
152
153 r = 0;
ae2a15bc 154 *_s = TAKE_PTR(s);
a16e1123
LP
155
156finish:
a16e1123
LP
157 /* We won't close the fds here! */
158 if (s)
159 set_free(MAKE_SET(s));
160
161 return r;
a16e1123
LP
162}
163
164int fdset_cloexec(FDSet *fds, bool b) {
165 Iterator i;
166 void *p;
167 int r;
168
169 assert(fds);
170
3cc2aff1
LP
171 SET_FOREACH(p, MAKE_SET(fds), i) {
172 r = fd_cloexec(PTR_TO_FD(p), b);
173 if (r < 0)
a16e1123 174 return r;
3cc2aff1 175 }
a16e1123
LP
176
177 return 0;
178}
e83c7163
LP
179
180int fdset_new_listen_fds(FDSet **_s, bool unset) {
181 int n, fd, r;
182 FDSet *s;
183
184 assert(_s);
185
186 /* Creates an fdset and fills in all passed file descriptors */
187
188 s = fdset_new();
189 if (!s) {
190 r = -ENOMEM;
191 goto fail;
192 }
193
194 n = sd_listen_fds(unset);
195 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
196 r = fdset_put(s, fd);
197 if (r < 0)
198 goto fail;
199 }
200
201 *_s = s;
202 return 0;
203
e83c7163
LP
204fail:
205 if (s)
206 set_free(MAKE_SET(s));
207
208 return r;
209}
210
211int fdset_close_others(FDSet *fds) {
212 void *e;
213 Iterator i;
214 int *a;
da6053d0 215 size_t j = 0, m;
e83c7163 216
da6053d0
LP
217 m = fdset_size(fds);
218 a = newa(int, m);
e83c7163
LP
219 SET_FOREACH(e, MAKE_SET(fds), i)
220 a[j++] = PTR_TO_FD(e);
221
222 assert(j == m);
223
224 return close_all_fds(a, j);
225}
226
227unsigned fdset_size(FDSet *fds) {
228 return set_size(MAKE_SET(fds));
229}
230
a354329f
LP
231bool fdset_isempty(FDSet *fds) {
232 return set_isempty(MAKE_SET(fds));
233}
234
e83c7163
LP
235int fdset_iterate(FDSet *s, Iterator *i) {
236 void *p;
237
8927b1da 238 if (!set_iterate(MAKE_SET(s), i, &p))
e83c7163
LP
239 return -ENOENT;
240
241 return PTR_TO_FD(p);
242}
a354329f
LP
243
244int fdset_steal_first(FDSet *fds) {
245 void *p;
246
247 p = set_steal_first(MAKE_SET(fds));
248 if (!p)
249 return -ENOENT;
250
251 return PTR_TO_FD(p);
252}