GDB (xrefs)
filestuff.c
Go to the documentation of this file.
1 /* Low-level file-handling.
2  Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 
4  This file is part of GDB.
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 
19 #include "common-defs.h"
20 #include "filestuff.h"
21 #include "gdb_vecs.h"
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <algorithm>
27 
28 #ifdef USE_WIN32API
29 #include <winsock2.h>
30 #include <windows.h>
31 #define HAVE_SOCKETS 1
32 #elif defined HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
34 /* Define HAVE_F_GETFD if we plan to use F_GETFD. */
35 #define HAVE_F_GETFD F_GETFD
36 #define HAVE_SOCKETS 1
37 #endif
38 
39 #ifdef HAVE_SYS_RESOURCE_H
40 #include <sys/resource.h>
41 #endif /* HAVE_SYS_RESOURCE_H */
42 
43 #ifndef O_CLOEXEC
44 #define O_CLOEXEC 0
45 #endif
46 
47 #ifndef SOCK_CLOEXEC
48 #define SOCK_CLOEXEC 0
49 #endif
50 
51 
52 
53 #ifndef HAVE_FDWALK
54 
55 #include <dirent.h>
56 
57 /* Replacement for fdwalk, if the system doesn't define it. Walks all
58  open file descriptors (though this implementation may walk closed
59  ones as well, depending on the host platform's capabilities) and
60  call FUNC with ARG. If FUNC returns non-zero, stops immediately
61  and returns the same value. Otherwise, returns zero when
62  finished. */
63 
64 static int
65 fdwalk (int (*func) (void *, int), void *arg)
66 {
67  /* Checking __linux__ isn't great but it isn't clear what would be
68  better. There doesn't seem to be a good way to check for this in
69  configure. */
70 #ifdef __linux__
71  DIR *dir;
72 
73  dir = opendir ("/proc/self/fd");
74  if (dir != NULL)
75  {
76  struct dirent *entry;
77  int result = 0;
78 
79  for (entry = readdir (dir); entry != NULL; entry = readdir (dir))
80  {
81  long fd;
82  char *tail;
83  int result;
84 
85  errno = 0;
86  fd = strtol (entry->d_name, &tail, 10);
87  if (*tail != '\0' || errno != 0)
88  continue;
89  if ((int) fd != fd)
90  {
91  /* What can we do here really? */
92  continue;
93  }
94 
95  if (fd == dirfd (dir))
96  continue;
97 
98  result = func (arg, fd);
99  if (result != 0)
100  break;
101  }
102 
103  closedir (dir);
104  return result;
105  }
106  /* We may fall through to the next case. */
107 #endif
108 
109  {
110  int max, fd;
111 
112 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
113  struct rlimit rlim;
114 
115  if (getrlimit (RLIMIT_NOFILE, &rlim) == 0 && rlim.rlim_max != RLIM_INFINITY)
116  max = rlim.rlim_max;
117  else
118 #endif
119  {
120 #ifdef _SC_OPEN_MAX
121  max = sysconf (_SC_OPEN_MAX);
122 #else
123  /* Whoops. */
124  return 0;
125 #endif /* _SC_OPEN_MAX */
126  }
127 
128  for (fd = 0; fd < max; ++fd)
129  {
130  struct stat sb;
131  int result;
132 
133  /* Only call FUNC for open fds. */
134  if (fstat (fd, &sb) == -1)
135  continue;
136 
137  result = func (arg, fd);
138  if (result != 0)
139  return result;
140  }
141 
142  return 0;
143  }
144 }
145 
146 #endif /* HAVE_FDWALK */
147 
148 
149 
150 /* A vector holding all the fds open when notice_open_fds was called. We
151  don't use a hashtab because we don't expect there to be many open fds. */
152 
153 static std::vector<int> open_fds;
154 
155 /* An fdwalk callback function used by notice_open_fds. It puts the
156  given file descriptor into the vec. */
157 
158 static int
159 do_mark_open_fd (void *ignore, int fd)
160 {
161  open_fds.push_back (fd);
162  return 0;
163 }
164 
165 /* See filestuff.h. */
166 
167 void
169 {
170  fdwalk (do_mark_open_fd, NULL);
171 }
172 
173 /* See filestuff.h. */
174 
175 void
177 {
178  do_mark_open_fd (NULL, fd);
179 }
180 
181 /* See filestuff.h. */
182 
183 void
185 {
186  auto it = std::remove (open_fds.begin (), open_fds.end (), fd);
187 
188  if (it != open_fds.end ())
189  open_fds.erase (it);
190  else
191  gdb_assert_not_reached (_("fd not found in open_fds"));
192 }
193 
194 /* Helper function for close_most_fds that closes the file descriptor
195  if appropriate. */
196 
197 static int
198 do_close (void *ignore, int fd)
199 {
200  for (int val : open_fds)
201  {
202  if (fd == val)
203  {
204  /* Keep this one open. */
205  return 0;
206  }
207  }
208 
209  close (fd);
210  return 0;
211 }
212 
213 /* See filestuff.h. */
214 
215 void
217 {
218  fdwalk (do_close, NULL);
219 }
220 
221 
222 
223 /* This is a tri-state flag. When zero it means we haven't yet tried
224  O_CLOEXEC. When positive it means that O_CLOEXEC works on this
225  host. When negative, it means that O_CLOEXEC doesn't work. We
226  track this state because, while gdb might have been compiled
227  against a libc that supplies O_CLOEXEC, there is no guarantee that
228  the kernel supports it. */
229 
230 static int trust_o_cloexec;
231 
232 /* Mark FD as close-on-exec, ignoring errors. Update
233  TRUST_O_CLOEXEC. */
234 
235 static void
236 mark_cloexec (int fd)
237 {
238 #ifdef HAVE_F_GETFD
239  int old = fcntl (fd, F_GETFD, 0);
240 
241  if (old != -1)
242  {
243  fcntl (fd, F_SETFD, old | FD_CLOEXEC);
244 
245  if (trust_o_cloexec == 0)
246  {
247  if ((old & FD_CLOEXEC) != 0)
248  trust_o_cloexec = 1;
249  else
250  trust_o_cloexec = -1;
251  }
252  }
253 #endif /* HAVE_F_GETFD */
254 }
255 
256 /* Depending on TRUST_O_CLOEXEC, mark FD as close-on-exec. */
257 
258 static void
260 {
261  if (trust_o_cloexec <= 0)
262  mark_cloexec (fd);
263 }
264 
265 #ifdef HAVE_SOCKETS
266 
267 /* Like maybe_mark_cloexec, but for callers that use SOCK_CLOEXEC. */
268 
269 static void
271 {
272  if (SOCK_CLOEXEC == 0 || trust_o_cloexec <= 0)
273  mark_cloexec (fd);
274 }
275 
276 #endif
277 
278 
279 
280 /* See filestuff.h. */
281 
282 int
283 gdb_open_cloexec (const char *filename, int flags, unsigned long mode)
284 {
285  int fd = open (filename, flags | O_CLOEXEC, mode);
286 
287  if (fd >= 0)
288  maybe_mark_cloexec (fd);
289 
290  return fd;
291 }
292 
293 /* See filestuff.h. */
294 
296 gdb_fopen_cloexec (const char *filename, const char *opentype)
297 {
298  FILE *result;
299  /* Probe for "e" support once. But, if we can tell the operating
300  system doesn't know about close on exec mode "e" without probing,
301  skip it. E.g., the Windows runtime issues an "Invalid parameter
302  passed to C runtime function" OutputDebugString warning for
303  unknown modes. Assume that if O_CLOEXEC is zero, then "e" isn't
304  supported. */
305  static int fopen_e_ever_failed_einval = O_CLOEXEC == 0;
306 
307  if (!fopen_e_ever_failed_einval)
308  {
309  char *copy;
310 
311  copy = (char *) alloca (strlen (opentype) + 2);
312  strcpy (copy, opentype);
313  /* This is a glibc extension but we try it unconditionally on
314  this path. */
315  strcat (copy, "e");
316  result = fopen (filename, copy);
317 
318  if (result == NULL && errno == EINVAL)
319  {
320  result = fopen (filename, opentype);
321  if (result != NULL)
322  fopen_e_ever_failed_einval = 1;
323  }
324  }
325  else
326  result = fopen (filename, opentype);
327 
328  if (result != NULL)
329  maybe_mark_cloexec (fileno (result));
330 
331  return gdb_file_up (result);
332 }
333 
334 #ifdef HAVE_SOCKETS
335 /* See filestuff.h. */
336 
337 int
338 gdb_socketpair_cloexec (int domain, int style, int protocol,
339  int filedes[2])
340 {
341 #ifdef HAVE_SOCKETPAIR
342  int result = socketpair (domain, style | SOCK_CLOEXEC, protocol, filedes);
343 
344  if (result != -1)
345  {
346  socket_mark_cloexec (filedes[0]);
347  socket_mark_cloexec (filedes[1]);
348  }
349 
350  return result;
351 #else
352  gdb_assert_not_reached (_("socketpair not available on this host"));
353 #endif
354 }
355 
356 /* See filestuff.h. */
357 
358 int
359 gdb_socket_cloexec (int domain, int style, int protocol)
360 {
361  int result = socket (domain, style | SOCK_CLOEXEC, protocol);
362 
363  if (result != -1)
364  socket_mark_cloexec (result);
365 
366  return result;
367 }
368 #endif
369 
370 /* See filestuff.h. */
371 
372 int
373 gdb_pipe_cloexec (int filedes[2])
374 {
375  int result;
376 
377 #ifdef HAVE_PIPE2
378  result = pipe2 (filedes, O_CLOEXEC);
379  if (result != -1)
380  {
381  maybe_mark_cloexec (filedes[0]);
382  maybe_mark_cloexec (filedes[1]);
383  }
384 #else
385 #ifdef HAVE_PIPE
386  result = pipe (filedes);
387  if (result != -1)
388  {
389  mark_cloexec (filedes[0]);
390  mark_cloexec (filedes[1]);
391  }
392 #else /* HAVE_PIPE */
393  gdb_assert_not_reached (_("pipe not available on this host"));
394 #endif /* HAVE_PIPE */
395 #endif /* HAVE_PIPE2 */
396 
397  return result;
398 }
399 
400 /* Helper function which does the work for make_cleanup_close. */
401 
402 static void
403 do_close_cleanup (void *arg)
404 {
405  int *fd = (int *) arg;
406 
407  close (*fd);
408 }
409 
410 /* See filestuff.h. */
411 
412 struct cleanup *
414 {
415  int *saved_fd = XNEW (int);
416 
417  *saved_fd = fd;
418  return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
419 }
#define O_CLOEXEC
Definition: filestuff.c:44
static void mark_cloexec(int fd)
Definition: filestuff.c:236
static int do_mark_open_fd(void *ignore, int fd)
Definition: filestuff.c:159
void notice_open_fds(void)
Definition: filestuff.c:168
static int fdwalk(int(*func)(void *, int), void *arg)
Definition: filestuff.c:65
void xfree(void *)
void(* func)(char *)
static void socket_mark_cloexec(int fd)
Definition: filestuff.c:270
int gdb_pipe_cloexec(int filedes[2])
Definition: filestuff.c:373
#define _(String)
Definition: gdb_locale.h:35
int gdb_socketpair_cloexec(int domain, int style, int protocol, int filedes[2])
Definition: filestuff.c:338
int gdb_socket_cloexec(int domain, int style, int protocol)
Definition: filestuff.c:359
static void do_close_cleanup(void *arg)
Definition: filestuff.c:403
#define XNEW(T)
Definition: poison.h:109
mach_port_t kern_return_t mach_port_t msgports mach_port_t kern_return_t pid_t pid mach_port_t kern_return_t mach_port_t task mach_port_t kern_return_t int flags
Definition: gnu-nat.c:1891
void unmark_fd_no_cloexec(int fd)
Definition: filestuff.c:184
std::unique_ptr< FILE, gdb_file_deleter > gdb_file_up
Definition: filestuff.h:59
static int do_close(void *ignore, int fd)
Definition: filestuff.c:198
struct cleanup * make_cleanup_dtor(make_cleanup_ftype *function, void *arg, make_cleanup_dtor_ftype *dtor)
Definition: cleanups.c:125
#define gdb_assert_not_reached(message)
Definition: gdb_assert.h:55
struct cleanup * make_cleanup_close(int fd)
Definition: filestuff.c:413
gdb_file_up gdb_fopen_cloexec(const char *filename, const char *opentype)
Definition: filestuff.c:296
void close_most_fds(void)
Definition: filestuff.c:216
static int trust_o_cloexec
Definition: filestuff.c:230
#define SOCK_CLOEXEC
Definition: filestuff.c:48
int gdb_open_cloexec(const char *filename, int flags, unsigned long mode)
Definition: filestuff.c:283
static int ignore(struct target_ops *ops, struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
Definition: corelow.c:879
static std::vector< int > open_fds
Definition: filestuff.c:153
void * arg
Definition: cleanups.c:43
void mark_fd_no_cloexec(int fd)
Definition: filestuff.c:176
static void maybe_mark_cloexec(int fd)
Definition: filestuff.c:259