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