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