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