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