D-Bus  1.13.12
dbus-message-util.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-message-util.c Would be in dbus-message.c, but only used by bus/tests
3  *
4  * Copyright 2009 Red Hat, Inc.
5  * Copyright 2011-2017 Collabora Ltd.
6  * Copyright 2017 Endless Mobile, Inc.
7  *
8  * Licensed under the Academic Free License version 2.1
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 
26 #include <config.h>
27 
28 #include "dbus-internals.h"
29 #include "dbus-test.h"
30 #include "dbus-message-private.h"
31 #include "dbus-marshal-recursive.h"
32 #include "dbus-string.h"
33 #ifdef HAVE_UNIX_FD_PASSING
34 #include "dbus-sysdeps-unix.h"
35 #endif
36 #include <dbus/dbus-test-tap.h>
37 
38 #ifdef __linux__
39 /* Necessary for the Linux-specific fd leak checking code only */
40 #include <sys/types.h>
41 #include <dirent.h>
42 #include <stdlib.h>
43 #include <errno.h>
44 #endif
45 
57 unsigned int
59 {
60 #ifdef HAVE_UNIX_FD_PASSING
61  return message->n_unix_fds;
62 #else
63  return 0;
64 #endif
65 }
66 
67 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
68 
69 #ifdef __linux__
70 struct DBusInitialFDs {
71  fd_set set;
72 };
73 #endif
74 
75 DBusInitialFDs *
76 _dbus_check_fdleaks_enter (void)
77 {
78 #ifdef __linux__
79  DIR *d;
80  DBusInitialFDs *fds;
81 
82  /* this is plain malloc so it won't interfere with leak checking */
83  fds = malloc (sizeof (DBusInitialFDs));
84  _dbus_assert (fds != NULL);
85 
86  /* This works on Linux only */
87 
88  if ((d = opendir ("/proc/self/fd")))
89  {
90  struct dirent *de;
91 
92  while ((de = readdir(d)))
93  {
94  long l;
95  char *e = NULL;
96  int fd;
97 
98  if (de->d_name[0] == '.')
99  continue;
100 
101  errno = 0;
102  l = strtol (de->d_name, &e, 10);
103  _dbus_assert (errno == 0 && e && !*e);
104 
105  fd = (int) l;
106 
107  if (fd < 3)
108  continue;
109 
110  if (fd == dirfd (d))
111  continue;
112 
113  if (fd >= FD_SETSIZE)
114  {
115  _dbus_verbose ("FD %d unexpectedly large; cannot track whether "
116  "it is leaked\n", fd);
117  continue;
118  }
119 
120  FD_SET (fd, &fds->set);
121  }
122 
123  closedir (d);
124  }
125 
126  return fds;
127 #else
128  return NULL;
129 #endif
130 }
131 
132 void
133 _dbus_check_fdleaks_leave (DBusInitialFDs *fds)
134 {
135 #ifdef __linux__
136  DIR *d;
137 
138  /* This works on Linux only */
139 
140  if ((d = opendir ("/proc/self/fd")))
141  {
142  struct dirent *de;
143 
144  while ((de = readdir(d)))
145  {
146  long l;
147  char *e = NULL;
148  int fd;
149 
150  if (de->d_name[0] == '.')
151  continue;
152 
153  errno = 0;
154  l = strtol (de->d_name, &e, 10);
155  _dbus_assert (errno == 0 && e && !*e);
156 
157  fd = (int) l;
158 
159  if (fd < 3)
160  continue;
161 
162  if (fd == dirfd (d))
163  continue;
164 
165  if (fd >= FD_SETSIZE)
166  {
167  _dbus_verbose ("FD %d unexpectedly large; cannot track whether "
168  "it is leaked\n", fd);
169  continue;
170  }
171 
172  if (FD_ISSET (fd, &fds->set))
173  continue;
174 
175  _dbus_test_fatal ("file descriptor %i leaked in %s.", fd, __FILE__);
176  }
177 
178  closedir (d);
179  }
180 
181  free (fds);
182 #else
183  _dbus_assert (fds == NULL);
184 #endif
185 }
186 
187 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
#define NULL
A null pointer, defined appropriately for C or C++.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Internals of DBusMessage.
unsigned int _dbus_message_get_n_unix_fds(DBusMessage *message)
Gets the number of unix fds attached to this message.