]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/fdset.c
Merge pull request #1693 from ssahani/word
[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 25
07630cea
LP
26#include "sd-daemon.h"
27
3ffd4af2
LP
28#include "fd-util.h"
29#include "fdset.h"
30#include "macro.h"
a16e1123
LP
31#include "set.h"
32#include "util.h"
a16e1123
LP
33
34#define MAKE_SET(s) ((Set*) s)
35#define MAKE_FDSET(s) ((FDSet*) s)
36
45afd519 37/* Make sure we can distinguish fd 0 and NULL */
a16e1123
LP
38#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
39#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
40
41FDSet *fdset_new(void) {
d5099efc 42 return MAKE_FDSET(set_new(NULL));
a16e1123
LP
43}
44
a354329f
LP
45int fdset_new_array(FDSet **ret, int *fds, unsigned n_fds) {
46 unsigned i;
47 FDSet *s;
48 int r;
49
50 assert(ret);
51
52 s = fdset_new();
53 if (!s)
54 return -ENOMEM;
55
56 for (i = 0; i < n_fds; i++) {
57
58 r = fdset_put(s, fds[i]);
59 if (r < 0) {
60 set_free(MAKE_SET(s));
61 return r;
62 }
63 }
64
65 *ret = s;
66 return 0;
67}
68
69FDSet* fdset_free(FDSet *s) {
a16e1123
LP
70 void *p;
71
72 while ((p = set_steal_first(MAKE_SET(s)))) {
73 /* Valgrind's fd might have ended up in this set here,
74 * due to fdset_new_fill(). We'll ignore all failures
75 * here, so that the EBADFD that valgrind will return
76 * us on close() doesn't influence us */
77
a7556052
LP
78 /* When reloading duplicates of the private bus
79 * connection fds and suchlike are closed here, which
80 * has no effect at all, since they are only
81 * duplicates. So don't be surprised about these log
82 * messages. */
83
b23de6af 84 log_debug("Closing left-over fd %i", PTR_TO_FD(p));
a16e1123
LP
85 close_nointr(PTR_TO_FD(p));
86 }
87
88 set_free(MAKE_SET(s));
a354329f 89 return NULL;
a16e1123
LP
90}
91
92int fdset_put(FDSet *s, int fd) {
93 assert(s);
94 assert(fd >= 0);
95
96 return set_put(MAKE_SET(s), FD_TO_PTR(fd));
97}
98
a354329f
LP
99int fdset_consume(FDSet *s, int fd) {
100 int r;
101
102 assert(s);
103 assert(fd >= 0);
104
105 r = fdset_put(s, fd);
106 if (r <= 0)
107 safe_close(fd);
108
109 return r;
110}
111
a16e1123
LP
112int fdset_put_dup(FDSet *s, int fd) {
113 int copy, r;
114
115 assert(s);
116 assert(fd >= 0);
117
e83c7163
LP
118 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
119 if (copy < 0)
a16e1123
LP
120 return -errno;
121
e83c7163
LP
122 r = fdset_put(s, copy);
123 if (r < 0) {
03e334a1 124 safe_close(copy);
a16e1123
LP
125 return r;
126 }
127
128 return copy;
129}
130
131bool fdset_contains(FDSet *s, int fd) {
132 assert(s);
133 assert(fd >= 0);
134
135 return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
136}
137
138int fdset_remove(FDSet *s, int fd) {
139 assert(s);
140 assert(fd >= 0);
141
142 return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
143}
144
145int fdset_new_fill(FDSet **_s) {
e1d75803 146 _cleanup_closedir_ DIR *d = NULL;
a16e1123
LP
147 struct dirent *de;
148 int r = 0;
149 FDSet *s;
150
151 assert(_s);
152
e83c7163 153 /* Creates an fdset and fills in all currently open file
a16e1123
LP
154 * descriptors. */
155
e83c7163
LP
156 d = opendir("/proc/self/fd");
157 if (!d)
a16e1123
LP
158 return -errno;
159
e83c7163
LP
160 s = fdset_new();
161 if (!s) {
a16e1123
LP
162 r = -ENOMEM;
163 goto finish;
164 }
165
166 while ((de = readdir(d))) {
167 int fd = -1;
168
a34bf9db 169 if (hidden_file(de->d_name))
a16e1123
LP
170 continue;
171
e83c7163
LP
172 r = safe_atoi(de->d_name, &fd);
173 if (r < 0)
a16e1123
LP
174 goto finish;
175
176 if (fd < 3)
177 continue;
178
179 if (fd == dirfd(d))
180 continue;
181
e83c7163
LP
182 r = fdset_put(s, fd);
183 if (r < 0)
a16e1123
LP
184 goto finish;
185 }
186
187 r = 0;
188 *_s = s;
189 s = NULL;
190
191finish:
a16e1123
LP
192 /* We won't close the fds here! */
193 if (s)
194 set_free(MAKE_SET(s));
195
196 return r;
a16e1123
LP
197}
198
199int fdset_cloexec(FDSet *fds, bool b) {
200 Iterator i;
201 void *p;
202 int r;
203
204 assert(fds);
205
3cc2aff1
LP
206 SET_FOREACH(p, MAKE_SET(fds), i) {
207 r = fd_cloexec(PTR_TO_FD(p), b);
208 if (r < 0)
a16e1123 209 return r;
3cc2aff1 210 }
a16e1123
LP
211
212 return 0;
213}
e83c7163
LP
214
215int fdset_new_listen_fds(FDSet **_s, bool unset) {
216 int n, fd, r;
217 FDSet *s;
218
219 assert(_s);
220
221 /* Creates an fdset and fills in all passed file descriptors */
222
223 s = fdset_new();
224 if (!s) {
225 r = -ENOMEM;
226 goto fail;
227 }
228
229 n = sd_listen_fds(unset);
230 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
231 r = fdset_put(s, fd);
232 if (r < 0)
233 goto fail;
234 }
235
236 *_s = s;
237 return 0;
238
239
240fail:
241 if (s)
242 set_free(MAKE_SET(s));
243
244 return r;
245}
246
247int fdset_close_others(FDSet *fds) {
248 void *e;
249 Iterator i;
250 int *a;
251 unsigned j, m;
252
253 j = 0, m = fdset_size(fds);
254 a = alloca(sizeof(int) * m);
255 SET_FOREACH(e, MAKE_SET(fds), i)
256 a[j++] = PTR_TO_FD(e);
257
258 assert(j == m);
259
260 return close_all_fds(a, j);
261}
262
263unsigned fdset_size(FDSet *fds) {
264 return set_size(MAKE_SET(fds));
265}
266
a354329f
LP
267bool fdset_isempty(FDSet *fds) {
268 return set_isempty(MAKE_SET(fds));
269}
270
e83c7163
LP
271int fdset_iterate(FDSet *s, Iterator *i) {
272 void *p;
273
8927b1da 274 if (!set_iterate(MAKE_SET(s), i, &p))
e83c7163
LP
275 return -ENOENT;
276
277 return PTR_TO_FD(p);
278}
a354329f
LP
279
280int fdset_steal_first(FDSet *fds) {
281 void *p;
282
283 p = set_steal_first(MAKE_SET(fds));
284 if (!p)
285 return -ENOENT;
286
287 return PTR_TO_FD(p);
288}