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