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