Patch provided by Ralf Habacker (ralf dot habacker at freenet dot de)
[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
47 struct BusOwner
48 {
49   int refcount;
50
51   BusService *service;
52   DBusConnection *conn;
53
54   unsigned int allow_replacement : 1;
55   unsigned int do_not_queue : 1;
56 };
57
58 struct BusRegistry
59 {
60   int refcount;
61
62   BusContext *context;
63   
64   DBusHashTable *service_hash;
65   DBusMemPool   *service_pool;
66   DBusMemPool   *owner_pool;
67
68   DBusHashTable *service_sid_table;
69 };
70
71 BusRegistry*
72 bus_registry_new (BusContext *context)
73 {
74   BusRegistry *registry;
75
76   registry = dbus_new0 (BusRegistry, 1);
77   if (registry == NULL)
78     return NULL;
79
80   registry->refcount = 1;
81   registry->context = context;
82   
83   registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
84                                                  NULL, NULL);
85   if (registry->service_hash == NULL)
86     goto failed;
87   
88   registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
89                                                TRUE);
90
91   if (registry->service_pool == NULL)
92     goto failed;
93
94   registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
95                                              TRUE);
96
97   if (registry->owner_pool == NULL)
98     goto failed;
99
100   registry->service_sid_table = NULL;
101   
102   return registry;
103
104  failed:
105   bus_registry_unref (registry);
106   return NULL;
107 }
108
109 BusRegistry *
110 bus_registry_ref (BusRegistry *registry)
111 {
112   _dbus_assert (registry->refcount > 0);
113   registry->refcount += 1;
114
115   return registry;
116 }
117
118 void
119 bus_registry_unref  (BusRegistry *registry)
120 {
121   _dbus_assert (registry->refcount > 0);
122   registry->refcount -= 1;
123
124   if (registry->refcount == 0)
125     {
126       if (registry->service_hash)
127         _dbus_hash_table_unref (registry->service_hash);
128       if (registry->service_pool)
129         _dbus_mem_pool_free (registry->service_pool);
130       if (registry->owner_pool)
131         _dbus_mem_pool_free (registry->owner_pool);
132       if (registry->service_sid_table)
133         _dbus_hash_table_unref (registry->service_sid_table);
134       
135       dbus_free (registry);
136     }
137 }
138
139 BusService*
140 bus_registry_lookup (BusRegistry      *registry,
141                      const DBusString *service_name)
142 {
143   BusService *service;
144
145   service = _dbus_hash_table_lookup_string (registry->service_hash,
146                                             _dbus_string_get_const_data (service_name));
147
148   return service;
149 }
150
151 static DBusList *
152 _bus_service_find_owner_link (BusService *service,
153                               DBusConnection *connection)
154 {
155   DBusList *link;
156   
157   link = _dbus_list_get_first_link (&service->owners);
158
159   while (link != NULL)
160     {
161       BusOwner *bus_owner;
162
163       bus_owner = (BusOwner *) link->data;
164       if (bus_owner->conn == connection) 
165         break;
166
167       link = _dbus_list_get_next_link (&service->owners, link);
168     }
169
170   return link;
171 }
172
173 static void
174 bus_owner_set_flags (BusOwner *owner,
175                      dbus_uint32_t flags)
176 {
177    owner->allow_replacement = 
178         (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
179
180    owner->do_not_queue =
181         (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
182 }
183
184 static BusOwner *
185 bus_owner_new (BusService *service, 
186                DBusConnection *conn, 
187                dbus_uint32_t flags)
188 {
189   BusOwner *result;
190
191   result = _dbus_mem_pool_alloc (service->registry->owner_pool);
192   if (result != NULL)
193     {
194       result->refcount = 1;
195       /* don't ref the connection because we don't want
196          to block the connection from going away.
197          transactions take care of reffing the connection
198          but we need to use refcounting on the owner
199          so that the owner does not get freed before
200          we can deref the connection in the transaction
201        */
202       result->conn = conn;
203       result->service = service;
204
205       if (!bus_connection_add_owned_service (conn, service))
206         {
207           _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
208           return NULL;
209         }
210         
211       bus_owner_set_flags (result, flags);
212     }
213   return result;
214 }
215
216 static BusOwner *
217 bus_owner_ref (BusOwner *owner)
218 {
219   _dbus_assert (owner->refcount > 0);
220   owner->refcount += 1;
221
222   return owner;
223 }
224
225 static void
226 bus_owner_unref  (BusOwner *owner)
227 {
228   _dbus_assert (owner->refcount > 0);
229   owner->refcount -= 1;
230
231   if (owner->refcount == 0)
232     {
233       bus_connection_remove_owned_service (owner->conn, owner->service);
234       _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
235     }
236 }
237
238 BusService*
239 bus_registry_ensure (BusRegistry               *registry,
240                      const DBusString          *service_name,
241                      DBusConnection            *owner_connection_if_created,
242                      dbus_uint32_t              flags,
243                      BusTransaction            *transaction,
244                      DBusError                 *error)
245 {
246   BusService *service;
247
248   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
249   
250   _dbus_assert (owner_connection_if_created != NULL);
251   _dbus_assert (transaction != NULL);
252
253   service = _dbus_hash_table_lookup_string (registry->service_hash,
254                                             _dbus_string_get_const_data (service_name));
255   if (service != NULL)
256     return service;
257   
258   service = _dbus_mem_pool_alloc (registry->service_pool);
259   if (service == NULL)
260     {
261       BUS_SET_OOM (error);
262       return NULL;
263     }
264
265   service->registry = registry;  
266   service->refcount = 1;
267
268   _dbus_verbose ("copying string %p '%s' to service->name\n",
269                  service_name, _dbus_string_get_const_data (service_name));
270   if (!_dbus_string_copy_data (service_name, &service->name))
271     {
272       _dbus_mem_pool_dealloc (registry->service_pool, service);
273       BUS_SET_OOM (error);
274       return NULL;
275     }
276   _dbus_verbose ("copied string %p '%s' to '%s'\n",
277                  service_name, _dbus_string_get_const_data (service_name),
278                  service->name);
279
280   if (!bus_driver_send_service_owner_changed (service->name, 
281                                               NULL,
282                                               bus_connection_get_name (owner_connection_if_created),
283                                               transaction, error))
284     {
285       bus_service_unref (service);
286       return NULL;
287     }
288
289   if (!bus_activation_service_created (bus_context_get_activation (registry->context),
290                                        service->name, transaction, error))
291     {
292       bus_service_unref (service);
293       return NULL;
294     }
295   
296   if (!bus_service_add_owner (service, owner_connection_if_created, flags,
297                                               transaction, error))
298     {
299       bus_service_unref (service);
300       return NULL;
301     }
302   
303   if (!_dbus_hash_table_insert_string (registry->service_hash,
304                                        service->name,
305                                        service))
306     {
307       /* The add_owner gets reverted on transaction cancel */
308       BUS_SET_OOM (error);
309       return NULL;
310     }
311   
312   return service;
313 }
314
315 void
316 bus_registry_foreach (BusRegistry               *registry,
317                       BusServiceForeachFunction  function,
318                       void                      *data)
319 {
320   DBusHashIter iter;
321   
322   _dbus_hash_iter_init (registry->service_hash, &iter);
323   while (_dbus_hash_iter_next (&iter))
324     {
325       BusService *service = _dbus_hash_iter_get_value (&iter);
326
327       (* function) (service, data);
328     }
329 }
330
331 dbus_bool_t
332 bus_registry_list_services (BusRegistry *registry,
333                             char      ***listp,
334                             int         *array_len)
335 {
336   int i, j, len;
337   char **retval;
338   DBusHashIter iter;
339    
340   len = _dbus_hash_table_get_n_entries (registry->service_hash);
341   retval = dbus_new (char *, len + 1);
342
343   if (retval == NULL)
344     return FALSE;
345
346   _dbus_hash_iter_init (registry->service_hash, &iter);
347   i = 0;
348   while (_dbus_hash_iter_next (&iter))
349     {
350       BusService *service = _dbus_hash_iter_get_value (&iter);
351
352       retval[i] = _dbus_strdup (service->name);
353       if (retval[i] == NULL)
354         goto error;
355
356       i++;
357     }
358
359   retval[i] = NULL;
360   
361   if (array_len)
362     *array_len = len;
363   
364   *listp = retval;
365   return TRUE;
366   
367  error:
368   for (j = 0; j < i; j++)
369     dbus_free (retval[i]);
370   dbus_free (retval);
371
372   return FALSE;
373 }
374
375 dbus_bool_t
376 bus_registry_acquire_service (BusRegistry      *registry,
377                               DBusConnection   *connection,
378                               const DBusString *service_name,
379                               dbus_uint32_t     flags,
380                               dbus_uint32_t    *result,
381                               BusTransaction   *transaction,
382                               DBusError        *error)
383 {
384   dbus_bool_t retval;
385   DBusConnection *old_owner_conn;
386   DBusConnection *current_owner_conn;
387   BusClientPolicy *policy;
388   BusService *service;
389   BusActivation  *activation;
390   BusSELinuxID *sid;
391   BusOwner *primary_owner;
392  
393   retval = FALSE;
394
395   if (!_dbus_validate_bus_name (service_name, 0,
396                                 _dbus_string_get_length (service_name)))
397     {
398       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
399                       "Requested bus name \"%s\" is not valid",
400                       _dbus_string_get_const_data (service_name));
401       
402       _dbus_verbose ("Attempt to acquire invalid service name\n");
403       
404       goto out;
405     }
406   
407   if (_dbus_string_get_byte (service_name, 0) == ':')
408     {
409       /* Not allowed; only base services can start with ':' */
410       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
411                       "Cannot acquire a service starting with ':' such as \"%s\"",
412                       _dbus_string_get_const_data (service_name));
413       
414       _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
415                      _dbus_string_get_const_data (service_name));
416       
417       goto out;
418     }
419
420   if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
421     {
422       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
423                       "Connection \"%s\" is not allowed to own the service \"%s\"because "
424                       "it is reserved for D-Bus' use only",
425                       bus_connection_is_active (connection) ?
426                       bus_connection_get_name (connection) :
427                       "(inactive)",
428                       DBUS_SERVICE_DBUS);
429       goto out;
430     }
431
432   policy = bus_connection_get_policy (connection);
433   _dbus_assert (policy != NULL);
434
435   /* Note that if sid is #NULL then the bus's own context gets used
436    * in bus_connection_selinux_allows_acquire_service()
437    */
438   sid = bus_selinux_id_table_lookup (registry->service_sid_table,
439                                      service_name);
440
441   if (!bus_selinux_allows_acquire_service (connection, sid,
442                                            _dbus_string_get_const_data (service_name), error))
443     {
444
445       if (dbus_error_is_set (error) &&
446           dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
447         {
448           goto out;
449         }
450
451       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
452                       "Connection \"%s\" is not allowed to own the service \"%s\" due "
453                       "to SELinux policy",
454                       bus_connection_is_active (connection) ?
455                       bus_connection_get_name (connection) :
456                       "(inactive)",
457                       _dbus_string_get_const_data (service_name));
458       goto out;
459     }
460   
461   if (!bus_client_policy_check_can_own (policy, connection,
462                                         service_name))
463     {
464       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
465                       "Connection \"%s\" is not allowed to own the service \"%s\" due "
466                       "to security policies in the configuration file",
467                       bus_connection_is_active (connection) ?
468                       bus_connection_get_name (connection) :
469                       "(inactive)",
470                       _dbus_string_get_const_data (service_name));
471       goto out;
472     }
473
474   if (bus_connection_get_n_services_owned (connection) >=
475       bus_context_get_max_services_per_connection (registry->context))
476     {
477       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
478                       "Connection \"%s\" is not allowed to own more services "
479                       "(increase limits in configuration file if required)",
480                       bus_connection_is_active (connection) ?
481                       bus_connection_get_name (connection) :
482                       "(inactive)");
483       goto out;
484     }
485   
486   service = bus_registry_lookup (registry, service_name);
487
488   if (service != NULL)
489     {
490       primary_owner = bus_service_get_primary_owner (service);
491       if (primary_owner != NULL)
492         old_owner_conn = primary_owner->conn;
493       else
494         old_owner_conn = NULL;
495     }
496   else
497     old_owner_conn = NULL;
498       
499   if (service == NULL)
500     {
501       service = bus_registry_ensure (registry,
502                                      service_name, connection, flags,
503                                      transaction, error);
504       if (service == NULL)
505         goto out;
506     }
507
508   primary_owner = bus_service_get_primary_owner (service);
509   if (primary_owner == NULL)
510     goto out;
511     
512   current_owner_conn = primary_owner->conn;
513      
514   if (old_owner_conn == NULL)
515     {
516       _dbus_assert (current_owner_conn == connection);
517
518       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;      
519     }
520   else if (old_owner_conn == connection)
521     {
522       bus_owner_set_flags (primary_owner, flags);
523       *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
524     }
525   else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
526            !(bus_service_get_allow_replacement (service))) ||
527            ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
528            !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING))) 
529     {
530       DBusList *link;
531       BusOwner *temp_owner;
532     /* Since we can't be queued if we are already in the queue
533        remove us */
534
535       link = _bus_service_find_owner_link (service, connection);
536       if (link != NULL)
537         {
538           _dbus_list_unlink (&service->owners, link);
539           temp_owner = (BusOwner *)link->data;
540           bus_owner_unref (temp_owner); 
541           _dbus_list_free_link (link);
542         }
543       
544       *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
545     }
546   else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
547            (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
548             !(bus_service_get_allow_replacement (service))))
549     {
550       /* Queue the connection */
551       if (!bus_service_add_owner (service, connection, 
552                                   flags,
553                                   transaction, error))
554         goto out;
555       
556       *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
557     }
558   else
559     {
560       /* Replace the current owner */
561
562       /* We enqueue the new owner and remove the first one because
563        * that will cause NameAcquired and NameLost messages to
564        * be sent.
565        */
566       
567       if (!bus_service_add_owner (service, connection,
568                                   flags,
569                                   transaction, error))
570         goto out;
571
572       if (primary_owner->do_not_queue)
573         {
574           if (!bus_service_remove_owner (service, old_owner_conn,
575                                          transaction, error))
576             goto out;
577         }
578       else
579         {
580           if (!bus_service_swap_owner (service, old_owner_conn,
581                                        transaction, error))
582             goto out;
583         }
584         
585     
586       _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
587       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
588     }
589
590   activation = bus_context_get_activation (registry->context);
591   retval = bus_activation_send_pending_auto_activation_messages (activation,
592                                                                  service,
593                                                                  transaction,
594                                                                  error);
595   
596  out:
597   return retval;
598 }
599
600 dbus_bool_t
601 bus_registry_release_service (BusRegistry      *registry,
602                               DBusConnection   *connection,
603                               const DBusString *service_name,
604                               dbus_uint32_t    *result,
605                               BusTransaction   *transaction,
606                               DBusError        *error)
607 {
608   dbus_bool_t retval;
609   BusService *service;
610
611   retval = FALSE;
612
613   if (!_dbus_validate_bus_name (service_name, 0,
614                                 _dbus_string_get_length (service_name)))
615     {
616       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
617                       "Given bus name \"%s\" is not valid",
618                       _dbus_string_get_const_data (service_name));
619
620       _dbus_verbose ("Attempt to release invalid service name\n");
621
622       goto out;
623     }
624
625   if (_dbus_string_get_byte (service_name, 0) == ':')
626     {
627       /* Not allowed; the base service name cannot be created or released */
628       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
629                       "Cannot release a service starting with ':' such as \"%s\"",
630                       _dbus_string_get_const_data (service_name));
631
632       _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
633                      _dbus_string_get_const_data (service_name));
634
635       goto out;
636     }
637
638    if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
639     {
640       /* Not allowed; the base service name cannot be created or released */
641       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
642                       "Cannot release the %s service because it is owned by the bus",
643                      DBUS_SERVICE_DBUS);
644
645       _dbus_verbose ("Attempt to release service name \"%s\"",
646                      DBUS_SERVICE_DBUS);
647
648       goto out;
649     }
650
651   service = bus_registry_lookup (registry, service_name);
652
653   if (service == NULL)
654     {
655       *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
656     }
657   else if (!bus_service_has_owner (service, connection))
658     {
659       *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
660     }
661   else
662     {
663       if (!bus_service_remove_owner (service, connection,
664                                      transaction, error))
665         goto out;
666
667       _dbus_assert (!bus_service_has_owner (service, connection));
668       *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
669     }
670
671   retval = TRUE;
672
673  out:
674   return retval;
675 }
676
677 dbus_bool_t
678 bus_registry_set_service_context_table (BusRegistry   *registry,
679                                         DBusHashTable *table)
680 {
681   DBusHashTable *new_table;
682   DBusHashIter iter;
683   
684   new_table = bus_selinux_id_table_new ();
685   if (!new_table)
686     return FALSE;
687
688   _dbus_hash_iter_init (table, &iter);
689   while (_dbus_hash_iter_next (&iter))
690     {
691       const char *service = _dbus_hash_iter_get_string_key (&iter);
692       const char *context = _dbus_hash_iter_get_value (&iter);
693
694       if (!bus_selinux_id_table_insert (new_table,
695                                         service,
696                                         context))
697         return FALSE;
698     }
699   
700   if (registry->service_sid_table)
701     _dbus_hash_table_unref (registry->service_sid_table);
702   registry->service_sid_table = new_table;
703   return TRUE;
704 }
705
706 static void
707 bus_service_unlink_owner (BusService      *service,
708                           BusOwner        *owner)
709 {
710   _dbus_list_remove_last (&service->owners, owner);
711   bus_owner_unref (owner);
712 }
713
714 static void
715 bus_service_unlink (BusService *service)
716 {
717   _dbus_assert (service->owners == NULL);
718
719   /* the service may not be in the hash, if
720    * the failure causing transaction cancel
721    * was in the right place, but that's OK
722    */
723   _dbus_hash_table_remove_string (service->registry->service_hash,
724                                   service->name);
725   
726   bus_service_unref (service);
727 }
728
729 static void
730 bus_service_relink (BusService           *service,
731                     DBusPreallocatedHash *preallocated)
732 {
733   _dbus_assert (service->owners == NULL);
734   _dbus_assert (preallocated != NULL);
735
736   _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
737                                                preallocated,
738                                                service->name,
739                                                service);
740   
741   bus_service_ref (service);
742 }
743
744 /**
745  * Data used to represent an ownership cancellation in
746  * a bus transaction.
747  */
748 typedef struct
749 {
750   BusOwner *owner;            /**< the owner */
751   BusService *service;        /**< service to cancel ownership of */
752 } OwnershipCancelData;
753
754 static void
755 cancel_ownership (void *data)
756 {
757   OwnershipCancelData *d = data;
758
759   /* We don't need to send messages notifying of these
760    * changes, since we're reverting something that was
761    * cancelled (effectively never really happened)
762    */
763   bus_service_unlink_owner (d->service, d->owner);
764   
765   if (d->service->owners == NULL)
766     bus_service_unlink (d->service);
767 }
768
769 static void
770 free_ownership_cancel_data (void *data)
771 {
772   OwnershipCancelData *d = data;
773
774   dbus_connection_unref (d->owner->conn);
775   bus_owner_unref (d->owner);
776   bus_service_unref (d->service);
777   
778   dbus_free (d);
779 }
780
781 static dbus_bool_t
782 add_cancel_ownership_to_transaction (BusTransaction *transaction,
783                                      BusService     *service,
784                                      BusOwner       *owner)
785 {
786   OwnershipCancelData *d;
787
788   d = dbus_new (OwnershipCancelData, 1);
789   if (d == NULL)
790     return FALSE;
791   
792   d->service = service;
793   d->owner = owner;
794
795   if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
796                                         free_ownership_cancel_data))
797     {
798       dbus_free (d);
799       return FALSE;
800     }
801
802   bus_service_ref (d->service);
803   bus_owner_ref (owner);
804   dbus_connection_ref (d->owner->conn);
805  
806   return TRUE;
807 }
808
809 /* this function is self-cancelling if you cancel the transaction */
810 dbus_bool_t
811 bus_service_add_owner (BusService     *service,
812                        DBusConnection *connection,
813                        dbus_uint32_t  flags,
814                        BusTransaction *transaction,
815                        DBusError      *error)
816 {
817   BusOwner *bus_owner;
818   DBusList *bus_owner_link;
819   
820   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
821   
822  /* Send service acquired message first, OOM will result
823   * in cancelling the transaction
824   */
825   if (service->owners == NULL)
826     {
827       if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
828         return FALSE;
829     }
830   
831   bus_owner_link = _bus_service_find_owner_link (service, connection);
832   
833   if (bus_owner_link == NULL)
834     {
835       bus_owner = bus_owner_new (service, connection, flags);
836       if (bus_owner == NULL)
837         {
838           BUS_SET_OOM (error);
839           return FALSE;
840         }
841
842       bus_owner_set_flags (bus_owner, flags);
843       if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
844         {
845           if (!_dbus_list_append (&service->owners,
846                                   bus_owner))
847             {
848               bus_owner_unref (bus_owner);
849               BUS_SET_OOM (error);
850               return FALSE;
851             }
852         }
853       else
854         {
855           if (!_dbus_list_insert_after (&service->owners,
856                                          _dbus_list_get_first_link (&service->owners),
857                                          bus_owner))
858             {
859               bus_owner_unref (bus_owner);
860               BUS_SET_OOM (error);
861               return FALSE;
862             }
863         }      
864     } 
865   else 
866     {
867       /* Update the link since we are already in the queue
868        * No need for operations that can produce OOM
869        */
870
871       bus_owner = (BusOwner *) bus_owner_link->data;
872       if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
873         {
874           DBusList *link;
875           _dbus_list_unlink (&service->owners, bus_owner_link);
876           link = _dbus_list_get_first_link (&service->owners);
877           _dbus_assert (link != NULL);
878           
879           _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
880         }
881       
882       bus_owner_set_flags (bus_owner, flags);
883       return TRUE;
884     }
885
886   if (!add_cancel_ownership_to_transaction (transaction,
887                                             service,
888                                             bus_owner))
889     {
890       bus_service_unlink_owner (service, bus_owner);
891       BUS_SET_OOM (error);
892       return FALSE;
893     }
894
895   return TRUE;
896 }
897
898 typedef struct
899 {
900   BusOwner       *owner;
901   BusService     *service;
902   BusOwner       *before_owner; /* restore to position before this connection in owners list */
903   DBusList       *owner_link;
904   DBusList       *service_link;
905   DBusPreallocatedHash *hash_entry;
906 } OwnershipRestoreData;
907
908 static void
909 restore_ownership (void *data)
910 {
911   OwnershipRestoreData *d = data;
912   DBusList *link;
913
914   _dbus_assert (d->service_link != NULL);
915   _dbus_assert (d->owner_link != NULL);
916   
917   if (d->service->owners == NULL)
918     {
919       _dbus_assert (d->hash_entry != NULL);
920       bus_service_relink (d->service, d->hash_entry);
921     }
922   else
923     {
924       _dbus_assert (d->hash_entry == NULL);
925     }
926   
927   /* We don't need to send messages notifying of these
928    * changes, since we're reverting something that was
929    * cancelled (effectively never really happened)
930    */
931   link = _dbus_list_get_first_link (&d->service->owners);
932   while (link != NULL)
933     {
934       if (link->data == d->before_owner)
935         break;
936
937       link = _dbus_list_get_next_link (&d->service->owners, link);
938     }
939   
940   _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
941
942   /* Note that removing then restoring this changes the order in which
943    * ServiceDeleted messages are sent on destruction of the
944    * connection.  This should be OK as the only guarantee there is
945    * that the base service is destroyed last, and we never even
946    * tentatively remove the base service.
947    */
948   bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
949   
950   d->hash_entry = NULL;
951   d->service_link = NULL;
952   d->owner_link = NULL;
953 }
954
955 static void
956 free_ownership_restore_data (void *data)
957 {
958   OwnershipRestoreData *d = data;
959
960   if (d->service_link)
961     _dbus_list_free_link (d->service_link);
962   if (d->owner_link)
963     _dbus_list_free_link (d->owner_link);
964   if (d->hash_entry)
965     _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
966                                               d->hash_entry);
967
968   dbus_connection_unref (d->owner->conn);
969   bus_owner_unref (d->owner);
970   bus_service_unref (d->service);
971   
972   dbus_free (d);
973 }
974
975 static dbus_bool_t
976 add_restore_ownership_to_transaction (BusTransaction *transaction,
977                                       BusService     *service,
978                                       BusOwner       *owner)
979 {
980   OwnershipRestoreData *d;
981   DBusList *link;
982
983   d = dbus_new (OwnershipRestoreData, 1);
984   if (d == NULL)
985     return FALSE;
986   
987   d->service = service;
988   d->owner = owner;
989   d->service_link = _dbus_list_alloc_link (service);
990   d->owner_link = _dbus_list_alloc_link (owner);
991   d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
992   
993   bus_service_ref (d->service);
994   bus_owner_ref (d->owner);
995   dbus_connection_ref (d->owner->conn);
996
997   d->before_owner = NULL;
998   link = _dbus_list_get_first_link (&service->owners);
999   while (link != NULL)
1000     {
1001       if (link->data == owner)
1002         {
1003           link = _dbus_list_get_next_link (&service->owners, link);
1004
1005           if (link)
1006             d->before_owner = link->data;
1007
1008           break;
1009         }
1010       
1011       link = _dbus_list_get_next_link (&service->owners, link);
1012     }
1013   
1014   if (d->service_link == NULL ||
1015       d->owner_link == NULL ||
1016       d->hash_entry == NULL ||
1017       !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1018                                         free_ownership_restore_data))
1019     {
1020       free_ownership_restore_data (d);
1021       return FALSE;
1022     }
1023   
1024   return TRUE;
1025 }
1026
1027 dbus_bool_t
1028 bus_service_swap_owner (BusService     *service,
1029                         DBusConnection *connection,
1030                         BusTransaction *transaction,
1031                         DBusError      *error)
1032 {
1033   DBusList *swap_link;
1034   BusOwner *primary_owner;
1035
1036   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1037
1038   /* We send out notifications before we do any work we
1039    * might have to undo if the notification-sending failed
1040    */
1041   
1042   /* Send service lost message */
1043   primary_owner = bus_service_get_primary_owner (service);
1044   if (primary_owner == NULL || primary_owner->conn != connection)
1045     _dbus_assert_not_reached ("Tried to swap a non primary owner");
1046
1047     
1048   if (!bus_driver_send_service_lost (connection, service->name,
1049                                      transaction, error))
1050     return FALSE;
1051
1052   if (service->owners == NULL)
1053     {
1054       _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1055     }
1056   else if (_dbus_list_length_is_one (&service->owners))
1057     {
1058       _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1059     }
1060   else
1061     {
1062       DBusList *link;
1063       BusOwner *new_owner;
1064       DBusConnection *new_owner_conn;
1065       link = _dbus_list_get_first_link (&service->owners);
1066       _dbus_assert (link != NULL);
1067       link = _dbus_list_get_next_link (&service->owners, link);
1068       _dbus_assert (link != NULL);
1069
1070       new_owner = (BusOwner *)link->data;
1071       new_owner_conn = new_owner->conn;
1072
1073       if (!bus_driver_send_service_owner_changed (service->name,
1074                                                   bus_connection_get_name (connection),
1075                                                   bus_connection_get_name (new_owner_conn),
1076                                                   transaction, error))
1077         return FALSE;
1078
1079       /* This will be our new owner */
1080       if (!bus_driver_send_service_acquired (new_owner_conn,
1081                                              service->name,
1082                                              transaction,
1083                                              error))
1084         return FALSE;
1085     }
1086
1087   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1088     {
1089       BUS_SET_OOM (error);
1090       return FALSE;
1091     }
1092
1093   /* unlink the primary and make it the second link */
1094   swap_link = _dbus_list_get_first_link (&service->owners);
1095   _dbus_list_unlink (&service->owners, swap_link);
1096
1097   _dbus_list_insert_after_link (&service->owners,
1098                                 _dbus_list_get_first_link (&service->owners),
1099                                 swap_link);
1100
1101   return TRUE;
1102 }
1103
1104 /* this function is self-cancelling if you cancel the transaction */
1105 dbus_bool_t
1106 bus_service_remove_owner (BusService     *service,
1107                           DBusConnection *connection,
1108                           BusTransaction *transaction,
1109                           DBusError      *error)
1110 {
1111   BusOwner *primary_owner;
1112   
1113   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1114   
1115   /* We send out notifications before we do any work we
1116    * might have to undo if the notification-sending failed
1117    */
1118   
1119   /* Send service lost message */
1120   primary_owner = bus_service_get_primary_owner (service);
1121   if (primary_owner != NULL && primary_owner->conn == connection)
1122     {
1123       if (!bus_driver_send_service_lost (connection, service->name,
1124                                          transaction, error))
1125         return FALSE;
1126     }
1127   else
1128     {
1129       /* if we are not the primary owner then just remove us from the queue */
1130       DBusList *link;
1131       BusOwner *temp_owner;
1132
1133       link = _bus_service_find_owner_link (service, connection);
1134       _dbus_list_unlink (&service->owners, link);
1135       temp_owner = (BusOwner *)link->data;
1136       bus_owner_unref (temp_owner); 
1137       _dbus_list_free_link (link);
1138
1139       return TRUE; 
1140     }
1141
1142   if (service->owners == NULL)
1143     {
1144       _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1145     }
1146   else if (_dbus_list_length_is_one (&service->owners))
1147     {
1148       if (!bus_driver_send_service_owner_changed (service->name,
1149                                                   bus_connection_get_name (connection),
1150                                                   NULL,
1151                                                   transaction, error))
1152         return FALSE;
1153     }
1154   else
1155     {
1156       DBusList *link;
1157       BusOwner *new_owner;
1158       DBusConnection *new_owner_conn;
1159       link = _dbus_list_get_first_link (&service->owners);
1160       _dbus_assert (link != NULL);
1161       link = _dbus_list_get_next_link (&service->owners, link);
1162       _dbus_assert (link != NULL);
1163
1164       new_owner = (BusOwner *)link->data;
1165       new_owner_conn = new_owner->conn;
1166
1167       if (!bus_driver_send_service_owner_changed (service->name,
1168                                                   bus_connection_get_name (connection),
1169                                                   bus_connection_get_name (new_owner_conn),
1170                                                   transaction, error))
1171         return FALSE;
1172
1173       /* This will be our new owner */
1174       if (!bus_driver_send_service_acquired (new_owner_conn,
1175                                              service->name,
1176                                              transaction,
1177                                              error))
1178         return FALSE;
1179     }
1180
1181   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1182     {
1183       BUS_SET_OOM (error);
1184       return FALSE;
1185     }
1186  
1187   bus_service_unlink_owner (service, primary_owner);
1188
1189   if (service->owners == NULL)
1190     bus_service_unlink (service);
1191
1192   return TRUE;
1193 }
1194
1195 BusService *
1196 bus_service_ref (BusService *service)
1197 {
1198   _dbus_assert (service->refcount > 0);
1199   
1200   service->refcount += 1;
1201
1202   return service;
1203 }
1204
1205 void
1206 bus_service_unref (BusService *service)
1207 {
1208   _dbus_assert (service->refcount > 0);
1209   
1210   service->refcount -= 1;
1211
1212   if (service->refcount == 0)
1213     {
1214       _dbus_assert (service->owners == NULL);
1215       
1216       dbus_free (service->name);
1217       _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1218     }
1219 }
1220
1221 DBusConnection *
1222 bus_service_get_primary_owners_connection (BusService *service)
1223 {
1224   BusOwner *owner;
1225
1226   owner = bus_service_get_primary_owner (service);
1227
1228   if (owner != NULL)
1229     return owner->conn;
1230   else
1231     return NULL;
1232 }
1233
1234 BusOwner*
1235 bus_service_get_primary_owner (BusService *service)
1236 {
1237   return _dbus_list_get_first (&service->owners);
1238 }
1239
1240 const char*
1241 bus_service_get_name (BusService *service)
1242 {
1243   return service->name;
1244 }
1245
1246 dbus_bool_t
1247 bus_service_get_allow_replacement (BusService *service)
1248 {
1249   BusOwner *owner;
1250   DBusList *link;
1251  
1252   _dbus_assert (service->owners != NULL);
1253
1254   link = _dbus_list_get_first_link (&service->owners);
1255   owner = (BusOwner *) link->data;
1256
1257   return owner->allow_replacement;
1258 }
1259
1260 dbus_bool_t
1261 bus_service_has_owner (BusService     *service,
1262                        DBusConnection *connection)
1263 {
1264   DBusList *link;
1265
1266   link = _bus_service_find_owner_link (service, connection);
1267  
1268   if (link == NULL)
1269     return FALSE;
1270   else
1271     return TRUE;
1272 }
1273
1274 dbus_bool_t 
1275 bus_service_list_queued_owners (BusService *service,
1276                                 DBusList  **return_list,
1277                                 DBusError  *error)
1278 {
1279   DBusList *link;
1280
1281   _dbus_assert (*return_list == NULL);
1282
1283   link = _dbus_list_get_first_link (&service->owners);
1284   _dbus_assert (link != NULL);
1285   
1286   while (link != NULL)
1287     {
1288       BusOwner *owner;
1289       const char *uname;
1290
1291       owner = (BusOwner *) link->data;
1292       uname = bus_connection_get_name (owner->conn);
1293
1294       if (!_dbus_list_append (return_list, (char *)uname))
1295         goto oom;
1296
1297       link = _dbus_list_get_next_link (&service->owners, link);
1298     }
1299   
1300   return TRUE;
1301   
1302  oom:
1303   _dbus_list_clear (return_list);
1304   BUS_SET_OOM (error);
1305   return FALSE;
1306 }