]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/fdset.c
man: clarify why User=/Group= don't work with mount units
[thirdparty/systemd.git] / src / core / 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"
31
32#define MAKE_SET(s) ((Set*) s)
33#define MAKE_FDSET(s) ((FDSet*) s)
34
35/* Make sure we can distuingish fd 0 and NULL */
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) {
40 return MAKE_FDSET(set_new(trivial_hash_func, trivial_compare_func));
41}
42
43void fdset_free(FDSet *s) {
44 void *p;
45
46 while ((p = set_steal_first(MAKE_SET(s)))) {
47 /* Valgrind's fd might have ended up in this set here,
48 * due to fdset_new_fill(). We'll ignore all failures
49 * here, so that the EBADFD that valgrind will return
50 * us on close() doesn't influence us */
51
a7556052
LP
52 /* When reloading duplicates of the private bus
53 * connection fds and suchlike are closed here, which
54 * has no effect at all, since they are only
55 * duplicates. So don't be surprised about these log
56 * messages. */
57
b23de6af 58 log_debug("Closing left-over fd %i", PTR_TO_FD(p));
a16e1123
LP
59 close_nointr(PTR_TO_FD(p));
60 }
61
62 set_free(MAKE_SET(s));
63}
64
65int fdset_put(FDSet *s, int fd) {
66 assert(s);
67 assert(fd >= 0);
68
69 return set_put(MAKE_SET(s), FD_TO_PTR(fd));
70}
71
72int fdset_put_dup(FDSet *s, int fd) {
73 int copy, r;
74
75 assert(s);
76 assert(fd >= 0);
77
78 if ((copy = fcntl(fd, F_DUPFD_CLOEXEC, 3)) < 0)
79 return -errno;
80
81 if ((r = fdset_put(s, copy)) < 0) {
82 close_nointr_nofail(copy);
83 return r;
84 }
85
86 return copy;
87}
88
89bool fdset_contains(FDSet *s, int fd) {
90 assert(s);
91 assert(fd >= 0);
92
93 return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
94}
95
96int fdset_remove(FDSet *s, int fd) {
97 assert(s);
98 assert(fd >= 0);
99
100 return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
101}
102
103int fdset_new_fill(FDSet **_s) {
104 DIR *d;
105 struct dirent *de;
106 int r = 0;
107 FDSet *s;
108
109 assert(_s);
110
111 /* Creates an fdsets and fills in all currently open file
112 * descriptors. */
113
114 if (!(d = opendir("/proc/self/fd")))
115 return -errno;
116
117 if (!(s = fdset_new())) {
118 r = -ENOMEM;
119 goto finish;
120 }
121
122 while ((de = readdir(d))) {
123 int fd = -1;
124
125 if (ignore_file(de->d_name))
126 continue;
127
128 if ((r = safe_atoi(de->d_name, &fd)) < 0)
129 goto finish;
130
131 if (fd < 3)
132 continue;
133
134 if (fd == dirfd(d))
135 continue;
136
137 if ((r = fdset_put(s, fd)) < 0)
138 goto finish;
139 }
140
141 r = 0;
142 *_s = s;
143 s = NULL;
144
145finish:
146 closedir(d);
147
148 /* We won't close the fds here! */
149 if (s)
150 set_free(MAKE_SET(s));
151
152 return r;
a16e1123
LP
153}
154
155int fdset_cloexec(FDSet *fds, bool b) {
156 Iterator i;
157 void *p;
158 int r;
159
160 assert(fds);
161
162 SET_FOREACH(p, MAKE_SET(fds), i)
163 if ((r = fd_cloexec(PTR_TO_FD(p), b)) < 0)
164 return r;
165
166 return 0;
167}