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