]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/fdset.c
util: split out escaping code into escape.[ch]
[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
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}