]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/fd-util.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[thirdparty/systemd.git] / src / basic / fd-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
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
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
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
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "fd-util.h"
23 #include "parse-util.h"
24 #include "util.h"
25
26 int close_nointr(int fd) {
27 assert(fd >= 0);
28
29 if (close(fd) >= 0)
30 return 0;
31
32 /*
33 * Just ignore EINTR; a retry loop is the wrong thing to do on
34 * Linux.
35 *
36 * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
37 * https://bugzilla.gnome.org/show_bug.cgi?id=682819
38 * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
39 * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
40 */
41 if (errno == EINTR)
42 return 0;
43
44 return -errno;
45 }
46
47 int safe_close(int fd) {
48
49 /*
50 * Like close_nointr() but cannot fail. Guarantees errno is
51 * unchanged. Is a NOP with negative fds passed, and returns
52 * -1, so that it can be used in this syntax:
53 *
54 * fd = safe_close(fd);
55 */
56
57 if (fd >= 0) {
58 PROTECT_ERRNO;
59
60 /* The kernel might return pretty much any error code
61 * via close(), but the fd will be closed anyway. The
62 * only condition we want to check for here is whether
63 * the fd was invalid at all... */
64
65 assert_se(close_nointr(fd) != -EBADF);
66 }
67
68 return -1;
69 }
70
71 void safe_close_pair(int p[]) {
72 assert(p);
73
74 if (p[0] == p[1]) {
75 /* Special case pairs which use the same fd in both
76 * directions... */
77 p[0] = p[1] = safe_close(p[0]);
78 return;
79 }
80
81 p[0] = safe_close(p[0]);
82 p[1] = safe_close(p[1]);
83 }
84
85 void close_many(const int fds[], unsigned n_fd) {
86 unsigned i;
87
88 assert(fds || n_fd <= 0);
89
90 for (i = 0; i < n_fd; i++)
91 safe_close(fds[i]);
92 }
93
94 int fclose_nointr(FILE *f) {
95 assert(f);
96
97 /* Same as close_nointr(), but for fclose() */
98
99 if (fclose(f) == 0)
100 return 0;
101
102 if (errno == EINTR)
103 return 0;
104
105 return -errno;
106 }
107
108 FILE* safe_fclose(FILE *f) {
109
110 /* Same as safe_close(), but for fclose() */
111
112 if (f) {
113 PROTECT_ERRNO;
114
115 assert_se(fclose_nointr(f) != EBADF);
116 }
117
118 return NULL;
119 }
120
121 DIR* safe_closedir(DIR *d) {
122
123 if (d) {
124 PROTECT_ERRNO;
125
126 assert_se(closedir(d) >= 0 || errno != EBADF);
127 }
128
129 return NULL;
130 }
131
132 int fd_nonblock(int fd, bool nonblock) {
133 int flags, nflags;
134
135 assert(fd >= 0);
136
137 flags = fcntl(fd, F_GETFL, 0);
138 if (flags < 0)
139 return -errno;
140
141 if (nonblock)
142 nflags = flags | O_NONBLOCK;
143 else
144 nflags = flags & ~O_NONBLOCK;
145
146 if (nflags == flags)
147 return 0;
148
149 if (fcntl(fd, F_SETFL, nflags) < 0)
150 return -errno;
151
152 return 0;
153 }
154
155 int fd_cloexec(int fd, bool cloexec) {
156 int flags, nflags;
157
158 assert(fd >= 0);
159
160 flags = fcntl(fd, F_GETFD, 0);
161 if (flags < 0)
162 return -errno;
163
164 if (cloexec)
165 nflags = flags | FD_CLOEXEC;
166 else
167 nflags = flags & ~FD_CLOEXEC;
168
169 if (nflags == flags)
170 return 0;
171
172 if (fcntl(fd, F_SETFD, nflags) < 0)
173 return -errno;
174
175 return 0;
176 }
177
178 _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
179 unsigned i;
180
181 assert(n_fdset == 0 || fdset);
182
183 for (i = 0; i < n_fdset; i++)
184 if (fdset[i] == fd)
185 return true;
186
187 return false;
188 }
189
190 int close_all_fds(const int except[], unsigned n_except) {
191 _cleanup_closedir_ DIR *d = NULL;
192 struct dirent *de;
193 int r = 0;
194
195 assert(n_except == 0 || except);
196
197 d = opendir("/proc/self/fd");
198 if (!d) {
199 int fd;
200 struct rlimit rl;
201
202 /* When /proc isn't available (for example in chroots)
203 * the fallback is brute forcing through the fd
204 * table */
205
206 assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
207 for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
208
209 if (fd_in_set(fd, except, n_except))
210 continue;
211
212 if (close_nointr(fd) < 0)
213 if (errno != EBADF && r == 0)
214 r = -errno;
215 }
216
217 return r;
218 }
219
220 while ((de = readdir(d))) {
221 int fd = -1;
222
223 if (hidden_file(de->d_name))
224 continue;
225
226 if (safe_atoi(de->d_name, &fd) < 0)
227 /* Let's better ignore this, just in case */
228 continue;
229
230 if (fd < 3)
231 continue;
232
233 if (fd == dirfd(d))
234 continue;
235
236 if (fd_in_set(fd, except, n_except))
237 continue;
238
239 if (close_nointr(fd) < 0) {
240 /* Valgrind has its own FD and doesn't want to have it closed */
241 if (errno != EBADF && r == 0)
242 r = -errno;
243 }
244 }
245
246 return r;
247 }
248
249 int same_fd(int a, int b) {
250 struct stat sta, stb;
251 pid_t pid;
252 int r, fa, fb;
253
254 assert(a >= 0);
255 assert(b >= 0);
256
257 /* Compares two file descriptors. Note that semantics are
258 * quite different depending on whether we have kcmp() or we
259 * don't. If we have kcmp() this will only return true for
260 * dup()ed file descriptors, but not otherwise. If we don't
261 * have kcmp() this will also return true for two fds of the same
262 * file, created by separate open() calls. Since we use this
263 * call mostly for filtering out duplicates in the fd store
264 * this difference hopefully doesn't matter too much. */
265
266 if (a == b)
267 return true;
268
269 /* Try to use kcmp() if we have it. */
270 pid = getpid();
271 r = kcmp(pid, pid, KCMP_FILE, a, b);
272 if (r == 0)
273 return true;
274 if (r > 0)
275 return false;
276 if (errno != ENOSYS)
277 return -errno;
278
279 /* We don't have kcmp(), use fstat() instead. */
280 if (fstat(a, &sta) < 0)
281 return -errno;
282
283 if (fstat(b, &stb) < 0)
284 return -errno;
285
286 if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
287 return false;
288
289 /* We consider all device fds different, since two device fds
290 * might refer to quite different device contexts even though
291 * they share the same inode and backing dev_t. */
292
293 if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
294 return false;
295
296 if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
297 return false;
298
299 /* The fds refer to the same inode on disk, let's also check
300 * if they have the same fd flags. This is useful to
301 * distinguish the read and write side of a pipe created with
302 * pipe(). */
303 fa = fcntl(a, F_GETFL);
304 if (fa < 0)
305 return -errno;
306
307 fb = fcntl(b, F_GETFL);
308 if (fb < 0)
309 return -errno;
310
311 return fa == fb;
312 }
313
314 void cmsg_close_all(struct msghdr *mh) {
315 struct cmsghdr *cmsg;
316
317 assert(mh);
318
319 CMSG_FOREACH(cmsg, mh)
320 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
321 close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
322 }