1#include <gio/gio.h>
2#include <gio/gnetworking.h>
3#include <gio/gunixfdmessage.h>
4#include <gio/gunixsocketaddress.h>
5#include <string.h>
6#include <unistd.h>
7
8/* ensures that no FDs are left open at the end */
9static void
10check_fd_list (const gint *fd_list)
11{
12 gint i;
13
14 for (i = 0; i < 40; i++)
15 {
16 int my_fd;
17
18 my_fd = dup (fd: 0);
19 g_assert_cmpint (fd_list[i], ==, my_fd);
20 }
21
22 for (i = 0; i < 40; i++)
23 close (fd: fd_list[i]);
24}
25
26static void
27create_fd_list (gint *fd_list)
28{
29 gint i;
30
31 for (i = 0; i < 40; i++)
32 {
33 fd_list[i] = dup (fd: 0);
34 g_assert_cmpint (fd_list[i], >, 0);
35 }
36
37 for (i = 0; i < 40; i++)
38 close (fd: fd_list[i]);
39}
40
41static void
42test_fds (void)
43{
44 GError *err = NULL;
45 GUnixFDMessage *message;
46 GUnixFDMessage **mv;
47 GUnixFDList *list, *l2;
48 GSocket *sockets[2];
49 GSocketAddress *addr;
50 const gint *peek;
51 char buffer[1024];
52 gint fd_list[40];
53 GOutputVector ov;
54 GInputVector iv;
55 gint *stolen;
56 gint sv[3];
57 gint flags;
58 gint nm;
59 gint s;
60 gchar *path;
61 GByteArray *array;
62 gboolean abstract;
63 GUnixSocketAddressType type;
64
65 create_fd_list (fd_list);
66
67 s = socketpair (PF_UNIX, SOCK_STREAM, protocol: 0, fds: sv);
68 g_assert_cmpint (s, ==, 0);
69 sv[2] = -1;
70
71 list = g_unix_fd_list_new_from_array (fds: sv, n_fds: -1);
72 message = G_UNIX_FD_MESSAGE (g_unix_fd_message_new_with_fd_list (list));
73 g_object_unref (object: list);
74
75 g_assert (g_unix_fd_message_get_fd_list (message) == list);
76 g_object_get (object: message, first_property_name: "fd-list", &l2, NULL);
77 g_assert (l2 == list);
78 g_assert_cmpint (g_unix_fd_list_get_length (list), ==, 2);
79
80 peek = g_unix_fd_list_peek_fds (list, length: &s);
81 g_assert_cmpint (s, ==, 2);
82 stolen = g_unix_fd_message_steal_fds (message, length: &s);
83 g_assert_cmpint (s, ==, 2);
84 g_assert (stolen == peek);
85
86 g_assert_cmpint (stolen[0], ==, sv[0]);
87 g_assert_cmpint (stolen[1], ==, sv[1]);
88 g_assert_cmpint (stolen[2], ==, sv[2]);
89 g_free (mem: stolen);
90
91 g_unix_fd_message_append_fd (message, fd: sv[0], error: &err);
92 g_assert_no_error (err);
93 s = close (fd: sv[0]);
94 g_assert_cmpint (s, ==, 0);
95 g_unix_fd_message_append_fd (message, fd: sv[1], error: &err);
96 g_assert_no_error (err);
97 s = close (fd: sv[1]);
98 g_assert_cmpint (s, ==, 0);
99
100 s = close (fd: g_unix_fd_list_get (list, index_: 0, error: &err));
101 g_assert_no_error (err);
102 g_assert_cmpint (s, ==, 0);
103 s = close (fd: g_unix_fd_list_get (list, index_: 1, error: &err));
104 g_assert_no_error (err);
105 g_assert_cmpint (s, ==, 0);
106 s = close (fd: g_unix_fd_list_get (list, index_: 0, error: &err));
107 g_assert_no_error (err);
108 g_assert_cmpint (s, ==, 0);
109 s = close (fd: g_unix_fd_list_get (list, index_: 1, error: &err));
110 g_assert_no_error (err);
111 g_assert_cmpint (s, ==, 0);
112 s = close (fd: g_unix_fd_list_get (list, index_: 0, error: &err));
113 g_assert_no_error (err);
114 g_assert_cmpint (s, ==, 0);
115 s = close (fd: g_unix_fd_list_get (list, index_: 1, error: &err));
116 g_assert_no_error (err);
117 g_assert_cmpint (s, ==, 0);
118
119 g_object_unref (object: message);
120 g_object_unref (object: list);
121
122 message = G_UNIX_FD_MESSAGE (g_unix_fd_message_new ());
123 list = g_unix_fd_message_get_fd_list (message);
124 s = pipe (pipedes: sv);
125 g_assert_cmpint (s, ==, 0);
126
127 s = g_unix_fd_list_append (list, fd: sv[0], error: &err);
128 g_assert_no_error (err);
129 g_assert_cmpint (s, >=, 0);
130 s = g_unix_fd_list_append (list, fd: sv[1], error: &err);
131 g_assert_no_error (err);
132 g_assert_cmpint (s, >=, 0);
133
134 s = close (fd: sv[0]);
135 g_assert_cmpint (s, ==, 0);
136 s = close (fd: sv[1]);
137 g_assert_cmpint (s, ==, 0);
138 s = close (fd: g_unix_fd_list_get (list, index_: 0, error: &err));
139 g_assert_no_error (err);
140 g_assert_cmpint (s, ==, 0);
141 s = close (fd: g_unix_fd_list_get (list, index_: 1, error: &err));
142 g_assert_no_error (err);
143 g_assert_cmpint (s, ==, 0);
144
145 s = socketpair (PF_UNIX, SOCK_STREAM, protocol: 0, fds: sv);
146 g_assert_cmpint (s, ==, 0);
147
148 sockets[0] = g_socket_new_from_fd (fd: sv[0], error: &err);
149 g_assert_no_error (err);
150 g_assert (G_IS_SOCKET (sockets[0]));
151 sockets[1] = g_socket_new_from_fd (fd: sv[1], error: &err);
152 g_assert_no_error (err);
153 g_assert (G_IS_SOCKET (sockets[1]));
154
155 addr = g_socket_get_local_address (socket: sockets[0], error: &err);
156 g_assert_no_error (err);
157 g_assert (G_IS_UNIX_SOCKET_ADDRESS (addr));
158 g_assert_cmpint (g_unix_socket_address_get_address_type (G_UNIX_SOCKET_ADDRESS (addr)), ==, G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
159 g_assert_cmpint (g_unix_socket_address_get_path_len (G_UNIX_SOCKET_ADDRESS (addr)), ==, 0);
160
161G_GNUC_BEGIN_IGNORE_DEPRECATIONS
162 g_assert (!g_unix_socket_address_get_is_abstract (G_UNIX_SOCKET_ADDRESS (addr)));
163G_GNUC_END_IGNORE_DEPRECATIONS
164
165 g_object_get (object: addr,
166 first_property_name: "path", &path,
167 "path-as-array", &array,
168 "abstract", &abstract,
169 "address-type", &type,
170 NULL);
171 g_assert_cmpstr (path, ==, "");
172 g_assert_cmpint (array->len, ==, 0);
173 g_assert (!abstract);
174 g_assert (type == G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
175 g_free (mem: path);
176 g_byte_array_free (array, TRUE);
177
178 g_object_unref (object: addr);
179
180 buffer[0] = 0xff;
181 ov.buffer = buffer;
182 ov.size = 1;
183 s = g_socket_send_message (socket: sockets[0], NULL, vectors: &ov, num_vectors: 1,
184 messages: (GSocketControlMessage **) &message,
185 num_messages: 1, flags: 0, NULL, error: &err);
186 g_assert_no_error (err);
187 g_assert_cmpint (s, ==, 1);
188 g_object_unref (object: message);
189
190 message = NULL;
191
192 flags = 0;
193 iv.buffer = buffer;
194 iv.size = 1;
195 s = g_socket_receive_message (socket: sockets[1], NULL, vectors: &iv, num_vectors: 1,
196 messages: (GSocketControlMessage ***) &mv,
197 num_messages: &nm, flags: &flags, NULL, error: &err);
198 g_assert_no_error (err);
199 g_assert_cmpint (s, ==, 1);
200 g_object_unref (object: sockets[0]);
201 g_object_unref (object: sockets[1]);
202
203 g_assert_cmpint (nm, ==, 1);
204 message = mv[0];
205 g_free (mem: mv);
206
207 g_assert (G_IS_UNIX_FD_MESSAGE (message));
208 list = g_object_ref (g_unix_fd_message_get_fd_list (message));
209 g_object_unref (object: message);
210
211 peek = g_unix_fd_list_peek_fds (list, length: &s);
212 g_assert_cmpint (s, ==, 2);
213 sv[0] = g_unix_fd_list_get (list, index_: 1, error: &err);
214 g_assert_no_error (err);
215
216 strcpy (dest: buffer, src: "failure to say failure to say 'i love gnome-panel!'.");
217 s = write (fd: sv[0], buf: buffer, n: strlen (s: buffer) + 1);
218 g_assert_cmpint (s, ==, strlen (buffer) + 1);
219
220 close (fd: sv[0]);
221 memset (s: buffer, c: 0xff, n: sizeof buffer);
222
223 s = read (fd: peek[0], buf: buffer, nbytes: sizeof buffer);
224 g_assert_cmpint (s, ==, 53);
225 g_assert_cmpstr (buffer, ==,
226 "failure to say failure to say 'i love gnome-panel!'.");
227
228 g_object_unref (object: list);
229
230 check_fd_list (fd_list);
231}
232
233int
234main (int argc, char **argv)
235{
236 g_test_init (argc: &argc, argv: &argv, NULL);
237
238 g_test_add_func (testpath: "/unix-streams/file-descriptors", test_func: test_fds);
239
240 return g_test_run();
241
242}
243

source code of gtk/subprojects/glib/gio/tests/unix-fd.c