(root)/
glib-2.79.0/
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  }