]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/fdset.c
hwdb: Add support for HP ZBook Studio G5 keyboard (#17525)
[thirdparty/systemd.git] / src / shared / fdset.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a16e1123 2
cf0fbc49 3#include <errno.h>
a16e1123 4#include <fcntl.h>
11c3a366 5#include <stddef.h>
a16e1123 6
07630cea
LP
7#include "sd-daemon.h"
8
ae2a15bc 9#include "alloc-util.h"
8fb3f009 10#include "dirent-util.h"
3ffd4af2
LP
11#include "fd-util.h"
12#include "fdset.h"
93cc7779 13#include "log.h"
3ffd4af2 14#include "macro.h"
6bedfcbb 15#include "parse-util.h"
11c3a366 16#include "path-util.h"
93cc7779 17#include "set.h"
a16e1123
LP
18
19#define MAKE_SET(s) ((Set*) s)
20#define MAKE_FDSET(s) ((FDSet*) s)
21
a16e1123 22FDSet *fdset_new(void) {
d5099efc 23 return MAKE_FDSET(set_new(NULL));
a16e1123
LP
24}
25
da6053d0
LP
26int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds) {
27 size_t i;
a354329f
LP
28 FDSet *s;
29 int r;
30
31 assert(ret);
32
33 s = fdset_new();
34 if (!s)
35 return -ENOMEM;
36
37 for (i = 0; i < n_fds; i++) {
38
39 r = fdset_put(s, fds[i]);
40 if (r < 0) {
41 set_free(MAKE_SET(s));
42 return r;
43 }
44 }
45
46 *ret = s;
47 return 0;
48}
49
e4077ff6 50void fdset_close(FDSet *s) {
a16e1123
LP
51 void *p;
52
53 while ((p = set_steal_first(MAKE_SET(s)))) {
e4077ff6
LP
54 /* Valgrind's fd might have ended up in this set here, due to fdset_new_fill(). We'll ignore
55 * all failures here, so that the EBADFD that valgrind will return us on close() doesn't
56 * influence us */
57
58 /* When reloading duplicates of the private bus connection fds and suchlike are closed here,
59 * which has no effect at all, since they are only duplicates. So don't be surprised about
60 * these log messages. */
61
62 log_debug("Closing set fd %i", PTR_TO_FD(p));
63 (void) close_nointr(PTR_TO_FD(p));
a16e1123 64 }
e4077ff6 65}
a16e1123 66
e4077ff6
LP
67FDSet* fdset_free(FDSet *s) {
68 fdset_close(s);
a16e1123 69 set_free(MAKE_SET(s));
a354329f 70 return NULL;
a16e1123
LP
71}
72
73int fdset_put(FDSet *s, int fd) {
74 assert(s);
75 assert(fd >= 0);
76
77 return set_put(MAKE_SET(s), FD_TO_PTR(fd));
78}
79
80int fdset_put_dup(FDSet *s, int fd) {
81 int copy, r;
82
83 assert(s);
84 assert(fd >= 0);
85
e83c7163
LP
86 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
87 if (copy < 0)
a16e1123
LP
88 return -errno;
89
e83c7163
LP
90 r = fdset_put(s, copy);
91 if (r < 0) {
03e334a1 92 safe_close(copy);
a16e1123
LP
93 return r;
94 }
95
96 return copy;
97}
98
99bool fdset_contains(FDSet *s, int fd) {
100 assert(s);
101 assert(fd >= 0);
102
103 return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
104}
105
106int fdset_remove(FDSet *s, int fd) {
107 assert(s);
108 assert(fd >= 0);
109
110 return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
111}
112
113int fdset_new_fill(FDSet **_s) {
e1d75803 114 _cleanup_closedir_ DIR *d = NULL;
a16e1123
LP
115 struct dirent *de;
116 int r = 0;
117 FDSet *s;
118
119 assert(_s);
120
e83c7163 121 /* Creates an fdset and fills in all currently open file
a16e1123
LP
122 * descriptors. */
123
e83c7163
LP
124 d = opendir("/proc/self/fd");
125 if (!d)
a16e1123
LP
126 return -errno;
127
e83c7163
LP
128 s = fdset_new();
129 if (!s) {
a16e1123
LP
130 r = -ENOMEM;
131 goto finish;
132 }
133
8fb3f009 134 FOREACH_DIRENT(de, d, return -errno) {
a16e1123
LP
135 int fd = -1;
136
e83c7163
LP
137 r = safe_atoi(de->d_name, &fd);
138 if (r < 0)
a16e1123
LP
139 goto finish;
140
141 if (fd < 3)
142 continue;
143
144 if (fd == dirfd(d))
145 continue;
146
e83c7163
LP
147 r = fdset_put(s, fd);
148 if (r < 0)
a16e1123
LP
149 goto finish;
150 }
151
152 r = 0;
ae2a15bc 153 *_s = TAKE_PTR(s);
a16e1123
LP
154
155finish:
a16e1123
LP
156 /* We won't close the fds here! */
157 if (s)
158 set_free(MAKE_SET(s));
159
160 return r;
a16e1123
LP
161}
162
163int fdset_cloexec(FDSet *fds, bool b) {
a16e1123
LP
164 void *p;
165 int r;
166
167 assert(fds);
168
90e74a66 169 SET_FOREACH(p, MAKE_SET(fds)) {
3cc2aff1
LP
170 r = fd_cloexec(PTR_TO_FD(p), b);
171 if (r < 0)
a16e1123 172 return r;
3cc2aff1 173 }
a16e1123
LP
174
175 return 0;
176}
e83c7163
LP
177
178int fdset_new_listen_fds(FDSet **_s, bool unset) {
179 int n, fd, r;
180 FDSet *s;
181
182 assert(_s);
183
184 /* Creates an fdset and fills in all passed file descriptors */
185
186 s = fdset_new();
187 if (!s) {
188 r = -ENOMEM;
189 goto fail;
190 }
191
192 n = sd_listen_fds(unset);
193 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
194 r = fdset_put(s, fd);
195 if (r < 0)
196 goto fail;
197 }
198
199 *_s = s;
200 return 0;
201
e83c7163
LP
202fail:
203 if (s)
204 set_free(MAKE_SET(s));
205
206 return r;
207}
208
209int fdset_close_others(FDSet *fds) {
210 void *e;
8192548e 211 int *a = NULL;
da6053d0 212 size_t j = 0, m;
e83c7163 213
da6053d0 214 m = fdset_size(fds);
8192548e
DT
215
216 if (m > 0) {
217 a = newa(int, m);
90e74a66 218 SET_FOREACH(e, MAKE_SET(fds))
8192548e
DT
219 a[j++] = PTR_TO_FD(e);
220 }
e83c7163
LP
221
222 assert(j == m);
223
224 return close_all_fds(a, j);
225}
226
227unsigned fdset_size(FDSet *fds) {
228 return set_size(MAKE_SET(fds));
229}
230
a354329f
LP
231bool fdset_isempty(FDSet *fds) {
232 return set_isempty(MAKE_SET(fds));
233}
234
e83c7163
LP
235int fdset_iterate(FDSet *s, Iterator *i) {
236 void *p;
237
8927b1da 238 if (!set_iterate(MAKE_SET(s), i, &p))
e83c7163
LP
239 return -ENOENT;
240
241 return PTR_TO_FD(p);
242}
a354329f
LP
243
244int fdset_steal_first(FDSet *fds) {
245 void *p;
246
247 p = set_steal_first(MAKE_SET(fds));
248 if (!p)
249 return -ENOENT;
250
251 return PTR_TO_FD(p);
252}