2005-01-18 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / bus / services.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* services.c  Service management
3  *
4  * Copyright (C) 2003  Red Hat, Inc.
5  * Copyright (C) 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24 #include <dbus/dbus-hash.h>
25 #include <dbus/dbus-list.h>
26 #include <dbus/dbus-mempool.h>
27
28 #include "driver.h"
29 #include "services.h"
30 #include "connection.h"
31 #include "utils.h"
32 #include "activation.h"
33 #include "policy.h"
34 #include "bus.h"
35 #include "selinux.h"
36
37 struct BusService
38 {
39   int refcount;
40
41   BusRegistry *registry;
42   char *name;
43   DBusList *owners;
44   
45   unsigned int prohibit_replacement : 1;
46 };
47
48 struct BusRegistry
49 {
50   int refcount;
51
52   BusContext *context;
53   
54   DBusHashTable *service_hash;
55   DBusMemPool   *service_pool;
56
57   DBusHashTable *service_sid_table;
58 };
59
60 BusRegistry*
61 bus_registry_new (BusContext *context)
62 {
63   BusRegistry *registry;
64
65   registry = dbus_new0 (BusRegistry, 1);
66   if (registry == NULL)
67     return NULL;
68
69   registry->refcount = 1;
70   registry->context = context;
71   
72   registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
73                                                  NULL, NULL);
74   if (registry->service_hash == NULL)
75     goto failed;
76   
77   registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
78                                                TRUE);
79   if (registry->service_pool == NULL)
80     goto failed;
81
82   registry->service_sid_table = NULL;
83   
84   return registry;
85
86  failed:
87   bus_registry_unref (registry);
88   return NULL;
89 }
90
91 BusRegistry *
92 bus_registry_ref (BusRegistry *registry)
93 {
94   _dbus_assert (registry->refcount > 0);
95   registry->refcount += 1;
96
97   return registry;
98 }
99
100 void
101 bus_registry_unref  (BusRegistry *registry)
102 {
103   _dbus_assert (registry->refcount > 0);
104   registry->refcount -= 1;
105
106   if (registry->refcount == 0)
107     {
108       if (registry->service_hash)
109         _dbus_hash_table_unref (registry->service_hash);
110       if (registry->service_pool)
111         _dbus_mem_pool_free (registry->service_pool);
112       if (registry->service_sid_table)
113         _dbus_hash_table_unref (registry->service_sid_table);
114       
115       dbus_free (registry);
116     }
117 }
118
119 BusService*
120 bus_registry_lookup (BusRegistry      *registry,
121                      const DBusString *service_name)
122 {
123   BusService *service;
124
125   service = _dbus_hash_table_lookup_string (registry->service_hash,
126                                             _dbus_string_get_const_data (service_name));
127
128   return service;
129 }
130
131 BusService*
132 bus_registry_ensure (BusRegistry               *registry,
133                      const DBusString          *service_name,
134                      DBusConnection            *owner_if_created,
135                      BusTransaction            *transaction,
136                      DBusError                 *error)
137 {
138   BusService *service;
139
140   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
141   
142   _dbus_assert (owner_if_created != NULL);
143   _dbus_assert (transaction != NULL);
144
145   service = _dbus_hash_table_lookup_string (registry->service_hash,
146                                             _dbus_string_get_const_data (service_name));
147   if (service != NULL)
148     return service;
149   
150   service = _dbus_mem_pool_alloc (registry->service_pool);
151   if (service == NULL)
152     {
153       BUS_SET_OOM (error);
154       return NULL;
155     }
156
157   service->registry = registry;  
158   service->refcount = 1;
159
160   _dbus_verbose ("copying string %p '%s' to service->name\n",
161                  service_name, _dbus_string_get_const_data (service_name));
162   if (!_dbus_string_copy_data (service_name, &service->name))
163     {
164       _dbus_mem_pool_dealloc (registry->service_pool, service);
165       BUS_SET_OOM (error);
166       return NULL;
167     }
168   _dbus_verbose ("copied string %p '%s' to '%s'\n",
169                  service_name, _dbus_string_get_const_data (service_name),
170                  service->name);
171
172   if (!bus_driver_send_service_owner_changed (service->name, 
173                                               NULL,
174                                               bus_connection_get_name (owner_if_created),
175                                               transaction, error))
176     {
177       bus_service_unref (service);
178       return NULL;
179     }
180
181   if (!bus_activation_service_created (bus_context_get_activation (registry->context),
182                                        service->name, transaction, error))
183     {
184       bus_service_unref (service);
185       return NULL;
186     }
187   
188   if (!bus_service_add_owner (service, owner_if_created,
189                               transaction, error))
190     {
191       bus_service_unref (service);
192       return NULL;
193     }
194   
195   if (!_dbus_hash_table_insert_string (registry->service_hash,
196                                        service->name,
197                                        service))
198     {
199       /* The add_owner gets reverted on transaction cancel */
200       BUS_SET_OOM (error);
201       return NULL;
202     }
203   
204   return service;
205 }
206
207 void
208 bus_registry_foreach (BusRegistry               *registry,
209                       BusServiceForeachFunction  function,
210                       void                      *data)
211 {
212   DBusHashIter iter;
213   
214   _dbus_hash_iter_init (registry->service_hash, &iter);
215   while (_dbus_hash_iter_next (&iter))
216     {
217       BusService *service = _dbus_hash_iter_get_value (&iter);
218
219       (* function) (service, data);
220     }
221 }
222
223 dbus_bool_t
224 bus_registry_list_services (BusRegistry *registry,
225                             char      ***listp,
226                             int         *array_len)
227 {
228   int i, j, len;
229   char **retval;
230   DBusHashIter iter;
231    
232   len = _dbus_hash_table_get_n_entries (registry->service_hash);
233   retval = dbus_new (char *, len + 1);
234
235   if (retval == NULL)
236     return FALSE;
237
238   _dbus_hash_iter_init (registry->service_hash, &iter);
239   i = 0;
240   while (_dbus_hash_iter_next (&iter))
241     {
242       BusService *service = _dbus_hash_iter_get_value (&iter);
243
244       retval[i] = _dbus_strdup (service->name);
245       if (retval[i] == NULL)
246         goto error;
247
248       i++;
249     }
250
251   retval[i] = NULL;
252   
253   if (array_len)
254     *array_len = len;
255   
256   *listp = retval;
257   return TRUE;
258   
259  error:
260   for (j = 0; j < i; j++)
261     dbus_free (retval[i]);
262   dbus_free (retval);
263
264   return FALSE;
265 }
266
267 dbus_bool_t
268 bus_registry_acquire_service (BusRegistry      *registry,
269                               DBusConnection   *connection,
270                               const DBusString *service_name,
271                               dbus_uint32_t     flags,
272                               dbus_uint32_t    *result,
273                               BusTransaction   *transaction,
274                               DBusError        *error)
275 {
276   dbus_bool_t retval;
277   DBusConnection *old_owner;
278   DBusConnection *current_owner;
279   BusClientPolicy *policy;
280   BusService *service;
281   BusActivation  *activation;
282   BusSELinuxID *sid;
283   
284   retval = FALSE;
285
286   if (_dbus_string_get_length (service_name) == 0)
287     {
288       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
289                       "Zero-length service name is not allowed");
290       
291       _dbus_verbose ("Attempt to acquire zero-length service name\n");
292       
293       goto out;
294     }
295   
296   if (_dbus_string_get_byte (service_name, 0) == ':')
297     {
298       /* Not allowed; only base services can start with ':' */
299       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
300                       "Cannot acquire a service starting with ':' such as \"%s\"",
301                       _dbus_string_get_const_data (service_name));
302       
303       _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
304                      _dbus_string_get_const_data (service_name));
305       
306       goto out;
307     }
308
309   policy = bus_connection_get_policy (connection);
310   _dbus_assert (policy != NULL);
311
312   /* Note that if sid is #NULL then the bus's own context gets used
313    * in bus_connection_selinux_allows_acquire_service()
314    */
315   sid = bus_selinux_id_table_lookup (registry->service_sid_table,
316                                      service_name);
317
318   if (!bus_selinux_allows_acquire_service (connection, sid,
319                                            _dbus_string_get_const_data (service_name)))
320     {
321       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
322                       "Connection \"%s\" is not allowed to own the service \"%s\" due "
323                       "to SELinux policy",
324                       bus_connection_is_active (connection) ?
325                       bus_connection_get_name (connection) :
326                       "(inactive)",
327                       _dbus_string_get_const_data (service_name));
328       goto out;
329     }
330       
331   if (!bus_client_policy_check_can_own (policy, connection,
332                                         service_name))
333     {
334       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
335                       "Connection \"%s\" is not allowed to own the service \"%s\" due "
336                       "to security policies in the configuration file",
337                       bus_connection_is_active (connection) ?
338                       bus_connection_get_name (connection) :
339                       "(inactive)",
340                       _dbus_string_get_const_data (service_name));
341       goto out;
342     }
343
344   if (bus_connection_get_n_services_owned (connection) >=
345       bus_context_get_max_services_per_connection (registry->context))
346     {
347       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
348                       "Connection \"%s\" is not allowed to own more services "
349                       "(increase limits in configuration file if required)",
350                       bus_connection_is_active (connection) ?
351                       bus_connection_get_name (connection) :
352                       "(inactive)");
353       goto out;
354     }
355   
356   service = bus_registry_lookup (registry, service_name);
357
358   if (service != NULL)
359     old_owner = bus_service_get_primary_owner (service);
360   else
361     old_owner = NULL;
362       
363   if (service == NULL)
364     {
365       service = bus_registry_ensure (registry,
366                                      service_name, connection, transaction, error);
367       if (service == NULL)
368         goto out;
369     }
370
371   current_owner = bus_service_get_primary_owner (service);
372
373   if (old_owner == NULL)
374     {
375       _dbus_assert (current_owner == connection);
376
377       bus_service_set_prohibit_replacement (service,
378                                             (flags & DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT));      
379                         
380       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;      
381     }
382   else if (old_owner == connection)
383     *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
384   else if (!((flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
385     *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
386   else if (bus_service_get_prohibit_replacement (service))
387     {
388       /* Queue the connection */
389       if (!bus_service_add_owner (service, connection,
390                                   transaction, error))
391         goto out;
392       
393       *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
394     }
395   else
396     {
397       /* Replace the current owner */
398
399       /* We enqueue the new owner and remove the first one because
400        * that will cause NameAcquired and NameLost messages to
401        * be sent.
402        */
403       
404       if (!bus_service_add_owner (service, connection,
405                                   transaction, error))
406         goto out;
407
408       if (!bus_service_remove_owner (service, old_owner,
409                                      transaction, error))
410         goto out;
411       
412       _dbus_assert (connection == bus_service_get_primary_owner (service));
413       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
414     }
415
416   activation = bus_context_get_activation (registry->context);
417   retval = bus_activation_send_pending_auto_activation_messages (activation,
418                                                                  service,
419                                                                  transaction,
420                                                                  error);
421   
422  out:
423   return retval;
424 }
425
426 dbus_bool_t
427 bus_registry_set_service_context_table (BusRegistry   *registry,
428                                         DBusHashTable *table)
429 {
430   DBusHashTable *new_table;
431   DBusHashIter iter;
432   
433   new_table = bus_selinux_id_table_new ();
434   if (!new_table)
435     return FALSE;
436
437   _dbus_hash_iter_init (table, &iter);
438   while (_dbus_hash_iter_next (&iter))
439     {
440       const char *service = _dbus_hash_iter_get_string_key (&iter);
441       const char *context = _dbus_hash_iter_get_value (&iter);
442
443       if (!bus_selinux_id_table_insert (new_table,
444                                         service,
445                                         context))
446         return FALSE;
447     }
448   
449   if (registry->service_sid_table)
450     _dbus_hash_table_unref (registry->service_sid_table);
451   registry->service_sid_table = new_table;
452   return TRUE;
453 }
454
455 static void
456 bus_service_unlink_owner (BusService      *service,
457                           DBusConnection  *owner)
458 {
459   _dbus_list_remove_last (&service->owners, owner);
460   bus_connection_remove_owned_service (owner, service);
461 }
462
463 static void
464 bus_service_unlink (BusService *service)
465 {
466   _dbus_assert (service->owners == NULL);
467
468   /* the service may not be in the hash, if
469    * the failure causing transaction cancel
470    * was in the right place, but that's OK
471    */
472   _dbus_hash_table_remove_string (service->registry->service_hash,
473                                   service->name);
474   
475   bus_service_unref (service);
476 }
477
478 static void
479 bus_service_relink (BusService           *service,
480                     DBusPreallocatedHash *preallocated)
481 {
482   _dbus_assert (service->owners == NULL);
483   _dbus_assert (preallocated != NULL);
484
485   _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
486                                                preallocated,
487                                                service->name,
488                                                service);
489   
490   bus_service_ref (service);
491 }
492
493 /**
494  * Data used to represent an ownership cancellation in
495  * a bus transaction.
496  */
497 typedef struct
498 {
499   DBusConnection *connection; /**< the connection */
500   BusService *service;        /**< service to cancel ownership of */
501 } OwnershipCancelData;
502
503 static void
504 cancel_ownership (void *data)
505 {
506   OwnershipCancelData *d = data;
507
508   /* We don't need to send messages notifying of these
509    * changes, since we're reverting something that was
510    * cancelled (effectively never really happened)
511    */
512   bus_service_unlink_owner (d->service, d->connection);
513   
514   if (d->service->owners == NULL)
515     bus_service_unlink (d->service);
516 }
517
518 static void
519 free_ownership_cancel_data (void *data)
520 {
521   OwnershipCancelData *d = data;
522
523   dbus_connection_unref (d->connection);
524   bus_service_unref (d->service);
525   
526   dbus_free (d);
527 }
528
529 static dbus_bool_t
530 add_cancel_ownership_to_transaction (BusTransaction *transaction,
531                                      BusService     *service,
532                                      DBusConnection *connection)
533 {
534   OwnershipCancelData *d;
535
536   d = dbus_new (OwnershipCancelData, 1);
537   if (d == NULL)
538     return FALSE;
539   
540   d->service = service;
541   d->connection = connection;
542
543   if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
544                                         free_ownership_cancel_data))
545     {
546       dbus_free (d);
547       return FALSE;
548     }
549
550   bus_service_ref (d->service);
551   dbus_connection_ref (d->connection);
552   
553   return TRUE;
554 }
555
556 /* this function is self-cancelling if you cancel the transaction */
557 dbus_bool_t
558 bus_service_add_owner (BusService     *service,
559                        DBusConnection *owner,
560                        BusTransaction *transaction,
561                        DBusError      *error)
562 {
563   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
564   
565  /* Send service acquired message first, OOM will result
566   * in cancelling the transaction
567   */
568   if (service->owners == NULL)
569     {
570       if (!bus_driver_send_service_acquired (owner, service->name, transaction, error))
571         return FALSE;
572     }
573   
574   if (!_dbus_list_append (&service->owners,
575                           owner))
576     {
577       BUS_SET_OOM (error);
578       return FALSE;
579     }
580
581   if (!bus_connection_add_owned_service (owner, service))
582     {
583       _dbus_list_remove_last (&service->owners, owner);
584       BUS_SET_OOM (error);
585       return FALSE;
586     }
587
588   if (!add_cancel_ownership_to_transaction (transaction,
589                                             service,
590                                             owner))
591     {
592       bus_service_unlink_owner (service, owner);
593       BUS_SET_OOM (error);
594       return FALSE;
595     }
596   
597   return TRUE;
598 }
599
600 typedef struct
601 {
602   DBusConnection *connection;
603   BusService     *service;
604   DBusConnection *before_connection; /* restore to position before this connection in owners list */
605   DBusList       *connection_link;
606   DBusList       *service_link;
607   DBusPreallocatedHash *hash_entry;
608 } OwnershipRestoreData;
609
610 static void
611 restore_ownership (void *data)
612 {
613   OwnershipRestoreData *d = data;
614   DBusList *link;
615
616   _dbus_assert (d->service_link != NULL);
617   _dbus_assert (d->connection_link != NULL);
618   
619   if (d->service->owners == NULL)
620     {
621       _dbus_assert (d->hash_entry != NULL);
622       bus_service_relink (d->service, d->hash_entry);
623     }
624   else
625     {
626       _dbus_assert (d->hash_entry == NULL);
627     }
628   
629   /* We don't need to send messages notifying of these
630    * changes, since we're reverting something that was
631    * cancelled (effectively never really happened)
632    */
633   link = _dbus_list_get_first_link (&d->service->owners);
634   while (link != NULL)
635     {
636       if (link->data == d->before_connection)
637         break;
638
639       link = _dbus_list_get_next_link (&d->service->owners, link);
640     }
641   
642   _dbus_list_insert_before_link (&d->service->owners, link, d->connection_link);
643
644   /* Note that removing then restoring this changes the order in which
645    * ServiceDeleted messages are sent on destruction of the
646    * connection.  This should be OK as the only guarantee there is
647    * that the base service is destroyed last, and we never even
648    * tentatively remove the base service.
649    */
650   bus_connection_add_owned_service_link (d->connection, d->service_link);
651   
652   d->hash_entry = NULL;
653   d->service_link = NULL;
654   d->connection_link = NULL;
655 }
656
657 static void
658 free_ownership_restore_data (void *data)
659 {
660   OwnershipRestoreData *d = data;
661
662   if (d->service_link)
663     _dbus_list_free_link (d->service_link);
664   if (d->connection_link)
665     _dbus_list_free_link (d->connection_link);
666   if (d->hash_entry)
667     _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
668                                               d->hash_entry);
669
670   dbus_connection_unref (d->connection);
671   bus_service_unref (d->service);
672   
673   dbus_free (d);
674 }
675
676 static dbus_bool_t
677 add_restore_ownership_to_transaction (BusTransaction *transaction,
678                                       BusService     *service,
679                                       DBusConnection *connection)
680 {
681   OwnershipRestoreData *d;
682   DBusList *link;
683
684   d = dbus_new (OwnershipRestoreData, 1);
685   if (d == NULL)
686     return FALSE;
687   
688   d->service = service;
689   d->connection = connection;
690   d->service_link = _dbus_list_alloc_link (service);
691   d->connection_link = _dbus_list_alloc_link (connection);
692   d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
693   
694   bus_service_ref (d->service);
695   dbus_connection_ref (d->connection);
696
697   d->before_connection = NULL;
698   link = _dbus_list_get_first_link (&service->owners);
699   while (link != NULL)
700     {
701       if (link->data == connection)
702         {
703           link = _dbus_list_get_next_link (&service->owners, link);
704
705           if (link)
706             d->before_connection = link->data;
707
708           break;
709         }
710       
711       link = _dbus_list_get_next_link (&service->owners, link);
712     }
713   
714   if (d->service_link == NULL ||
715       d->connection_link == NULL ||
716       d->hash_entry == NULL ||
717       !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
718                                         free_ownership_restore_data))
719     {
720       free_ownership_restore_data (d);
721       return FALSE;
722     }
723   
724   return TRUE;
725 }
726
727 /* this function is self-cancelling if you cancel the transaction */
728 dbus_bool_t
729 bus_service_remove_owner (BusService     *service,
730                           DBusConnection *owner,
731                           BusTransaction *transaction,
732                           DBusError      *error)
733 {
734   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
735   
736   /* We send out notifications before we do any work we
737    * might have to undo if the notification-sending failed
738    */
739   
740   /* Send service lost message */
741   if (bus_service_get_primary_owner (service) == owner)
742     {
743       if (!bus_driver_send_service_lost (owner, service->name,
744                                          transaction, error))
745         return FALSE;
746     }
747
748   if (service->owners == NULL)
749     {
750       _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
751     }
752   else if (_dbus_list_length_is_one (&service->owners))
753     {
754       if (!bus_driver_send_service_owner_changed (service->name,
755                                                   bus_connection_get_name (owner),
756                                                   NULL,
757                                                   transaction, error))
758         return FALSE;
759     }
760   else
761     {
762       DBusList *link;
763       DBusConnection *new_owner;
764       link = _dbus_list_get_first_link (&service->owners);
765       _dbus_assert (link != NULL);
766       link = _dbus_list_get_next_link (&service->owners, link);
767       _dbus_assert (link != NULL);
768
769       new_owner = link->data;
770
771       if (!bus_driver_send_service_owner_changed (service->name,
772                                                   bus_connection_get_name (owner),
773                                                   bus_connection_get_name (new_owner),
774                                                   transaction, error))
775         return FALSE;
776
777       /* This will be our new owner */
778       if (!bus_driver_send_service_acquired (new_owner,
779                                              service->name,
780                                              transaction,
781                                              error))
782         return FALSE;
783     }
784
785   if (!add_restore_ownership_to_transaction (transaction, service, owner))
786     {
787       BUS_SET_OOM (error);
788       return FALSE;
789     }
790   
791   bus_service_unlink_owner (service, owner);
792
793   if (service->owners == NULL)
794     bus_service_unlink (service);
795
796   return TRUE;
797 }
798
799 BusService *
800 bus_service_ref (BusService *service)
801 {
802   _dbus_assert (service->refcount > 0);
803   
804   service->refcount += 1;
805
806   return service;
807 }
808
809 void
810 bus_service_unref (BusService *service)
811 {
812   _dbus_assert (service->refcount > 0);
813   
814   service->refcount -= 1;
815
816   if (service->refcount == 0)
817     {
818       _dbus_assert (service->owners == NULL);
819       
820       dbus_free (service->name);
821       _dbus_mem_pool_dealloc (service->registry->service_pool, service);
822     }
823 }
824
825 DBusConnection*
826 bus_service_get_primary_owner (BusService *service)
827 {
828   return _dbus_list_get_first (&service->owners);
829 }
830
831 const char*
832 bus_service_get_name (BusService *service)
833 {
834   return service->name;
835 }
836
837 void
838 bus_service_set_prohibit_replacement (BusService  *service,
839                                       dbus_bool_t  prohibit_replacement)
840 {
841   service->prohibit_replacement = prohibit_replacement != FALSE;
842 }
843
844 dbus_bool_t
845 bus_service_get_prohibit_replacement (BusService *service)
846 {
847   return service->prohibit_replacement;
848 }
849
850 dbus_bool_t
851 bus_service_has_owner (BusService     *service,
852                        DBusConnection *owner)
853 {
854   DBusList *link;
855
856   link = _dbus_list_get_first_link (&service->owners);
857   
858   while (link != NULL)
859     {
860       if (link->data == owner)
861         return TRUE;
862       
863       link = _dbus_list_get_next_link (&service->owners, link);
864     }
865
866   return FALSE;
867 }