]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/fdset.c
tree-wide: drop redundant if checks before safe_close()
[thirdparty/systemd.git] / src / basic / fdset.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
a16e1123
LP
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a16e1123
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a16e1123 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a16e1123
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
23#include <dirent.h>
24#include <fcntl.h>
a16e1123
LP
25
26#include "set.h"
27#include "util.h"
28#include "macro.h"
29#include "fdset.h"
e83c7163 30#include "sd-daemon.h"
a16e1123
LP
31
32#define MAKE_SET(s) ((Set*) s)
33#define MAKE_FDSET(s) ((FDSet*) s)
34
45afd519 35/* Make sure we can distinguish fd 0 and NULL */
a16e1123
LP
36#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
37#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
38
39FDSet *fdset_new(void) {
d5099efc 40 return MAKE_FDSET(set_new(NULL));
a16e1123
LP
41}
42
a354329f
LP
43int fdset_new_array(FDSet **ret, int *fds, unsigned n_fds) {
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
204 SET_FOREACH(p, MAKE_SET(fds), i)
205 if ((r = fd_cloexec(PTR_TO_FD(p), b)) < 0)
206 return r;
207
208 return 0;
209}
e83c7163
LP
210
211int fdset_new_listen_fds(FDSet **_s, bool unset) {
212 int n, fd, r;
213 FDSet *s;
214
215 assert(_s);
216
217 /* Creates an fdset and fills in all passed file descriptors */
218
219 s = fdset_new();
220 if (!s) {
221 r = -ENOMEM;
222 goto fail;
223 }
224
225 n = sd_listen_fds(unset);
226 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
227 r = fdset_put(s, fd);
228 if (r < 0)
229 goto fail;
230 }
231
232 *_s = s;
233 return 0;
234
235
236fail:
237 if (s)
238 set_free(MAKE_SET(s));
239
240 return r;
241}
242
243int fdset_close_others(FDSet *fds) {
244 void *e;
245 Iterator i;
246 int *a;
247 unsigned j, m;
248
249 j = 0, m = fdset_size(fds);
250 a = alloca(sizeof(int) * m);
251 SET_FOREACH(e, MAKE_SET(fds), i)
252 a[j++] = PTR_TO_FD(e);
253
254 assert(j == m);
255
256 return close_all_fds(a, j);
257}
258
259unsigned fdset_size(FDSet *fds) {
260 return set_size(MAKE_SET(fds));
261}
262
a354329f
LP
263bool fdset_isempty(FDSet *fds) {
264 return set_isempty(MAKE_SET(fds));
265}
266
e83c7163
LP
267int fdset_iterate(FDSet *s, Iterator *i) {
268 void *p;
269
8927b1da 270 if (!set_iterate(MAKE_SET(s), i, &p))
e83c7163
LP
271 return -ENOENT;
272
273 return PTR_TO_FD(p);
274}
a354329f
LP
275
276int fdset_steal_first(FDSet *fds) {
277 void *p;
278
279 p = set_steal_first(MAKE_SET(fds));
280 if (!p)
281 return -ENOENT;
282
283 return PTR_TO_FD(p);
284}