D-Bus  1.13.7
dbus-object-tree.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-object-tree.c DBusObjectTree (internals of DBusConnection)
3  *
4  * Copyright (C) 2003, 2005 Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23 
24 #include <config.h>
25 #include "dbus-object-tree.h"
26 #include "dbus-connection-internal.h"
27 #include "dbus-internals.h"
28 #include "dbus-hash.h"
29 #include "dbus-protocol.h"
30 #include "dbus-string.h"
31 #include <dbus/dbus-test-tap.h>
32 #include <string.h>
33 #include <stdlib.h>
34 
48 
49 static DBusObjectSubtree* _dbus_object_subtree_new (const char *name,
50  const DBusObjectPathVTable *vtable,
51  void *user_data);
52 static DBusObjectSubtree* _dbus_object_subtree_ref (DBusObjectSubtree *subtree);
53 static void _dbus_object_subtree_unref (DBusObjectSubtree *subtree);
54 
59 {
60  int refcount;
64 };
65 
72 {
77  void *user_data;
79  int n_subtrees;
81  unsigned int invoke_as_fallback : 1;
82  char name[1];
83 };
84 
94 {
95  DBusObjectTree *tree;
96 
97  /* the connection passed in here isn't fully constructed,
98  * so don't do anything more than store a pointer to
99  * it
100  */
101 
102  tree = dbus_new0 (DBusObjectTree, 1);
103  if (tree == NULL)
104  goto oom;
105 
106  tree->refcount = 1;
107  tree->connection = connection;
108  tree->root = _dbus_object_subtree_new ("/", NULL, NULL);
109  if (tree->root == NULL)
110  goto oom;
111  tree->root->invoke_as_fallback = TRUE;
112 
113  return tree;
114 
115  oom:
116  if (tree)
117  {
118  dbus_free (tree);
119  }
120 
121  return NULL;
122 }
123 
131 {
132  _dbus_assert (tree->refcount > 0);
133 
134  tree->refcount += 1;
135 
136  return tree;
137 }
138 
143 void
145 {
146  _dbus_assert (tree->refcount > 0);
147 
148  tree->refcount -= 1;
149 
150  if (tree->refcount == 0)
151  {
153 
154  dbus_free (tree);
155  }
156 }
157 
161 #define VERBOSE_FIND 0
162 
163 static DBusObjectSubtree*
164 find_subtree_recurse (DBusObjectSubtree *subtree,
165  const char **path,
166  dbus_bool_t create_if_not_found,
167  int *index_in_parent,
168  dbus_bool_t *exact_match)
169 {
170  int i, j;
171  dbus_bool_t return_deepest_match;
172 
173  return_deepest_match = exact_match != NULL;
174 
175  _dbus_assert (!(return_deepest_match && create_if_not_found));
176 
177  if (path[0] == NULL)
178  {
179 #if VERBOSE_FIND
180  _dbus_verbose (" path exhausted, returning %s\n",
181  subtree->name);
182 #endif
183  if (exact_match != NULL)
184  *exact_match = TRUE;
185  return subtree;
186  }
187 
188 #if VERBOSE_FIND
189  _dbus_verbose (" searching children of %s for %s\n",
190  subtree->name, path[0]);
191 #endif
192 
193  i = 0;
194  j = subtree->n_subtrees;
195  while (i < j)
196  {
197  int k, v;
198 
199  k = (i + j) / 2;
200  v = strcmp (path[0], subtree->subtrees[k]->name);
201 
202 #if VERBOSE_FIND
203  _dbus_verbose (" %s cmp %s = %d\n",
204  path[0], subtree->subtrees[k]->name,
205  v);
206 #endif
207 
208  if (v == 0)
209  {
210  if (index_in_parent)
211  {
212 #if VERBOSE_FIND
213  _dbus_verbose (" storing parent index %d\n", k);
214 #endif
215  *index_in_parent = k;
216  }
217 
218  if (return_deepest_match)
219  {
220  DBusObjectSubtree *next;
221 
222  next = find_subtree_recurse (subtree->subtrees[k],
223  &path[1], create_if_not_found,
224  index_in_parent, exact_match);
225  if (next == NULL &&
226  subtree->invoke_as_fallback)
227  {
228 #if VERBOSE_FIND
229  _dbus_verbose (" no deeper match found, returning %s\n",
230  subtree->name);
231 #endif
232  if (exact_match != NULL)
233  *exact_match = FALSE;
234  return subtree;
235  }
236  else
237  return next;
238  }
239  else
240  return find_subtree_recurse (subtree->subtrees[k],
241  &path[1], create_if_not_found,
242  index_in_parent, exact_match);
243  }
244  else if (v < 0)
245  {
246  j = k;
247  }
248  else
249  {
250  i = k + 1;
251  }
252  }
253 
254 #if VERBOSE_FIND
255  _dbus_verbose (" no match found, current tree %s, create_if_not_found = %d\n",
256  subtree->name, create_if_not_found);
257 #endif
258 
259  if (create_if_not_found)
260  {
261  DBusObjectSubtree* child;
262  int child_pos, new_n_subtrees;
263 
264 #if VERBOSE_FIND
265  _dbus_verbose (" creating subtree %s\n",
266  path[0]);
267 #endif
268 
269  child = _dbus_object_subtree_new (path[0],
270  NULL, NULL);
271  if (child == NULL)
272  return NULL;
273 
274  new_n_subtrees = subtree->n_subtrees + 1;
275  if (new_n_subtrees > subtree->max_subtrees)
276  {
277  int new_max_subtrees;
278  DBusObjectSubtree **new_subtrees;
279 
280  new_max_subtrees = subtree->max_subtrees == 0 ? 1 : 2 * subtree->max_subtrees;
281  new_subtrees = dbus_realloc (subtree->subtrees,
282  new_max_subtrees * sizeof (DBusObjectSubtree*));
283  if (new_subtrees == NULL)
284  {
285  _dbus_object_subtree_unref (child);
286  return NULL;
287  }
288  subtree->subtrees = new_subtrees;
289  subtree->max_subtrees = new_max_subtrees;
290  }
291 
292  /* The binary search failed, so i == j points to the
293  place the child should be inserted. */
294  child_pos = i;
295  _dbus_assert (child_pos < new_n_subtrees &&
296  new_n_subtrees <= subtree->max_subtrees);
297  if (child_pos + 1 < new_n_subtrees)
298  {
299  memmove (&subtree->subtrees[child_pos+1],
300  &subtree->subtrees[child_pos],
301  (new_n_subtrees - child_pos - 1) *
302  sizeof subtree->subtrees[0]);
303  }
304  subtree->subtrees[child_pos] = child;
305 
306  if (index_in_parent)
307  *index_in_parent = child_pos;
308  subtree->n_subtrees = new_n_subtrees;
309  child->parent = subtree;
310 
311  return find_subtree_recurse (child,
312  &path[1], create_if_not_found,
313  index_in_parent, exact_match);
314  }
315  else
316  {
317  if (exact_match != NULL)
318  *exact_match = FALSE;
319  return (return_deepest_match && subtree->invoke_as_fallback) ? subtree : NULL;
320  }
321 }
322 
323 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
324 static DBusObjectSubtree*
325 find_subtree (DBusObjectTree *tree,
326  const char **path,
327  int *index_in_parent)
328 {
329  DBusObjectSubtree *subtree;
330 
331 #if VERBOSE_FIND
332  _dbus_verbose ("Looking for exact registered subtree\n");
333 #endif
334 
335  subtree = find_subtree_recurse (tree->root, path, FALSE, index_in_parent, NULL);
336 
337  if (subtree && subtree->message_function == NULL)
338  return NULL;
339  else
340  return subtree;
341 }
342 #endif
343 
344 static DBusObjectSubtree*
345 lookup_subtree (DBusObjectTree *tree,
346  const char **path)
347 {
348 #if VERBOSE_FIND
349  _dbus_verbose ("Looking for subtree\n");
350 #endif
351  return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL);
352 }
353 
354 static DBusObjectSubtree*
355 find_handler (DBusObjectTree *tree,
356  const char **path,
357  dbus_bool_t *exact_match)
358 {
359 #if VERBOSE_FIND
360  _dbus_verbose ("Looking for deepest handler\n");
361 #endif
362  _dbus_assert (exact_match != NULL);
363 
364  *exact_match = FALSE; /* ensure always initialized */
365 
366  return find_subtree_recurse (tree->root, path, FALSE, NULL, exact_match);
367 }
368 
369 static DBusObjectSubtree*
370 ensure_subtree (DBusObjectTree *tree,
371  const char **path)
372 {
373 #if VERBOSE_FIND
374  _dbus_verbose ("Ensuring subtree\n");
375 #endif
376  return find_subtree_recurse (tree->root, path, TRUE, NULL, NULL);
377 }
378 
379 static char *flatten_path (const char **path);
380 
395  dbus_bool_t fallback,
396  const char **path,
397  const DBusObjectPathVTable *vtable,
398  void *user_data,
399  DBusError *error)
400 {
401  DBusObjectSubtree *subtree;
402 
403  _dbus_assert (tree != NULL);
404  _dbus_assert (vtable->message_function != NULL);
405  _dbus_assert (path != NULL);
406 
407  subtree = ensure_subtree (tree, path);
408  if (subtree == NULL)
409  {
410  _DBUS_SET_OOM (error);
411  return FALSE;
412  }
413 
414  if (subtree->message_function != NULL)
415  {
416  if (error != NULL)
417  {
418  char *complete_path = flatten_path (path);
419 
421  "A handler is already registered for %s",
422  complete_path ? complete_path
423  : "(cannot represent path: out of memory!)");
424 
425  dbus_free (complete_path);
426  }
427 
428  return FALSE;
429  }
430 
431  subtree->message_function = vtable->message_function;
432  subtree->unregister_function = vtable->unregister_function;
433  subtree->user_data = user_data;
434  subtree->invoke_as_fallback = fallback != FALSE;
435 
436  return TRUE;
437 }
438 
450 static dbus_bool_t
451 unregister_subtree (DBusObjectSubtree *subtree,
452  DBusObjectPathUnregisterFunction *unregister_function_out,
453  void **user_data_out)
454 {
455  _dbus_assert (subtree != NULL);
456  _dbus_assert (unregister_function_out != NULL);
457  _dbus_assert (user_data_out != NULL);
458 
459  /* Confirm subtree is registered */
460  if (subtree->message_function != NULL)
461  {
462  subtree->message_function = NULL;
463 
464  *unregister_function_out = subtree->unregister_function;
465  *user_data_out = subtree->user_data;
466 
467  subtree->unregister_function = NULL;
468  subtree->user_data = NULL;
469 
470  return TRUE;
471  }
472  else
473  {
474  /* Assert that this unregistered subtree is either the root node or has
475  children, otherwise we have a dangling path which should never
476  happen */
477  _dbus_assert (subtree->parent == NULL || subtree->n_subtrees > 0);
478 
479  /* The subtree is not registered */
480  return FALSE;
481  }
482 }
483 
495 static dbus_bool_t
496 attempt_child_removal (DBusObjectSubtree *parent,
497  int child_index)
498 {
499  /* Candidate for removal */
500  DBusObjectSubtree* candidate;
501 
502  _dbus_assert (parent != NULL);
503  _dbus_assert (child_index >= 0 && child_index < parent->n_subtrees);
504 
505  candidate = parent->subtrees[child_index];
506  _dbus_assert (candidate != NULL);
507 
508  if (candidate->n_subtrees == 0 && candidate->message_function == NULL)
509  {
510  /* The candidate node is childless and is not a registered
511  path, so... */
512 
513  /* ... remove it from its parent... */
514  /* Assumes a 0-byte memmove is OK */
515  memmove (&parent->subtrees[child_index],
516  &parent->subtrees[child_index + 1],
517  (parent->n_subtrees - child_index - 1)
518  * sizeof (parent->subtrees[0]));
519  parent->n_subtrees -= 1;
520 
521  /* ... and free it */
522  candidate->parent = NULL;
523  _dbus_object_subtree_unref (candidate);
524 
525  return TRUE;
526  }
527  return FALSE;
528 }
529 
567 static dbus_bool_t
568 unregister_and_free_path_recurse
569 (DBusObjectSubtree *subtree,
570  const char **path,
571  dbus_bool_t *continue_removal_attempts,
572  DBusObjectPathUnregisterFunction *unregister_function_out,
573  void **user_data_out)
574 {
575  int i, j;
576 
577  _dbus_assert (continue_removal_attempts != NULL);
578  _dbus_assert (*continue_removal_attempts);
579  _dbus_assert (unregister_function_out != NULL);
580  _dbus_assert (user_data_out != NULL);
581 
582  if (path[0] == NULL)
583  return unregister_subtree (subtree, unregister_function_out, user_data_out);
584 
585  i = 0;
586  j = subtree->n_subtrees;
587  while (i < j)
588  {
589  int k, v;
590 
591  k = (i + j) / 2;
592  v = strcmp (path[0], subtree->subtrees[k]->name);
593 
594  if (v == 0)
595  {
596  dbus_bool_t freed;
597  freed = unregister_and_free_path_recurse (subtree->subtrees[k],
598  &path[1],
599  continue_removal_attempts,
600  unregister_function_out,
601  user_data_out);
602  if (freed && *continue_removal_attempts)
603  *continue_removal_attempts = attempt_child_removal (subtree, k);
604  return freed;
605  }
606  else if (v < 0)
607  {
608  j = k;
609  }
610  else
611  {
612  i = k + 1;
613  }
614  }
615  return FALSE;
616 }
617 
625 void
627  const char **path)
628 {
629  dbus_bool_t found_subtree;
630  dbus_bool_t continue_removal_attempts;
631  DBusObjectPathUnregisterFunction unregister_function;
632  void *user_data;
634 
635  _dbus_assert (tree != NULL);
636  _dbus_assert (path != NULL);
637 
638  continue_removal_attempts = TRUE;
639  unregister_function = NULL;
640  user_data = NULL;
641 
642  found_subtree = unregister_and_free_path_recurse (tree->root,
643  path,
644  &continue_removal_attempts,
645  &unregister_function,
646  &user_data);
647 
648 #ifndef DBUS_DISABLE_CHECKS
649  if (found_subtree == FALSE)
650  {
651  _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered",
652  path[0] ? path[0] : "null",
653  (path[0] && path[1]) ? path[1] : "null");
654  goto unlock;
655  }
656 #else
657  _dbus_assert (found_subtree == TRUE);
658 #endif
659 
660 unlock:
661  connection = tree->connection;
662 
663  /* Unlock and call application code */
664 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
665  if (connection)
666 #endif
667  {
668  _dbus_connection_ref_unlocked (connection);
669  _dbus_verbose ("unlock\n");
670  _dbus_connection_unlock (connection);
671  }
672 
673  if (unregister_function)
674  (* unregister_function) (connection, user_data);
675 
676 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
677  if (connection)
678 #endif
679  dbus_connection_unref (connection);
680 }
681 
682 static void
683 free_subtree_recurse (DBusConnection *connection,
684  DBusObjectSubtree *subtree)
685 {
686  /* Delete them from the end, for slightly
687  * more robustness against odd reentrancy.
688  */
689  while (subtree->n_subtrees > 0)
690  {
691  DBusObjectSubtree *child;
692 
693  child = subtree->subtrees[subtree->n_subtrees - 1];
694  subtree->subtrees[subtree->n_subtrees - 1] = NULL;
695  subtree->n_subtrees -= 1;
696  child->parent = NULL;
697 
698  free_subtree_recurse (connection, child);
699  }
700 
701  /* Call application code */
702  if (subtree->unregister_function)
703  (* subtree->unregister_function) (connection,
704  subtree->user_data);
705 
706  subtree->message_function = NULL;
707  subtree->unregister_function = NULL;
708  subtree->user_data = NULL;
709 
710  /* Now free ourselves */
711  _dbus_object_subtree_unref (subtree);
712 }
713 
720 void
722 {
723  if (tree->root)
724  free_subtree_recurse (tree->connection,
725  tree->root);
726  tree->root = NULL;
727 }
728 
729 static dbus_bool_t
730 _dbus_object_tree_list_registered_unlocked (DBusObjectTree *tree,
731  const char **parent_path,
732  char ***child_entries)
733 {
734  DBusObjectSubtree *subtree;
735  char **retval;
736 
737  _dbus_assert (parent_path != NULL);
738  _dbus_assert (child_entries != NULL);
739 
740  *child_entries = NULL;
741 
742  subtree = lookup_subtree (tree, parent_path);
743  if (subtree == NULL)
744  {
745  retval = dbus_new0 (char *, 1);
746  }
747  else
748  {
749  int i;
750  retval = dbus_new0 (char*, subtree->n_subtrees + 1);
751  if (retval == NULL)
752  goto out;
753  i = 0;
754  while (i < subtree->n_subtrees)
755  {
756  retval[i] = _dbus_strdup (subtree->subtrees[i]->name);
757  if (retval[i] == NULL)
758  {
759  dbus_free_string_array (retval);
760  retval = NULL;
761  goto out;
762  }
763  ++i;
764  }
765  }
766 
767  out:
768 
769  *child_entries = retval;
770  return retval != NULL;
771 }
772 
773 static DBusHandlerResult
774 handle_default_introspect_and_unlock (DBusObjectTree *tree,
775  DBusMessage *message,
776  const char **path)
777 {
778  DBusString xml;
779  DBusHandlerResult result;
780  char **children;
781  int i;
782  DBusMessage *reply;
783  DBusMessageIter iter;
784  const char *v_STRING;
785  dbus_bool_t already_unlocked;
786 
787  /* We have the connection lock here */
788 
789  already_unlocked = FALSE;
790 
791  _dbus_verbose (" considering default Introspect() handler...\n");
792 
793  reply = NULL;
794 
795  if (!dbus_message_is_method_call (message,
797  "Introspect"))
798  {
799 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
800  if (tree->connection)
801 #endif
802  {
803  _dbus_verbose ("unlock\n");
805  }
806 
808  }
809 
810  _dbus_verbose (" using default Introspect() handler!\n");
811 
812  if (!_dbus_string_init (&xml))
813  {
814 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
815  if (tree->connection)
816 #endif
817  {
818  _dbus_verbose ("unlock\n");
820  }
821 
823  }
824 
826 
827  children = NULL;
828  if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children))
829  goto out;
830 
832  goto out;
833 
834  if (!_dbus_string_append (&xml, "<node>\n"))
835  goto out;
836 
837  i = 0;
838  while (children[i] != NULL)
839  {
840  if (!_dbus_string_append_printf (&xml, " <node name=\"%s\"/>\n",
841  children[i]))
842  goto out;
843 
844  ++i;
845  }
846 
847  if (!_dbus_string_append (&xml, "</node>\n"))
848  goto out;
849 
850  reply = dbus_message_new_method_return (message);
851  if (reply == NULL)
852  goto out;
853 
854  dbus_message_iter_init_append (reply, &iter);
855  v_STRING = _dbus_string_get_const_data (&xml);
856  if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &v_STRING))
857  goto out;
858 
859 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
860  if (tree->connection)
861 #endif
862  {
863  already_unlocked = TRUE;
864 
865  if (!_dbus_connection_send_and_unlock (tree->connection, reply, NULL))
866  goto out;
867  }
868 
870 
871  out:
872 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
873  if (tree->connection)
874 #endif
875  {
876  if (!already_unlocked)
877  {
878  _dbus_verbose ("unlock\n");
880  }
881  }
882 
883  _dbus_string_free (&xml);
884  dbus_free_string_array (children);
885  if (reply)
886  dbus_message_unref (reply);
887 
888  return result;
889 }
890 
907  DBusMessage *message,
908  dbus_bool_t *found_object)
909 {
910  char **path;
911  dbus_bool_t exact_match;
912  DBusList *list;
913  DBusList *link;
914  DBusHandlerResult result;
915  DBusObjectSubtree *subtree;
916 
917 #if 0
918  _dbus_verbose ("Dispatch of message by object path\n");
919 #endif
920 
921  path = NULL;
922  if (!dbus_message_get_path_decomposed (message, &path))
923  {
924 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
925  if (tree->connection)
926 #endif
927  {
928  _dbus_verbose ("unlock\n");
930  }
931 
932  _dbus_verbose ("No memory to get decomposed path\n");
933 
935  }
936 
937  if (path == NULL)
938  {
939 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
940  if (tree->connection)
941 #endif
942  {
943  _dbus_verbose ("unlock\n");
945  }
946 
947  _dbus_verbose ("No path field in message\n");
949  }
950 
951  /* Find the deepest path that covers the path in the message */
952  subtree = find_handler (tree, (const char**) path, &exact_match);
953 
954  if (found_object)
955  *found_object = !!subtree;
956 
957  /* Build a list of all paths that cover the path in the message */
958 
959  list = NULL;
960 
961  while (subtree != NULL)
962  {
963  if (subtree->message_function != NULL && (exact_match || subtree->invoke_as_fallback))
964  {
965  _dbus_object_subtree_ref (subtree);
966 
967  /* run deepest paths first */
968  if (!_dbus_list_append (&list, subtree))
969  {
971  _dbus_object_subtree_unref (subtree);
972  goto free_and_return;
973  }
974  }
975 
976  exact_match = FALSE;
977  subtree = subtree->parent;
978  }
979 
980  _dbus_verbose ("%d handlers in the path tree for this message\n",
981  _dbus_list_get_length (&list));
982 
983  /* Invoke each handler in the list */
984 
986 
987  link = _dbus_list_get_first_link (&list);
988  while (link != NULL)
989  {
990  DBusList *next = _dbus_list_get_next_link (&list, link);
991  subtree = link->data;
992 
993  /* message_function is NULL if we're unregistered
994  * due to reentrancy
995  */
996  if (subtree->message_function)
997  {
998  DBusObjectPathMessageFunction message_function;
999  void *user_data;
1000 
1001  message_function = subtree->message_function;
1002  user_data = subtree->user_data;
1003 
1004 #if 0
1005  _dbus_verbose (" (invoking a handler)\n");
1006 #endif
1007 
1008 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1009  if (tree->connection)
1010 #endif
1011  {
1012  _dbus_verbose ("unlock\n");
1014  }
1015 
1016  /* FIXME you could unregister the subtree in another thread
1017  * before we invoke the callback, and I can't figure out a
1018  * good way to solve this.
1019  */
1020 
1021  result = (* message_function) (tree->connection,
1022  message,
1023  user_data);
1024 
1025 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1026  if (tree->connection)
1027 #endif
1029 
1031  goto free_and_return;
1032  }
1033 
1034  link = next;
1035  }
1036 
1037  free_and_return:
1038 
1040  {
1041  /* This hardcoded default handler does a minimal Introspect()
1042  */
1043  result = handle_default_introspect_and_unlock (tree, message,
1044  (const char**) path);
1045  }
1046  else
1047  {
1048 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1049  if (tree->connection)
1050 #endif
1051  {
1052  _dbus_verbose ("unlock\n");
1054  }
1055  }
1056 
1057  while (list != NULL)
1058  {
1059  link = _dbus_list_get_first_link (&list);
1060  _dbus_object_subtree_unref (link->data);
1061  _dbus_list_remove_link (&list, link);
1062  }
1063 
1064  dbus_free_string_array (path);
1065 
1066  return result;
1067 }
1068 
1077 void*
1079  const char **path)
1080 {
1081  dbus_bool_t exact_match;
1082  DBusObjectSubtree *subtree;
1083 
1084  _dbus_assert (tree != NULL);
1085  _dbus_assert (path != NULL);
1086 
1087  /* Find the deepest path that covers the path in the message */
1088  subtree = find_handler (tree, (const char**) path, &exact_match);
1089 
1090  if ((subtree == NULL) || !exact_match)
1091  {
1092  _dbus_verbose ("No object at specified path found\n");
1093  return NULL;
1094  }
1095 
1096  return subtree->user_data;
1097 }
1098 
1105 static DBusObjectSubtree*
1106 allocate_subtree_object (const char *name)
1107 {
1108  int len;
1109  DBusObjectSubtree *subtree;
1110  const size_t front_padding = _DBUS_STRUCT_OFFSET (DBusObjectSubtree, name);
1111 
1112  _dbus_assert (name != NULL);
1113 
1114  len = strlen (name);
1115 
1116  subtree = dbus_malloc0 (MAX (front_padding + (len + 1), sizeof (DBusObjectSubtree)));
1117 
1118  if (subtree == NULL)
1119  return NULL;
1120 
1121  memcpy (subtree->name, name, len + 1);
1122 
1123  return subtree;
1124 }
1125 
1126 static DBusObjectSubtree*
1127 _dbus_object_subtree_new (const char *name,
1128  const DBusObjectPathVTable *vtable,
1129  void *user_data)
1130 {
1131  DBusObjectSubtree *subtree;
1132 
1133  subtree = allocate_subtree_object (name);
1134  if (subtree == NULL)
1135  goto oom;
1136 
1137  _dbus_assert (name != NULL);
1138 
1139  subtree->parent = NULL;
1140 
1141  if (vtable)
1142  {
1143  subtree->message_function = vtable->message_function;
1144  subtree->unregister_function = vtable->unregister_function;
1145  }
1146  else
1147  {
1148  subtree->message_function = NULL;
1149  subtree->unregister_function = NULL;
1150  }
1151 
1152  subtree->user_data = user_data;
1153  _dbus_atomic_inc (&subtree->refcount);
1154  subtree->subtrees = NULL;
1155  subtree->n_subtrees = 0;
1156  subtree->max_subtrees = 0;
1157  subtree->invoke_as_fallback = FALSE;
1158 
1159  return subtree;
1160 
1161  oom:
1162  return NULL;
1163 }
1164 
1165 static DBusObjectSubtree *
1166 _dbus_object_subtree_ref (DBusObjectSubtree *subtree)
1167 {
1168 #ifdef DBUS_DISABLE_ASSERT
1169  _dbus_atomic_inc (&subtree->refcount);
1170 #else
1171  dbus_int32_t old_value;
1172 
1173  old_value = _dbus_atomic_inc (&subtree->refcount);
1174  _dbus_assert (old_value > 0);
1175 #endif
1176 
1177  return subtree;
1178 }
1179 
1180 static void
1181 _dbus_object_subtree_unref (DBusObjectSubtree *subtree)
1182 {
1183  dbus_int32_t old_value;
1184 
1185  old_value = _dbus_atomic_dec (&subtree->refcount);
1186  _dbus_assert (old_value > 0);
1187 
1188  if (old_value == 1)
1189  {
1190  _dbus_assert (subtree->unregister_function == NULL);
1191  _dbus_assert (subtree->message_function == NULL);
1192 
1193  dbus_free (subtree->subtrees);
1194  dbus_free (subtree);
1195  }
1196 }
1197 
1210  const char **parent_path,
1211  char ***child_entries)
1212 {
1213  dbus_bool_t result;
1214 
1215  result = _dbus_object_tree_list_registered_unlocked (tree,
1216  parent_path,
1217  child_entries);
1218 
1219 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1220  if (tree->connection)
1221 #endif
1222  {
1223  _dbus_verbose ("unlock\n");
1225  }
1226 
1227  return result;
1228 }
1229 
1230 
1232 #define VERBOSE_DECOMPOSE 0
1233 
1245 _dbus_decompose_path (const char* data,
1246  int len,
1247  char ***path,
1248  int *path_len)
1249 {
1250  char **retval;
1251  int n_components;
1252  int i, j, comp;
1253 
1254  _dbus_assert (data != NULL);
1255  _dbus_assert (path != NULL);
1256 
1257 #if VERBOSE_DECOMPOSE
1258  _dbus_verbose ("Decomposing path \"%s\"\n",
1259  data);
1260 #endif
1261 
1262  n_components = 0;
1263  if (len > 1) /* if path is not just "/" */
1264  {
1265  i = 0;
1266  while (i < len)
1267  {
1268  _dbus_assert (data[i] != '\0');
1269  if (data[i] == '/')
1270  n_components += 1;
1271  ++i;
1272  }
1273  }
1274 
1275  retval = dbus_new0 (char*, n_components + 1);
1276 
1277  if (retval == NULL)
1278  return FALSE;
1279 
1280  comp = 0;
1281  if (n_components == 0)
1282  i = 1;
1283  else
1284  i = 0;
1285  while (comp < n_components)
1286  {
1287  _dbus_assert (i < len);
1288 
1289  if (data[i] == '/')
1290  ++i;
1291  j = i;
1292 
1293  while (j < len && data[j] != '/')
1294  ++j;
1295 
1296  /* Now [i, j) is the path component */
1297  _dbus_assert (i < j);
1298  _dbus_assert (data[i] != '/');
1299  _dbus_assert (j == len || data[j] == '/');
1300 
1301 #if VERBOSE_DECOMPOSE
1302  _dbus_verbose (" (component in [%d,%d))\n",
1303  i, j);
1304 #endif
1305 
1306  retval[comp] = _dbus_memdup (&data[i], j - i + 1);
1307  if (retval[comp] == NULL)
1308  {
1309  dbus_free_string_array (retval);
1310  return FALSE;
1311  }
1312  retval[comp][j-i] = '\0';
1313 #if VERBOSE_DECOMPOSE
1314  _dbus_verbose (" (component %d = \"%s\")\n",
1315  comp, retval[comp]);
1316 #endif
1317 
1318  ++comp;
1319  i = j;
1320  }
1321  _dbus_assert (i == len);
1322 
1323  *path = retval;
1324  if (path_len)
1325  *path_len = n_components;
1326 
1327  return TRUE;
1328 }
1329 
1332 static char*
1333 flatten_path (const char **path)
1334 {
1335  DBusString str;
1336  char *s;
1337 
1338  if (!_dbus_string_init (&str))
1339  return NULL;
1340 
1341  if (path[0] == NULL)
1342  {
1343  if (!_dbus_string_append_byte (&str, '/'))
1344  goto nomem;
1345  }
1346  else
1347  {
1348  int i;
1349 
1350  i = 0;
1351  while (path[i])
1352  {
1353  if (!_dbus_string_append_byte (&str, '/'))
1354  goto nomem;
1355 
1356  if (!_dbus_string_append (&str, path[i]))
1357  goto nomem;
1358 
1359  ++i;
1360  }
1361  }
1362 
1363  if (!_dbus_string_steal_data (&str, &s))
1364  goto nomem;
1365 
1366  _dbus_string_free (&str);
1367 
1368  return s;
1369 
1370  nomem:
1371  _dbus_string_free (&str);
1372  return NULL;
1373 }
1374 
1375 
1376 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1377 
1378 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1379 
1380 #include "dbus-test.h"
1381 #include <stdio.h>
1382 
1383 typedef enum
1384 {
1385  STR_EQUAL,
1386  STR_PREFIX,
1387  STR_DIFFERENT
1388 } StrComparison;
1389 
1390 /* Returns TRUE if container is a parent of child
1391  */
1392 static StrComparison
1393 path_contains (const char **container,
1394  const char **child)
1395 {
1396  int i;
1397 
1398  i = 0;
1399  while (child[i] != NULL)
1400  {
1401  int v;
1402 
1403  if (container[i] == NULL)
1404  return STR_PREFIX; /* container ran out, child continues;
1405  * thus the container is a parent of the
1406  * child.
1407  */
1408 
1409  _dbus_assert (container[i] != NULL);
1410  _dbus_assert (child[i] != NULL);
1411 
1412  v = strcmp (container[i], child[i]);
1413 
1414  if (v != 0)
1415  return STR_DIFFERENT; /* they overlap until here and then are different,
1416  * not overlapping
1417  */
1418 
1419  ++i;
1420  }
1421 
1422  /* Child ran out; if container also did, they are equal;
1423  * otherwise, the child is a parent of the container.
1424  */
1425  if (container[i] == NULL)
1426  return STR_EQUAL;
1427  else
1428  return STR_DIFFERENT;
1429 }
1430 
1431 #if 0
1432 static void
1433 spew_subtree_recurse (DBusObjectSubtree *subtree,
1434  int indent)
1435 {
1436  int i;
1437 
1438  i = 0;
1439  while (i < indent)
1440  {
1441  _dbus_verbose (" ");
1442  ++i;
1443  }
1444 
1445  _dbus_verbose ("%s (%d children)\n",
1446  subtree->name, subtree->n_subtrees);
1447 
1448  i = 0;
1449  while (i < subtree->n_subtrees)
1450  {
1451  spew_subtree_recurse (subtree->subtrees[i], indent + 2);
1452 
1453  ++i;
1454  }
1455 }
1456 
1457 static void
1458 spew_tree (DBusObjectTree *tree)
1459 {
1460  spew_subtree_recurse (tree->root, 0);
1461 }
1462 #endif
1463 
1467 typedef struct
1468 {
1469  const char **path;
1470  dbus_bool_t handler_fallback;
1471  dbus_bool_t message_handled;
1472  dbus_bool_t handler_unregistered;
1473 } TreeTestData;
1474 
1475 
1476 static void
1477 test_unregister_function (DBusConnection *connection,
1478  void *user_data)
1479 {
1480  TreeTestData *ttd = user_data;
1481 
1482  ttd->handler_unregistered = TRUE;
1483 }
1484 
1485 static DBusHandlerResult
1486 test_message_function (DBusConnection *connection,
1487  DBusMessage *message,
1488  void *user_data)
1489 {
1490  TreeTestData *ttd = user_data;
1491 
1492  ttd->message_handled = TRUE;
1493 
1495 }
1496 
1497 static dbus_bool_t
1498 do_register (DBusObjectTree *tree,
1499  const char **path,
1500  dbus_bool_t fallback,
1501  int i,
1502  TreeTestData *tree_test_data)
1503 {
1504  DBusObjectPathVTable vtable = { test_unregister_function,
1505  test_message_function, NULL };
1506 
1507  tree_test_data[i].message_handled = FALSE;
1508  tree_test_data[i].handler_unregistered = FALSE;
1509  tree_test_data[i].handler_fallback = fallback;
1510  tree_test_data[i].path = path;
1511 
1512  if (!_dbus_object_tree_register (tree, fallback, path,
1513  &vtable,
1514  &tree_test_data[i],
1515  NULL))
1516  return FALSE;
1517 
1519  &tree_test_data[i]);
1520 
1521  return TRUE;
1522 }
1523 
1524 static dbus_bool_t
1525 do_test_dispatch (DBusObjectTree *tree,
1526  const char **path,
1527  int i,
1528  TreeTestData *tree_test_data,
1529  int n_test_data)
1530 {
1531  DBusMessage *message;
1532  int j;
1533  DBusHandlerResult result;
1534  char *flat;
1535 
1536  message = NULL;
1537 
1538  flat = flatten_path (path);
1539  if (flat == NULL)
1540  goto oom;
1541 
1543  flat,
1544  "org.freedesktop.TestInterface",
1545  "Foo");
1546  dbus_free (flat);
1547  if (message == NULL)
1548  goto oom;
1549 
1550  j = 0;
1551  while (j < n_test_data)
1552  {
1553  tree_test_data[j].message_handled = FALSE;
1554  ++j;
1555  }
1556 
1557  result = _dbus_object_tree_dispatch_and_unlock (tree, message, NULL);
1558  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
1559  goto oom;
1560 
1561  _dbus_assert (tree_test_data[i].message_handled);
1562 
1563  j = 0;
1564  while (j < n_test_data)
1565  {
1566  if (tree_test_data[j].message_handled)
1567  {
1568  if (tree_test_data[j].handler_fallback)
1569  _dbus_assert (path_contains (tree_test_data[j].path,
1570  path) != STR_DIFFERENT);
1571  else
1572  _dbus_assert (path_contains (tree_test_data[j].path, path) == STR_EQUAL);
1573  }
1574  else
1575  {
1576  if (tree_test_data[j].handler_fallback)
1577  _dbus_assert (path_contains (tree_test_data[j].path,
1578  path) == STR_DIFFERENT);
1579  else
1580  _dbus_assert (path_contains (tree_test_data[j].path, path) != STR_EQUAL);
1581  }
1582 
1583  ++j;
1584  }
1585 
1586  dbus_message_unref (message);
1587 
1588  return TRUE;
1589 
1590  oom:
1591  if (message)
1592  dbus_message_unref (message);
1593  return FALSE;
1594 }
1595 
1596 typedef struct
1597 {
1598  const char *path;
1599  const char *result[20];
1600 } DecomposePathTest;
1601 
1602 static DecomposePathTest decompose_tests[] = {
1603  { "/foo", { "foo", NULL } },
1604  { "/foo/bar", { "foo", "bar", NULL } },
1605  { "/", { NULL } },
1606  { "/a/b", { "a", "b", NULL } },
1607  { "/a/b/c", { "a", "b", "c", NULL } },
1608  { "/a/b/c/d", { "a", "b", "c", "d", NULL } },
1609  { "/foo/bar/q", { "foo", "bar", "q", NULL } },
1610  { "/foo/bar/this/is/longer", { "foo", "bar", "this", "is", "longer", NULL } }
1611 };
1612 
1613 /* Return TRUE on success, FALSE on OOM, die with an assertion failure
1614  * on failure. */
1615 static dbus_bool_t
1616 run_decompose_tests (void)
1617 {
1618  int i;
1619 
1620  i = 0;
1621  while (i < _DBUS_N_ELEMENTS (decompose_tests))
1622  {
1623  char **result;
1624  int result_len;
1625  int expected_len;
1626 
1627  if (!_dbus_decompose_path (decompose_tests[i].path,
1628  strlen (decompose_tests[i].path),
1629  &result, &result_len))
1630  return FALSE;
1631 
1632  expected_len = _dbus_string_array_length (decompose_tests[i].result);
1633 
1634  if (result_len != (int) _dbus_string_array_length ((const char**)result) ||
1635  expected_len != result_len ||
1636  path_contains (decompose_tests[i].result,
1637  (const char**) result) != STR_EQUAL)
1638  {
1639  int real_len = _dbus_string_array_length ((const char**)result);
1640  _dbus_warn ("Expected decompose of %s to have len %d, returned %d, appears to have %d",
1641  decompose_tests[i].path, expected_len, result_len,
1642  real_len);
1643  _dbus_warn ("Decompose resulted in elements: { ");
1644  i = 0;
1645  while (i < real_len)
1646  {
1647  _dbus_warn ("\"%s\"%s", result[i],
1648  (i + 1) == real_len ? "" : ", ");
1649  ++i;
1650  }
1651  _dbus_warn ("}");
1652  _dbus_test_fatal ("path decompose failed");
1653  }
1654 
1655  dbus_free_string_array (result);
1656 
1657  ++i;
1658  }
1659 
1660  return TRUE;
1661 }
1662 
1663 static DBusObjectSubtree*
1664 find_subtree_registered_or_unregistered (DBusObjectTree *tree,
1665  const char **path)
1666 {
1667 #if VERBOSE_FIND
1668  _dbus_verbose ("Looking for exact subtree, registered or unregistered\n");
1669 #endif
1670 
1671  return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL);
1672 }
1673 
1674 /* Returns TRUE if the right thing happens, but the right thing might
1675  * be OOM. */
1676 static dbus_bool_t
1677 object_tree_test_iteration (void *data,
1678  dbus_bool_t have_memory)
1679 {
1680  const char *path0[] = { NULL };
1681  const char *path1[] = { "foo", NULL };
1682  const char *path2[] = { "foo", "bar", NULL };
1683  const char *path3[] = { "foo", "bar", "baz", NULL };
1684  const char *path4[] = { "foo", "bar", "boo", NULL };
1685  const char *path5[] = { "blah", NULL };
1686  const char *path6[] = { "blah", "boof", NULL };
1687  const char *path7[] = { "blah", "boof", "this", "is", "really", "long", NULL };
1688  const char *path8[] = { "childless", NULL };
1689  const char *path9[] = { "blah", "a", NULL };
1690  const char *path10[] = { "blah", "b", NULL };
1691  const char *path11[] = { "blah", "c", NULL };
1692  const char *path12[] = { "blah", "a", "d", NULL };
1693  const char *path13[] = { "blah", "b", "d", NULL };
1694  const char *path14[] = { "blah", "c", "d", NULL };
1695  DBusObjectPathVTable test_vtable = { NULL, test_message_function, NULL };
1696  DBusObjectTree *tree;
1697  TreeTestData tree_test_data[9];
1698  int i;
1699  dbus_bool_t exact_match;
1700 
1701  if (!run_decompose_tests ())
1702  return TRUE; /* OOM is OK */
1703 
1704  tree = NULL;
1705 
1706  tree = _dbus_object_tree_new (NULL);
1707  if (tree == NULL)
1708  goto out;
1709 
1710  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
1711  goto out;
1712 
1713  _dbus_assert (find_subtree (tree, path0, NULL));
1714  _dbus_assert (!find_subtree (tree, path1, NULL));
1715  _dbus_assert (!find_subtree (tree, path2, NULL));
1716  _dbus_assert (!find_subtree (tree, path3, NULL));
1717  _dbus_assert (!find_subtree (tree, path4, NULL));
1718  _dbus_assert (!find_subtree (tree, path5, NULL));
1719  _dbus_assert (!find_subtree (tree, path6, NULL));
1720  _dbus_assert (!find_subtree (tree, path7, NULL));
1721  _dbus_assert (!find_subtree (tree, path8, NULL));
1722 
1723  _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match);
1724  _dbus_assert (find_handler (tree, path1, &exact_match) == tree->root && !exact_match);
1725  _dbus_assert (find_handler (tree, path2, &exact_match) == tree->root && !exact_match);
1726  _dbus_assert (find_handler (tree, path3, &exact_match) == tree->root && !exact_match);
1727  _dbus_assert (find_handler (tree, path4, &exact_match) == tree->root && !exact_match);
1728  _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match);
1729  _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match);
1730  _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match);
1731  _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
1732 
1733  if (!do_register (tree, path1, TRUE, 1, tree_test_data))
1734  goto out;
1735 
1736  _dbus_assert (find_subtree (tree, path0, NULL));
1737  _dbus_assert (find_subtree (tree, path1, NULL));
1738  _dbus_assert (!find_subtree (tree, path2, NULL));
1739  _dbus_assert (!find_subtree (tree, path3, NULL));
1740  _dbus_assert (!find_subtree (tree, path4, NULL));
1741  _dbus_assert (!find_subtree (tree, path5, NULL));
1742  _dbus_assert (!find_subtree (tree, path6, NULL));
1743  _dbus_assert (!find_subtree (tree, path7, NULL));
1744  _dbus_assert (!find_subtree (tree, path8, NULL));
1745 
1746  _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match);
1747  _dbus_assert (find_handler (tree, path1, &exact_match) && exact_match);
1748  _dbus_assert (find_handler (tree, path2, &exact_match) && !exact_match);
1749  _dbus_assert (find_handler (tree, path3, &exact_match) && !exact_match);
1750  _dbus_assert (find_handler (tree, path4, &exact_match) && !exact_match);
1751  _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match);
1752  _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match);
1753  _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match);
1754  _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
1755 
1756  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
1757  goto out;
1758 
1759  _dbus_assert (find_subtree (tree, path1, NULL));
1760  _dbus_assert (find_subtree (tree, path2, NULL));
1761  _dbus_assert (!find_subtree (tree, path3, NULL));
1762  _dbus_assert (!find_subtree (tree, path4, NULL));
1763  _dbus_assert (!find_subtree (tree, path5, NULL));
1764  _dbus_assert (!find_subtree (tree, path6, NULL));
1765  _dbus_assert (!find_subtree (tree, path7, NULL));
1766  _dbus_assert (!find_subtree (tree, path8, NULL));
1767 
1768  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
1769  goto out;
1770 
1771  _dbus_assert (find_subtree (tree, path0, NULL));
1772  _dbus_assert (find_subtree (tree, path1, NULL));
1773  _dbus_assert (find_subtree (tree, path2, NULL));
1774  _dbus_assert (find_subtree (tree, path3, NULL));
1775  _dbus_assert (!find_subtree (tree, path4, NULL));
1776  _dbus_assert (!find_subtree (tree, path5, NULL));
1777  _dbus_assert (!find_subtree (tree, path6, NULL));
1778  _dbus_assert (!find_subtree (tree, path7, NULL));
1779  _dbus_assert (!find_subtree (tree, path8, NULL));
1780 
1781  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
1782  goto out;
1783 
1784  _dbus_assert (find_subtree (tree, path0, NULL));
1785  _dbus_assert (find_subtree (tree, path1, NULL));
1786  _dbus_assert (find_subtree (tree, path2, NULL));
1787  _dbus_assert (find_subtree (tree, path3, NULL));
1788  _dbus_assert (find_subtree (tree, path4, NULL));
1789  _dbus_assert (!find_subtree (tree, path5, NULL));
1790  _dbus_assert (!find_subtree (tree, path6, NULL));
1791  _dbus_assert (!find_subtree (tree, path7, NULL));
1792  _dbus_assert (!find_subtree (tree, path8, NULL));
1793 
1794  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
1795  goto out;
1796 
1797  _dbus_assert (find_subtree (tree, path0, NULL));
1798  _dbus_assert (find_subtree (tree, path1, NULL));
1799  _dbus_assert (find_subtree (tree, path2, NULL));
1800  _dbus_assert (find_subtree (tree, path3, NULL));
1801  _dbus_assert (find_subtree (tree, path4, NULL));
1802  _dbus_assert (find_subtree (tree, path5, NULL));
1803  _dbus_assert (!find_subtree (tree, path6, NULL));
1804  _dbus_assert (!find_subtree (tree, path7, NULL));
1805  _dbus_assert (!find_subtree (tree, path8, NULL));
1806 
1807  _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root && exact_match);
1808  _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match);
1809  _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match);
1810  _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match);
1811  _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match);
1812  _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match);
1813  _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && !exact_match);
1814  _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && !exact_match);
1815  _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
1816 
1817  if (!do_register (tree, path6, TRUE, 6, tree_test_data))
1818  goto out;
1819 
1820  _dbus_assert (find_subtree (tree, path0, NULL));
1821  _dbus_assert (find_subtree (tree, path1, NULL));
1822  _dbus_assert (find_subtree (tree, path2, NULL));
1823  _dbus_assert (find_subtree (tree, path3, NULL));
1824  _dbus_assert (find_subtree (tree, path4, NULL));
1825  _dbus_assert (find_subtree (tree, path5, NULL));
1826  _dbus_assert (find_subtree (tree, path6, NULL));
1827  _dbus_assert (!find_subtree (tree, path7, NULL));
1828  _dbus_assert (!find_subtree (tree, path8, NULL));
1829 
1830  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
1831  goto out;
1832 
1833  _dbus_assert (find_subtree (tree, path0, NULL));
1834  _dbus_assert (find_subtree (tree, path1, NULL));
1835  _dbus_assert (find_subtree (tree, path2, NULL));
1836  _dbus_assert (find_subtree (tree, path3, NULL));
1837  _dbus_assert (find_subtree (tree, path4, NULL));
1838  _dbus_assert (find_subtree (tree, path5, NULL));
1839  _dbus_assert (find_subtree (tree, path6, NULL));
1840  _dbus_assert (find_subtree (tree, path7, NULL));
1841  _dbus_assert (!find_subtree (tree, path8, NULL));
1842 
1843  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
1844  goto out;
1845 
1846  _dbus_assert (find_subtree (tree, path0, NULL));
1847  _dbus_assert (find_subtree (tree, path1, NULL));
1848  _dbus_assert (find_subtree (tree, path2, NULL));
1849  _dbus_assert (find_subtree (tree, path3, NULL));
1850  _dbus_assert (find_subtree (tree, path4, NULL));
1851  _dbus_assert (find_subtree (tree, path5, NULL));
1852  _dbus_assert (find_subtree (tree, path6, NULL));
1853  _dbus_assert (find_subtree (tree, path7, NULL));
1854  _dbus_assert (find_subtree (tree, path8, NULL));
1855 
1856  _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root && exact_match);
1857  _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match);
1858  _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match);
1859  _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match);
1860  _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match);
1861  _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match);
1862  _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && exact_match);
1863  _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && exact_match);
1864  _dbus_assert (find_handler (tree, path8, &exact_match) != tree->root && exact_match);
1865 
1866  /* test the list_registered function */
1867 
1868  {
1869  const char *root[] = { NULL };
1870  char **child_entries;
1871  int nb;
1872 
1873  _dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries);
1874  if (child_entries != NULL)
1875  {
1876  nb = _dbus_string_array_length ((const char**)child_entries);
1877  _dbus_assert (nb == 1);
1878  dbus_free_string_array (child_entries);
1879  }
1880 
1881  _dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries);
1882  if (child_entries != NULL)
1883  {
1884  nb = _dbus_string_array_length ((const char**)child_entries);
1885  _dbus_assert (nb == 2);
1886  dbus_free_string_array (child_entries);
1887  }
1888 
1889  _dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries);
1890  if (child_entries != NULL)
1891  {
1892  nb = _dbus_string_array_length ((const char**)child_entries);
1893  _dbus_assert (nb == 0);
1894  dbus_free_string_array (child_entries);
1895  }
1896 
1897  _dbus_object_tree_list_registered_unlocked (tree, root, &child_entries);
1898  if (child_entries != NULL)
1899  {
1900  nb = _dbus_string_array_length ((const char**)child_entries);
1901  _dbus_assert (nb == 3);
1902  dbus_free_string_array (child_entries);
1903  }
1904  }
1905 
1906  /* Check that destroying tree calls unregister funcs */
1907  _dbus_object_tree_unref (tree);
1908 
1909  i = 0;
1910  while (i < (int) _DBUS_N_ELEMENTS (tree_test_data))
1911  {
1912  _dbus_assert (tree_test_data[i].handler_unregistered);
1913  _dbus_assert (!tree_test_data[i].message_handled);
1914  ++i;
1915  }
1916 
1917  /* Now start again and try the individual unregister function */
1918  tree = _dbus_object_tree_new (NULL);
1919  if (tree == NULL)
1920  goto out;
1921 
1922  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
1923  goto out;
1924  if (!do_register (tree, path1, TRUE, 1, tree_test_data))
1925  goto out;
1926  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
1927  goto out;
1928  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
1929  goto out;
1930  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
1931  goto out;
1932  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
1933  goto out;
1934  if (!do_register (tree, path6, TRUE, 6, tree_test_data))
1935  goto out;
1936  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
1937  goto out;
1938  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
1939  goto out;
1940 
1943 
1944  _dbus_assert (!find_subtree (tree, path0, NULL));
1945  _dbus_assert (find_subtree (tree, path1, NULL));
1946  _dbus_assert (find_subtree (tree, path2, NULL));
1947  _dbus_assert (find_subtree (tree, path3, NULL));
1948  _dbus_assert (find_subtree (tree, path4, NULL));
1949  _dbus_assert (find_subtree (tree, path5, NULL));
1950  _dbus_assert (find_subtree (tree, path6, NULL));
1951  _dbus_assert (find_subtree (tree, path7, NULL));
1952  _dbus_assert (find_subtree (tree, path8, NULL));
1953 
1956 
1957  _dbus_assert (!find_subtree (tree, path0, NULL));
1958  _dbus_assert (!find_subtree (tree, path1, NULL));
1959  _dbus_assert (find_subtree (tree, path2, NULL));
1960  _dbus_assert (find_subtree (tree, path3, NULL));
1961  _dbus_assert (find_subtree (tree, path4, NULL));
1962  _dbus_assert (find_subtree (tree, path5, NULL));
1963  _dbus_assert (find_subtree (tree, path6, NULL));
1964  _dbus_assert (find_subtree (tree, path7, NULL));
1965  _dbus_assert (find_subtree (tree, path8, NULL));
1966 
1969 
1970  _dbus_assert (!find_subtree (tree, path0, NULL));
1971  _dbus_assert (!find_subtree (tree, path1, NULL));
1972  _dbus_assert (!find_subtree (tree, path2, NULL));
1973  _dbus_assert (find_subtree (tree, path3, NULL));
1974  _dbus_assert (find_subtree (tree, path4, NULL));
1975  _dbus_assert (find_subtree (tree, path5, NULL));
1976  _dbus_assert (find_subtree (tree, path6, NULL));
1977  _dbus_assert (find_subtree (tree, path7, NULL));
1978  _dbus_assert (find_subtree (tree, path8, NULL));
1979 
1982 
1983  _dbus_assert (!find_subtree (tree, path0, NULL));
1984  _dbus_assert (!find_subtree (tree, path1, NULL));
1985  _dbus_assert (!find_subtree (tree, path2, NULL));
1986  _dbus_assert (!find_subtree (tree, path3, NULL));
1987  _dbus_assert (find_subtree (tree, path4, NULL));
1988  _dbus_assert (find_subtree (tree, path5, NULL));
1989  _dbus_assert (find_subtree (tree, path6, NULL));
1990  _dbus_assert (find_subtree (tree, path7, NULL));
1991  _dbus_assert (find_subtree (tree, path8, NULL));
1992 
1995 
1996  _dbus_assert (!find_subtree (tree, path0, NULL));
1997  _dbus_assert (!find_subtree (tree, path1, NULL));
1998  _dbus_assert (!find_subtree (tree, path2, NULL));
1999  _dbus_assert (!find_subtree (tree, path3, NULL));
2000  _dbus_assert (!find_subtree (tree, path4, NULL));
2001  _dbus_assert (find_subtree (tree, path5, NULL));
2002  _dbus_assert (find_subtree (tree, path6, NULL));
2003  _dbus_assert (find_subtree (tree, path7, NULL));
2004  _dbus_assert (find_subtree (tree, path8, NULL));
2005 
2008 
2009  _dbus_assert (!find_subtree (tree, path0, NULL));
2010  _dbus_assert (!find_subtree (tree, path1, NULL));
2011  _dbus_assert (!find_subtree (tree, path2, NULL));
2012  _dbus_assert (!find_subtree (tree, path3, NULL));
2013  _dbus_assert (!find_subtree (tree, path4, NULL));
2014  _dbus_assert (!find_subtree (tree, path5, NULL));
2015  _dbus_assert (find_subtree (tree, path6, NULL));
2016  _dbus_assert (find_subtree (tree, path7, NULL));
2017  _dbus_assert (find_subtree (tree, path8, NULL));
2018 
2021 
2022  _dbus_assert (!find_subtree (tree, path0, NULL));
2023  _dbus_assert (!find_subtree (tree, path1, NULL));
2024  _dbus_assert (!find_subtree (tree, path2, NULL));
2025  _dbus_assert (!find_subtree (tree, path3, NULL));
2026  _dbus_assert (!find_subtree (tree, path4, NULL));
2027  _dbus_assert (!find_subtree (tree, path5, NULL));
2028  _dbus_assert (!find_subtree (tree, path6, NULL));
2029  _dbus_assert (find_subtree (tree, path7, NULL));
2030  _dbus_assert (find_subtree (tree, path8, NULL));
2031 
2034 
2035  _dbus_assert (!find_subtree (tree, path0, NULL));
2036  _dbus_assert (!find_subtree (tree, path1, NULL));
2037  _dbus_assert (!find_subtree (tree, path2, NULL));
2038  _dbus_assert (!find_subtree (tree, path3, NULL));
2039  _dbus_assert (!find_subtree (tree, path4, NULL));
2040  _dbus_assert (!find_subtree (tree, path5, NULL));
2041  _dbus_assert (!find_subtree (tree, path6, NULL));
2042  _dbus_assert (!find_subtree (tree, path7, NULL));
2043  _dbus_assert (find_subtree (tree, path8, NULL));
2044 
2047 
2048  _dbus_assert (!find_subtree (tree, path0, NULL));
2049  _dbus_assert (!find_subtree (tree, path1, NULL));
2050  _dbus_assert (!find_subtree (tree, path2, NULL));
2051  _dbus_assert (!find_subtree (tree, path3, NULL));
2052  _dbus_assert (!find_subtree (tree, path4, NULL));
2053  _dbus_assert (!find_subtree (tree, path5, NULL));
2054  _dbus_assert (!find_subtree (tree, path6, NULL));
2055  _dbus_assert (!find_subtree (tree, path7, NULL));
2056  _dbus_assert (!find_subtree (tree, path8, NULL));
2057 
2058  i = 0;
2059  while (i < (int) _DBUS_N_ELEMENTS (tree_test_data))
2060  {
2061  _dbus_assert (tree_test_data[i].handler_unregistered);
2062  _dbus_assert (!tree_test_data[i].message_handled);
2063  ++i;
2064  }
2065 
2066  /* Test removal of newly-childless unregistered nodes */
2067  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
2068  goto out;
2069 
2071  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
2072  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
2073  _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
2074 
2075  /* Test that unregistered parents cannot be freed out from under their
2076  children */
2077  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
2078  goto out;
2079 
2080  _dbus_assert (!find_subtree (tree, path1, NULL));
2081  _dbus_assert (find_subtree_registered_or_unregistered (tree, path1));
2082  _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
2083 
2084 #if 0
2085  /* This triggers the "Attempted to unregister path ..." warning message */
2087 #endif
2088  _dbus_assert (find_subtree (tree, path2, NULL));
2089  _dbus_assert (!find_subtree (tree, path1, NULL));
2090  _dbus_assert (find_subtree_registered_or_unregistered (tree, path1));
2091  _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
2092 
2094  _dbus_assert (!find_subtree (tree, path2, NULL));
2095  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
2096  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
2097  _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
2098 
2099  /* Test that registered parents cannot be freed out from under their
2100  children, and that if they are unregistered before their children, they
2101  are still freed when their children are unregistered */
2102  if (!do_register (tree, path1, TRUE, 1, tree_test_data))
2103  goto out;
2104  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
2105  goto out;
2106 
2107  _dbus_assert (find_subtree (tree, path1, NULL));
2108  _dbus_assert (find_subtree (tree, path2, NULL));
2109 
2111  _dbus_assert (!find_subtree (tree, path1, NULL));
2112  _dbus_assert (find_subtree (tree, path2, NULL));
2113  _dbus_assert (find_subtree_registered_or_unregistered (tree, path1));
2114  _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
2115 
2117  _dbus_assert (!find_subtree (tree, path1, NULL));
2118  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
2119  _dbus_assert (!find_subtree (tree, path2, NULL));
2120  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
2121  _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
2122 
2123  /* Test with NULL unregister_function and user_data */
2124  if (!_dbus_object_tree_register (tree, TRUE, path2,
2125  &test_vtable,
2126  NULL,
2127  NULL))
2128  goto out;
2129 
2132  _dbus_assert (!find_subtree (tree, path2, NULL));
2133  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
2134  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
2135  _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
2136 
2137  /* Test freeing a long path */
2138  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
2139  goto out;
2140 
2142  _dbus_assert (!find_subtree (tree, path3, NULL));
2143  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3));
2144  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
2145  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
2146  _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
2147 
2148  /* Test freeing multiple children from the same path */
2149  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
2150  goto out;
2151  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
2152  goto out;
2153 
2154  _dbus_assert (find_subtree (tree, path3, NULL));
2155  _dbus_assert (find_subtree (tree, path4, NULL));
2156 
2158  _dbus_assert (!find_subtree (tree, path3, NULL));
2159  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3));
2160  _dbus_assert (find_subtree (tree, path4, NULL));
2161  _dbus_assert (find_subtree_registered_or_unregistered (tree, path4));
2162  _dbus_assert (find_subtree_registered_or_unregistered (tree, path2));
2163  _dbus_assert (find_subtree_registered_or_unregistered (tree, path1));
2164 
2166  _dbus_assert (!find_subtree (tree, path4, NULL));
2167  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path4));
2168  _dbus_assert (!find_subtree (tree, path3, NULL));
2169  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3));
2170  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
2171  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
2172 
2173  /* Test subtree removal */
2174  if (!_dbus_object_tree_register (tree, TRUE, path12,
2175  &test_vtable,
2176  NULL,
2177  NULL))
2178  goto out;
2179 
2180  _dbus_assert (find_subtree (tree, path12, NULL));
2181 
2182  if (!_dbus_object_tree_register (tree, TRUE, path13,
2183  &test_vtable,
2184  NULL,
2185  NULL))
2186  goto out;
2187 
2188  _dbus_assert (find_subtree (tree, path13, NULL));
2189 
2190  if (!_dbus_object_tree_register (tree, TRUE, path14,
2191  &test_vtable,
2192  NULL,
2193  NULL))
2194  goto out;
2195 
2196  _dbus_assert (find_subtree (tree, path14, NULL));
2197 
2199 
2200  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path12));
2201  _dbus_assert (find_subtree (tree, path13, NULL));
2202  _dbus_assert (find_subtree (tree, path14, NULL));
2203  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path9));
2204  _dbus_assert (find_subtree_registered_or_unregistered (tree, path5));
2205 
2206  if (!_dbus_object_tree_register (tree, TRUE, path12,
2207  &test_vtable,
2208  NULL,
2209  NULL))
2210  goto out;
2211 
2212  _dbus_assert (find_subtree (tree, path12, NULL));
2213 
2215 
2216  _dbus_assert (find_subtree (tree, path12, NULL));
2217  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path13));
2218  _dbus_assert (find_subtree (tree, path14, NULL));
2219  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path10));
2220  _dbus_assert (find_subtree_registered_or_unregistered (tree, path5));
2221 
2222  if (!_dbus_object_tree_register (tree, TRUE, path13,
2223  &test_vtable,
2224  NULL,
2225  NULL))
2226  goto out;
2227 
2228  _dbus_assert (find_subtree (tree, path13, NULL));
2229 
2231 
2232  _dbus_assert (find_subtree (tree, path12, NULL));
2233  _dbus_assert (find_subtree (tree, path13, NULL));
2234  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path14));
2235  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path11));
2236  _dbus_assert (find_subtree_registered_or_unregistered (tree, path5));
2237 
2239 
2240  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path12));
2241  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path9));
2242  _dbus_assert (find_subtree_registered_or_unregistered (tree, path5));
2243 
2245 
2246  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path13));
2247  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path10));
2248  _dbus_assert (!find_subtree_registered_or_unregistered (tree, path5));
2249 
2250 #if 0
2251  /* Test attempting to unregister non-existent paths. These trigger
2252  "Attempted to unregister path ..." warning messages */
2258 #endif
2259 
2260  /* Register it all again, and test dispatch */
2261 
2262  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
2263  goto out;
2264  if (!do_register (tree, path1, FALSE, 1, tree_test_data))
2265  goto out;
2266  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
2267  goto out;
2268  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
2269  goto out;
2270  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
2271  goto out;
2272  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
2273  goto out;
2274  if (!do_register (tree, path6, FALSE, 6, tree_test_data))
2275  goto out;
2276  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
2277  goto out;
2278  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
2279  goto out;
2280 
2281 #if 0
2282  spew_tree (tree);
2283 #endif
2284 
2285  if (!do_test_dispatch (tree, path0, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2286  goto out;
2287  if (!do_test_dispatch (tree, path1, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2288  goto out;
2289  if (!do_test_dispatch (tree, path2, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2290  goto out;
2291  if (!do_test_dispatch (tree, path3, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2292  goto out;
2293  if (!do_test_dispatch (tree, path4, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2294  goto out;
2295  if (!do_test_dispatch (tree, path5, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2296  goto out;
2297  if (!do_test_dispatch (tree, path6, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2298  goto out;
2299  if (!do_test_dispatch (tree, path7, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2300  goto out;
2301  if (!do_test_dispatch (tree, path8, 8, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
2302  goto out;
2303 
2304  out:
2305  if (tree)
2306  {
2307  /* test ref */
2308  _dbus_object_tree_ref (tree);
2309  _dbus_object_tree_unref (tree);
2310  _dbus_object_tree_unref (tree);
2311  }
2312 
2313  return TRUE;
2314 }
2315 
2322 _dbus_object_tree_test (void)
2323 {
2324  return _dbus_test_oom_handling ("object tree",
2325  object_tree_test_iteration,
2326  NULL);
2327 }
2328 
2329 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
2330 
2331 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:952
DBusHandlerResult _dbus_object_tree_dispatch_and_unlock(DBusObjectTree *tree, DBusMessage *message, dbus_bool_t *found_object)
Tries to dispatch a message by directing it to handler for the object path listed in the message head...
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:323
int max_subtrees
Number of allocated entries in subtrees.
#define NULL
A null pointer, defined appropriately for C or C++.
dbus_bool_t dbus_message_is_method_call(DBusMessage *message, const char *iface, const char *method)
Checks whether the message is a method call with the given interface and member fields.
#define DBUS_INTERFACE_INTROSPECTABLE
The interface supported by introspectable objects.
Definition: dbus-shared.h:97
void _dbus_object_tree_free_all_unlocked(DBusObjectTree *tree)
Free all the handlers in the tree.
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:703
DBusConnection * connection
Connection this tree belongs to.
DBUS_PRIVATE_EXPORT void _dbus_connection_lock(DBusConnection *connection)
Acquires the connection lock.
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:528
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
DBusObjectPathMessageFunction message_function
Function to handle messages.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
void * data
Data stored at this element.
Definition: dbus-list.h:38
DBusObjectPathUnregisterFunction unregister_function
Function to call on unregister.
#define DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
XML document type declaration of the introspection format version 1.0.
unsigned int invoke_as_fallback
Whether to invoke message_function when child nodes don&#39;t handle the message.
Message has not had any effect - see if other handlers want it.
Definition: dbus-shared.h:69
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
Struct representing a single registered subtree handler, or node that&#39;s a parent of a registered subt...
void _dbus_object_tree_unregister_and_unlock(DBusObjectTree *tree, const char **path)
Unregisters an object subtree that was registered with the same path.
char name[1]
Allocated as large as necessary.
Implementation details of DBusConnection.
DBusObjectSubtree * root
Root of the tree ("/" node)
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
DBusHandlerResult
Results that a message handler can return.
Definition: dbus-shared.h:66
DBusMessageIter struct; contains no public fields.
Definition: dbus-message.h:61
#define _dbus_list_get_next_link(list, link)
Gets the next link in the list, or NULL if there are no more links.
Definition: dbus-list.h:119
Virtual table that must be implemented to handle a portion of the object path hierarchy.
Internals of DBusMessage.
void(* DBusObjectPathUnregisterFunction)(DBusConnection *connection, void *user_data)
Called when a DBusObjectPathVTable is unregistered (or its connection is freed).
int n_subtrees
Number of child nodes.
DBusObjectPathUnregisterFunction unregister_function
Function to unregister this handler.
#define DBUS_ERROR_OBJECT_PATH_IN_USE
There&#39;s already an object with the requested object path.
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
dbus_bool_t _dbus_object_tree_list_registered_and_unlock(DBusObjectTree *tree, const char **parent_path, char ***child_entries)
Lists the registered fallback handlers and object path handlers at the given parent_path.
dbus_bool_t dbus_message_get_path_decomposed(DBusMessage *message, char ***path)
Gets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitt...
Internals of DBusObjectTree.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
DBusObjectTree * _dbus_object_tree_ref(DBusObjectTree *tree)
Increment the reference count.
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:271
dbus_bool_t _dbus_decompose_path(const char *data, int len, char ***path, int *path_len)
Decompose an object path.
void * _dbus_memdup(const void *mem, size_t n_bytes)
Duplicates a block of memory.
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1131
DBusObjectSubtree ** subtrees
Child nodes.
Object representing an exception.
Definition: dbus-errors.h:48
size_t _dbus_string_array_length(const char **array)
Returns the size of a string array.
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
DBusObjectPathMessageFunction message_function
Function to handle messages.
void * user_data
Data for functions.
dbus_bool_t _dbus_connection_send_and_unlock(DBusConnection *connection, DBusMessage *message, dbus_uint32_t *client_serial)
Like dbus_connection_send(), but assumes the connection is already locked on function entry...
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
DBusMessage * dbus_message_new_method_call(const char *destination, const char *path, const char *iface, const char *method)
Constructs a new message to invoke a method on a remote object.
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1174
DBusObjectSubtree * parent
Parent node.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:264
#define TRUE
Expands to "1".
void * _dbus_object_tree_get_user_data_unlocked(DBusObjectTree *tree, const char **path)
Looks up the data passed to _dbus_object_tree_register() for a handler at the given path...
dbus_bool_t _dbus_object_tree_register(DBusObjectTree *tree, dbus_bool_t fallback, const char **path, const DBusObjectPathVTable *vtable, void *user_data, DBusError *error)
Registers a new subtree in the global object tree.
DBusHandlerResult(* DBusObjectPathMessageFunction)(DBusConnection *connection, DBusMessage *message, void *user_data)
Called when a message is sent to a registered object path.
int refcount
Reference count.
DBusObjectTree * _dbus_object_tree_new(DBusConnection *connection)
Creates a new object tree, representing a mapping from paths to handler vtables.
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
A node in a linked list.
Definition: dbus-list.h:34
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:751
DBusAtomic refcount
Reference count.
int _dbus_list_get_length(DBusList **list)
Gets the length of a list.
Definition: dbus-list.c:758
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
DBusList * _dbus_list_get_first_link(DBusList **list)
Gets the first link in the list.
Definition: dbus-list.c:595
#define FALSE
Expands to "0".
void * dbus_malloc0(size_t bytes)
Allocates the given number of bytes, as with standard malloc(), but all bytes are initialized to zero...
Definition: dbus-memory.c:533
dbus_bool_t _dbus_string_steal_data(DBusString *str, char **data_return)
Like _dbus_string_get_data(), but removes the gotten data from the original string.
Definition: dbus-string.c:658
void dbus_connection_unref(DBusConnection *connection)
Decrements the reference count of a DBusConnection, and finalizes it if the count reaches zero...
void _dbus_object_tree_unref(DBusObjectTree *tree)
Decrement the reference count.
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:603
DBUS_PRIVATE_EXPORT DBusConnection * _dbus_connection_ref_unlocked(DBusConnection *connection)
Increments the reference count of a DBusConnection.
Message has had its effect - no need to run more handlers.
Definition: dbus-shared.h:68
char * _dbus_strdup(const char *str)
Duplicates a string.
DBUS_PRIVATE_EXPORT void _dbus_connection_unlock(DBusConnection *connection)
Releases the connection lock.
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0...
Need more memory in order to return DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLE...
Definition: dbus-shared.h:70
DBusMessage * dbus_message_new_method_return(DBusMessage *method_call)
Constructs a message that is a reply to a method call.