]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/fdset.c
tree-wide: remove Emacs lines from all files
[thirdparty/systemd.git] / src / basic / 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>
a16e1123 21#include <dirent.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
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
a354329f
LP
97int fdset_consume(FDSet *s, int fd) {
98 int r;
99
100 assert(s);
101 assert(fd >= 0);
102
103 r = fdset_put(s, fd);
104 if (r <= 0)
105 safe_close(fd);
106
107 return r;
108}
109
a16e1123
LP
110int fdset_put_dup(FDSet *s, int fd) {
111 int copy, r;
112
113 assert(s);
114 assert(fd >= 0);
115
e83c7163
LP
116 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
117 if (copy < 0)
a16e1123
LP
118 return -errno;
119
e83c7163
LP
120 r = fdset_put(s, copy);
121 if (r < 0) {
03e334a1 122 safe_close(copy);
a16e1123
LP
123 return r;
124 }
125
126 return copy;
127}
128
129bool fdset_contains(FDSet *s, int fd) {
130 assert(s);
131 assert(fd >= 0);
132
133 return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
134}
135
136int fdset_remove(FDSet *s, int fd) {
137 assert(s);
138 assert(fd >= 0);
139
140 return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
141}
142
143int fdset_new_fill(FDSet **_s) {
e1d75803 144 _cleanup_closedir_ DIR *d = NULL;
a16e1123
LP
145 struct dirent *de;
146 int r = 0;
147 FDSet *s;
148
149 assert(_s);
150
e83c7163 151 /* Creates an fdset and fills in all currently open file
a16e1123
LP
152 * descriptors. */
153
e83c7163
LP
154 d = opendir("/proc/self/fd");
155 if (!d)
a16e1123
LP
156 return -errno;
157
e83c7163
LP
158 s = fdset_new();
159 if (!s) {
a16e1123
LP
160 r = -ENOMEM;
161 goto finish;
162 }
163
164 while ((de = readdir(d))) {
165 int fd = -1;
166
a34bf9db 167 if (hidden_file(de->d_name))
a16e1123
LP
168 continue;
169
e83c7163
LP
170 r = safe_atoi(de->d_name, &fd);
171 if (r < 0)
a16e1123
LP
172 goto finish;
173
174 if (fd < 3)
175 continue;
176
177 if (fd == dirfd(d))
178 continue;
179
e83c7163
LP
180 r = fdset_put(s, fd);
181 if (r < 0)
a16e1123
LP
182 goto finish;
183 }
184
185 r = 0;
186 *_s = s;
187 s = NULL;
188
189finish:
a16e1123
LP
190 /* We won't close the fds here! */
191 if (s)
192 set_free(MAKE_SET(s));
193
194 return r;
a16e1123
LP
195}
196
197int fdset_cloexec(FDSet *fds, bool b) {
198 Iterator i;
199 void *p;
200 int r;
201
202 assert(fds);
203
3cc2aff1
LP
204 SET_FOREACH(p, MAKE_SET(fds), i) {
205 r = fd_cloexec(PTR_TO_FD(p), b);
206 if (r < 0)
a16e1123 207 return r;
3cc2aff1 208 }
a16e1123
LP
209
210 return 0;
211}
e83c7163
LP
212
213int fdset_new_listen_fds(FDSet **_s, bool unset) {
214 int n, fd, r;
215 FDSet *s;
216
217 assert(_s);
218
219 /* Creates an fdset and fills in all passed file descriptors */
220
221 s = fdset_new();
222 if (!s) {
223 r = -ENOMEM;
224 goto fail;
225 }
226
227 n = sd_listen_fds(unset);
228 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
229 r = fdset_put(s, fd);
230 if (r < 0)
231 goto fail;
232 }
233
234 *_s = s;
235 return 0;
236
237
238fail:
239 if (s)
240 set_free(MAKE_SET(s));
241
242 return r;
243}
244
245int fdset_close_others(FDSet *fds) {
246 void *e;
247 Iterator i;
248 int *a;
249 unsigned j, m;
250
251 j = 0, m = fdset_size(fds);
252 a = alloca(sizeof(int) * m);
253 SET_FOREACH(e, MAKE_SET(fds), i)
254 a[j++] = PTR_TO_FD(e);
255
256 assert(j == m);
257
258 return close_all_fds(a, j);
259}
260
261unsigned fdset_size(FDSet *fds) {
262 return set_size(MAKE_SET(fds));
263}
264
a354329f
LP
265bool fdset_isempty(FDSet *fds) {
266 return set_isempty(MAKE_SET(fds));
267}
268
e83c7163
LP
269int fdset_iterate(FDSet *s, Iterator *i) {
270 void *p;
271
8927b1da 272 if (!set_iterate(MAKE_SET(s), i, &p))
e83c7163
LP
273 return -ENOENT;
274
275 return PTR_TO_FD(p);
276}
a354329f
LP
277
278int fdset_steal_first(FDSet *fds) {
279 void *p;
280
281 p = set_steal_first(MAKE_SET(fds));
282 if (!p)
283 return -ENOENT;
284
285 return PTR_TO_FD(p);
286}