Branch data Line data Source code
1 : : #include <gio/gio.h>
2 : : #include <gio/gnetworking.h>
3 : : #include <gio/gunixfdmessage.h>
4 : : #include <gio/gunixsocketaddress.h>
5 : : #ifdef G_OS_UNIX
6 : : #include <glib-unix.h>
7 : : #include <unistd.h>
8 : : #endif
9 : : #include <glib/gstdio.h>
10 : : #include <fcntl.h>
11 : : #include <string.h>
12 : : #ifdef G_OS_WIN32
13 : : #include <io.h>
14 : : #endif
15 : :
16 : : /* ensures that no FDs are left open at the end */
17 : : static void
18 : 3 : check_fd_list (const gint *fd_list)
19 : : {
20 : : gint i;
21 : :
22 : 123 : for (i = 0; i < 40; i++)
23 : : {
24 : : int my_fd;
25 : :
26 : 120 : my_fd = dup (0);
27 : 120 : g_assert_cmpint (fd_list[i], ==, my_fd);
28 : 40 : }
29 : :
30 : 123 : for (i = 0; i < 40; i++)
31 : 120 : g_close (fd_list[i], NULL);
32 : 3 : }
33 : :
34 : : static void
35 : 3 : create_fd_list (gint *fd_list)
36 : : {
37 : : gint i;
38 : :
39 : 123 : for (i = 0; i < 40; i++)
40 : : {
41 : 120 : fd_list[i] = dup (0);
42 : 120 : g_assert_cmpint (fd_list[i], >, 0);
43 : 40 : }
44 : :
45 : 123 : for (i = 0; i < 40; i++)
46 : 120 : g_close (fd_list[i], NULL);
47 : 3 : }
48 : :
49 : : static void
50 : 2 : test_fd_list (void)
51 : : {
52 : 2 : GError *err = NULL;
53 : : GUnixFDList *list;
54 : : const gint *peek;
55 : : gint *stolen;
56 : : gint fd_list[40];
57 : : gint sv[3];
58 : : gint s;
59 : : gint sv0, sv1;
60 : :
61 : 2 : create_fd_list (fd_list);
62 : 2 : sv[2] = -1;
63 : : #ifdef G_OS_WIN32
64 : 1 : s = _pipe (sv, 4096, _O_NOINHERIT | _O_BINARY);
65 : 1 : g_assert_cmpint (s, ==, 0);
66 : : #else
67 : 1 : g_unix_open_pipe (sv, O_CLOEXEC, &err);
68 : 1 : g_assert_no_error (err);
69 : : #endif
70 : 2 : sv0 = sv[0];
71 : 2 : sv1 = sv[1];
72 : :
73 : 2 : list = g_unix_fd_list_new_from_array (sv, -1);
74 : 2 : peek = g_unix_fd_list_peek_fds (list, &s);
75 : 2 : g_assert_cmpint (s, ==, 2);
76 : 2 : g_assert_cmpint (peek[0], ==, sv0);
77 : 2 : g_assert_cmpint (peek[1], ==, sv1);
78 : :
79 : 2 : s = g_unix_fd_list_get (list, 0, &err);
80 : 2 : g_assert_no_error (err);
81 : 2 : g_close (s, &err);
82 : 2 : g_assert_no_error (err);
83 : 2 : s = g_unix_fd_list_get (list, 1, &err);
84 : 2 : g_assert_no_error (err);
85 : 2 : g_close (s, &err);
86 : 2 : g_assert_no_error (err);
87 : :
88 : 2 : s = g_unix_fd_list_append (list, sv0, &err);
89 : 2 : g_assert_no_error (err);
90 : 2 : g_assert_cmpint (s, >=, 0);
91 : 2 : stolen = g_unix_fd_list_steal_fds (list, &s);
92 : 2 : g_assert_cmpint (s, ==, 3);
93 : 2 : g_assert_cmpint (stolen[0], ==, sv0);
94 : 2 : g_assert_cmpint (stolen[1], ==, sv1);
95 : 2 : g_assert_cmpint (stolen[2], >=, 0);
96 : 2 : g_close (stolen[0], &err);
97 : 2 : g_assert_no_error (err);
98 : 2 : g_close (stolen[1], &err);
99 : 2 : g_assert_no_error (err);
100 : 2 : g_close (stolen[2], &err);
101 : 2 : g_assert_no_error (err);
102 : 2 : g_free (stolen);
103 : :
104 : : #ifdef G_OS_WIN32
105 : 1 : s = _pipe (sv, 4096, _O_NOINHERIT | _O_BINARY);
106 : 1 : g_assert_cmpint (s, ==, 0);
107 : : #else
108 : 1 : g_unix_open_pipe (sv, O_CLOEXEC, &err);
109 : 1 : g_assert_no_error (err);
110 : : #endif
111 : 2 : sv0 = sv[0];
112 : 2 : sv1 = sv[1];
113 : :
114 : 2 : g_assert_cmpuint (g_unix_fd_list_append_take (list, g_steal_fd (&sv[0])), ==, 0);
115 : 2 : g_assert_cmpuint (g_unix_fd_list_append_take (list, g_steal_fd (&sv[1])), ==, 1);
116 : 2 : g_assert_cmpint (g_unix_fd_list_get_length (list), ==, 2);
117 : :
118 : 2 : g_assert_cmpint (g_unix_fd_list_peek (list, 0), ==, sv0);
119 : 2 : g_assert_cmpint (g_unix_fd_list_peek (list, 1), ==, sv1);
120 : :
121 : 2 : g_assert_cmpint (g_unix_fd_list_lookup (list, 0), ==, sv0);
122 : 2 : g_assert_cmpint (g_unix_fd_list_lookup (list, 1), ==, sv1);
123 : 2 : g_assert_cmpint (g_unix_fd_list_lookup (list, 2), ==, -1);
124 : :
125 : 2 : g_object_unref (list);
126 : 2 : check_fd_list (fd_list);
127 : 2 : }
128 : :
129 : : static void
130 : 2 : test_scm (void)
131 : : {
132 : : #ifndef G_OS_WIN32
133 : 1 : GError *err = NULL;
134 : : GUnixFDMessage *message;
135 : : GUnixFDMessage **mv;
136 : : GUnixFDList *list, *l2;
137 : : GSocket *sockets[2];
138 : : GSocketAddress *addr;
139 : : const gint *peek;
140 : : char buffer[1024];
141 : : gint fd_list[40];
142 : : GOutputVector ov;
143 : : GInputVector iv;
144 : : gint *stolen;
145 : : gint sv[3];
146 : : gint flags;
147 : : gint nm;
148 : : gint s, i;
149 : : gchar *path;
150 : : GByteArray *array;
151 : : gboolean abstract;
152 : : GUnixSocketAddressType type;
153 : :
154 : 1 : create_fd_list (fd_list);
155 : :
156 : 1 : s = socketpair (PF_UNIX, SOCK_STREAM, 0, sv);
157 : 1 : g_assert_cmpint (s, ==, 0);
158 : 1 : sv[2] = -1;
159 : :
160 : 1 : list = g_unix_fd_list_new_from_array (sv, -1);
161 : 1 : message = G_UNIX_FD_MESSAGE (g_unix_fd_message_new_with_fd_list (list));
162 : 1 : g_object_unref (list);
163 : :
164 : 1 : g_assert (g_unix_fd_message_get_fd_list (message) == list);
165 : 1 : g_object_get (message, "fd-list", &l2, NULL);
166 : 1 : g_assert (l2 == list);
167 : 1 : g_assert_cmpint (g_unix_fd_list_get_length (list), ==, 2);
168 : :
169 : 1 : peek = g_unix_fd_list_peek_fds (list, &s);
170 : 1 : g_assert_cmpint (s, ==, 2);
171 : 1 : stolen = g_unix_fd_message_steal_fds (message, &s);
172 : 1 : g_assert_cmpint (s, ==, 2);
173 : 1 : g_assert (stolen == peek);
174 : :
175 : 1 : g_assert_cmpint (stolen[0], ==, sv[0]);
176 : 1 : g_assert_cmpint (stolen[1], ==, sv[1]);
177 : 1 : g_assert_cmpint (stolen[2], ==, sv[2]);
178 : 1 : g_free (stolen);
179 : :
180 : 1 : g_unix_fd_message_append_fd (message, sv[0], &err);
181 : 1 : g_assert_no_error (err);
182 : 1 : g_close (sv[0], &err);
183 : 1 : g_assert_no_error (err);
184 : 1 : g_unix_fd_message_append_fd (message, sv[1], &err);
185 : 1 : g_assert_no_error (err);
186 : 1 : g_close (sv[1], &err);
187 : 1 : g_assert_no_error (err);
188 : :
189 : 4 : for (i = 0; i < 3; i++)
190 : : {
191 : 3 : s = g_unix_fd_list_get (list, 0, &err);
192 : 3 : g_assert_no_error (err);
193 : 3 : g_close (s, &err);
194 : 3 : g_assert_no_error (err);
195 : 3 : s = g_unix_fd_list_get (list, 1, &err);
196 : 3 : g_assert_no_error (err);
197 : 3 : g_close (s, &err);
198 : 3 : g_assert_no_error (err);
199 : : }
200 : :
201 : 1 : g_object_unref (message);
202 : 1 : g_object_unref (list);
203 : :
204 : 1 : message = G_UNIX_FD_MESSAGE (g_unix_fd_message_new ());
205 : 1 : list = g_unix_fd_message_get_fd_list (message);
206 : 1 : s = pipe (sv);
207 : 1 : g_assert_cmpint (s, ==, 0);
208 : :
209 : 1 : s = g_unix_fd_list_append (list, sv[0], &err);
210 : 1 : g_assert_no_error (err);
211 : 1 : g_assert_cmpint (s, >=, 0);
212 : 1 : s = g_unix_fd_list_append (list, sv[1], &err);
213 : 1 : g_assert_no_error (err);
214 : 1 : g_assert_cmpint (s, >=, 0);
215 : :
216 : 1 : g_close (sv[0], &err);
217 : 1 : g_assert_no_error (err);
218 : 1 : g_close (sv[1], &err);
219 : 1 : g_assert_no_error (err);
220 : 1 : s = g_unix_fd_list_get (list, 0, &err);
221 : 1 : g_assert_no_error (err);
222 : 1 : g_close (s, &err);
223 : 1 : g_assert_no_error (err);
224 : 1 : s = g_unix_fd_list_get (list, 1, &err);
225 : 1 : g_assert_no_error (err);
226 : 1 : g_close (s, &err);
227 : 1 : g_assert_no_error (err);
228 : :
229 : 1 : s = socketpair (PF_UNIX, SOCK_STREAM, 0, sv);
230 : 1 : g_assert_cmpint (s, ==, 0);
231 : :
232 : 1 : sockets[0] = g_socket_new_from_fd (sv[0], &err);
233 : 1 : g_assert_no_error (err);
234 : 1 : g_assert (G_IS_SOCKET (sockets[0]));
235 : 1 : sockets[1] = g_socket_new_from_fd (sv[1], &err);
236 : 1 : g_assert_no_error (err);
237 : 1 : g_assert (G_IS_SOCKET (sockets[1]));
238 : :
239 : 1 : addr = g_socket_get_local_address (sockets[0], &err);
240 : 1 : g_assert_no_error (err);
241 : 1 : g_assert (G_IS_UNIX_SOCKET_ADDRESS (addr));
242 : 1 : g_assert_cmpint (g_unix_socket_address_get_address_type (G_UNIX_SOCKET_ADDRESS (addr)), ==, G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
243 : 1 : g_assert_cmpint (g_unix_socket_address_get_path_len (G_UNIX_SOCKET_ADDRESS (addr)), ==, 0);
244 : :
245 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
246 : 1 : g_assert (!g_unix_socket_address_get_is_abstract (G_UNIX_SOCKET_ADDRESS (addr)));
247 : : G_GNUC_END_IGNORE_DEPRECATIONS
248 : :
249 : 1 : g_object_get (addr,
250 : : "path", &path,
251 : : "path-as-array", &array,
252 : : "abstract", &abstract,
253 : : "address-type", &type,
254 : : NULL);
255 : 1 : g_assert_cmpstr (path, ==, "");
256 : 1 : g_assert_cmpint (array->len, ==, 0);
257 : 1 : g_assert (!abstract);
258 : 1 : g_assert (type == G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
259 : 1 : g_free (path);
260 : 1 : g_byte_array_free (array, TRUE);
261 : :
262 : 1 : g_object_unref (addr);
263 : :
264 : 1 : buffer[0] = 0xff;
265 : 1 : ov.buffer = buffer;
266 : 1 : ov.size = 1;
267 : 1 : s = g_socket_send_message (sockets[0], NULL, &ov, 1,
268 : : (GSocketControlMessage **) &message,
269 : : 1, 0, NULL, &err);
270 : 1 : g_assert_no_error (err);
271 : 1 : g_assert_cmpint (s, ==, 1);
272 : 1 : g_object_unref (message);
273 : :
274 : 1 : message = NULL;
275 : :
276 : 1 : flags = 0;
277 : 1 : iv.buffer = buffer;
278 : 1 : iv.size = 1;
279 : 1 : s = g_socket_receive_message (sockets[1], NULL, &iv, 1,
280 : : (GSocketControlMessage ***) &mv,
281 : : &nm, &flags, NULL, &err);
282 : 1 : g_assert_no_error (err);
283 : 1 : g_assert_cmpint (s, ==, 1);
284 : 1 : g_object_unref (sockets[0]);
285 : 1 : g_object_unref (sockets[1]);
286 : :
287 : 1 : g_assert_cmpint (nm, ==, 1);
288 : 1 : message = mv[0];
289 : 1 : g_free (mv);
290 : :
291 : 1 : g_assert (G_IS_UNIX_FD_MESSAGE (message));
292 : 1 : list = g_object_ref (g_unix_fd_message_get_fd_list (message));
293 : 1 : g_object_unref (message);
294 : :
295 : 1 : peek = g_unix_fd_list_peek_fds (list, &s);
296 : 1 : g_assert_cmpint (s, ==, 2);
297 : 1 : sv[0] = g_unix_fd_list_get (list, 1, &err);
298 : 1 : g_assert_no_error (err);
299 : :
300 : 1 : strcpy (buffer, "failure to say failure to say 'i love gnome-panel!'.");
301 : 1 : s = write (sv[0], buffer, strlen (buffer) + 1);
302 : 1 : g_assert_cmpint (s, ==, strlen (buffer) + 1);
303 : :
304 : 1 : g_close (sv[0], NULL);
305 : 1 : memset (buffer, 0xff, sizeof buffer);
306 : :
307 : 1 : s = read (peek[0], buffer, sizeof buffer);
308 : 1 : g_assert_cmpint (s, ==, 53);
309 : 1 : g_assert_cmpstr (buffer, ==,
310 : : "failure to say failure to say 'i love gnome-panel!'.");
311 : :
312 : 1 : g_object_unref (list);
313 : :
314 : 1 : check_fd_list (fd_list);
315 : : #else
316 : 1 : g_test_skip ("FD SCM support doesn’t exist on Windows");
317 : : #endif
318 : 2 : }
319 : :
320 : : int
321 : 2 : main (int argc, char **argv)
322 : : {
323 : 2 : g_test_init (&argc, &argv, NULL);
324 : :
325 : 2 : g_test_add_func ("/unix-fd/fd-list", test_fd_list);
326 : 2 : g_test_add_func ("/unix-fd/scm", test_scm);
327 : :
328 : 2 : return g_test_run();
329 : : }
|