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 */ |
9 | static void |
10 | check_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 | |
26 | static void |
27 | create_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 | |
41 | static void |
42 | test_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 | |
161 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS |
162 | g_assert (!g_unix_socket_address_get_is_abstract (G_UNIX_SOCKET_ADDRESS (addr))); |
163 | G_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 | |
233 | int |
234 | main (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 | |