Sophie

Sophie

distrib > Mandriva > 2007.0 > x86_64 > media > main-release > by-pkgid > 926d2d1e3111287cee1b0a4fad4fb4f6 > files > 222

lib64dbus-1_3-devel-0.92-6mdv2007.0.x86_64.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>services.c Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.2.15 -->
<center>
<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; <a class="qindex" href="annotated.html">Data Structures</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Data Fields</a> &nbsp; <a class="qindex" href="pages.html">Related Pages</a> &nbsp; </center>
<hr><h1>services.c</h1><div class="fragment"><pre>00001 <font class="comment">/* -*- mode: C; c-file-style: "gnu" -*- */</font>
00002 <font class="comment">/* services.c  Service management</font>
00003 <font class="comment"> *</font>
00004 <font class="comment"> * Copyright (C) 2003  Red Hat, Inc.</font>
00005 <font class="comment"> * Copyright (C) 2003  CodeFactory AB</font>
00006 <font class="comment"> *</font>
00007 <font class="comment"> * Licensed under the Academic Free License version 1.2</font>
00008 <font class="comment"> * </font>
00009 <font class="comment"> * This program is free software; you can redistribute it and/or modify</font>
00010 <font class="comment"> * it under the terms of the GNU General Public License as published by</font>
00011 <font class="comment"> * the Free Software Foundation; either version 2 of the License, or</font>
00012 <font class="comment"> * (at your option) any later version.</font>
00013 <font class="comment"> *</font>
00014 <font class="comment"> * This program is distributed in the hope that it will be useful,</font>
00015 <font class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</font>
00016 <font class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</font>
00017 <font class="comment"> * GNU General Public License for more details.</font>
00018 <font class="comment"> * </font>
00019 <font class="comment"> * You should have received a copy of the GNU General Public License</font>
00020 <font class="comment"> * along with this program; if not, write to the Free Software</font>
00021 <font class="comment"> * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA</font>
00022 <font class="comment"> *</font>
00023 <font class="comment"> */</font>
00024 <font class="preprocessor">#include &lt;dbus/dbus-hash.h&gt;</font>
00025 <font class="preprocessor">#include &lt;dbus/dbus-list.h&gt;</font>
00026 <font class="preprocessor">#include &lt;dbus/dbus-mempool.h&gt;</font>
00027 
00028 <font class="preprocessor">#include "driver.h"</font>
00029 <font class="preprocessor">#include "services.h"</font>
00030 <font class="preprocessor">#include "connection.h"</font>
00031 <font class="preprocessor">#include "utils.h"</font>
00032 <font class="preprocessor">#include "activation.h"</font>
00033 <font class="preprocessor">#include "policy.h"</font>
00034 
00035 <font class="keyword">struct </font>BusService
00036 {
00037   <font class="keywordtype">int</font> refcount;
00038 
00039   BusRegistry *registry;
00040   <font class="keywordtype">char</font> *name;
00041   <a class="code" href="structDBusList.html">DBusList</a> *owners;
00042   
00043   <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> prohibit_replacement : 1;
00044 };
00045 
00046 <font class="keyword">struct </font>BusRegistry
00047 {
00048   <font class="keywordtype">int</font> refcount;
00049 
00050   BusContext *context;
00051   
00052   <a class="code" href="structDBusHashTable.html">DBusHashTable</a> *service_hash;
00053   <a class="code" href="structDBusMemPool.html">DBusMemPool</a>   *service_pool;
00054 };
00055 
00056 BusRegistry*
00057 bus_registry_new (BusContext *context)
00058 {
00059   BusRegistry *registry;
00060 
00061   registry = dbus_new0 (BusRegistry, 1);
00062   <font class="keywordflow">if</font> (registry == NULL)
00063     <font class="keywordflow">return</font> NULL;
00064 
00065   registry-&gt;refcount = 1;
00066   registry-&gt;context = context;
00067   
00068   registry-&gt;service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
00069                                                  NULL, NULL);
00070   <font class="keywordflow">if</font> (registry-&gt;service_hash == NULL)
00071     <font class="keywordflow">goto</font> failed;
00072   
00073   registry-&gt;service_pool = _dbus_mem_pool_new (<font class="keyword">sizeof</font> (BusService),
00074                                                TRUE);
00075   <font class="keywordflow">if</font> (registry-&gt;service_pool == NULL)
00076     <font class="keywordflow">goto</font> failed;
00077 
00078   <font class="keywordflow">return</font> registry;
00079 
00080  failed:
00081   bus_registry_unref (registry);
00082   <font class="keywordflow">return</font> NULL;
00083 }
00084 
00085 <font class="keywordtype">void</font>
00086 bus_registry_ref (BusRegistry *registry)
00087 {
00088   _dbus_assert (registry-&gt;refcount &gt; 0);
00089   registry-&gt;refcount += 1;
00090 }
00091 
00092 <font class="keywordtype">void</font>
00093 bus_registry_unref  (BusRegistry *registry)
00094 {
00095   _dbus_assert (registry-&gt;refcount &gt; 0);
00096   registry-&gt;refcount -= 1;
00097 
00098   <font class="keywordflow">if</font> (registry-&gt;refcount == 0)
00099     {
00100       <font class="keywordflow">if</font> (registry-&gt;service_hash)
00101         _dbus_hash_table_unref (registry-&gt;service_hash);
00102       <font class="keywordflow">if</font> (registry-&gt;service_pool)
00103         _dbus_mem_pool_free (registry-&gt;service_pool);
00104 
00105       dbus_free (registry);
00106     }
00107 }
00108 
00109 BusService*
00110 bus_registry_lookup (BusRegistry      *registry,
00111                      <font class="keyword">const</font> <a class="code" href="structDBusString.html">DBusString</a> *service_name)
00112 {
00113   BusService *service;
00114 
00115   service = _dbus_hash_table_lookup_string (registry-&gt;service_hash,
00116                                             _dbus_string_get_const_data (service_name));
00117 
00118   <font class="keywordflow">return</font> service;
00119 }
00120 
00121 BusService*
00122 bus_registry_ensure (BusRegistry               *registry,
00123                      <font class="keyword">const</font> <a class="code" href="structDBusString.html">DBusString</a>          *service_name,
00124                      <a class="code" href="structDBusConnection.html">DBusConnection</a>            *owner_if_created,
00125                      BusTransaction            *transaction,
00126                      <a class="code" href="structDBusError.html">DBusError</a>                 *error)
00127 {
00128   BusService *service;
00129 
00130   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00131   
00132   _dbus_assert (owner_if_created != NULL);
00133   _dbus_assert (transaction != NULL);
00134 
00135   service = _dbus_hash_table_lookup_string (registry-&gt;service_hash,
00136                                             _dbus_string_get_const_data (service_name));
00137   <font class="keywordflow">if</font> (service != NULL)
00138     <font class="keywordflow">return</font> service;
00139   
00140   service = _dbus_mem_pool_alloc (registry-&gt;service_pool);
00141   <font class="keywordflow">if</font> (service == NULL)
00142     {
00143       BUS_SET_OOM (error);
00144       <font class="keywordflow">return</font> NULL;
00145     }
00146 
00147   service-&gt;registry = registry;  
00148   service-&gt;refcount = 1;
00149   
00150   <font class="keywordflow">if</font> (!_dbus_string_copy_data (service_name, &amp;service-&gt;name))
00151     {
00152       _dbus_mem_pool_dealloc (registry-&gt;service_pool, service);
00153       BUS_SET_OOM (error);
00154       <font class="keywordflow">return</font> NULL;
00155     }
00156 
00157   <font class="keywordflow">if</font> (!bus_driver_send_service_created (service-&gt;name, transaction, error))
00158     {
00159       bus_service_unref (service);
00160       <font class="keywordflow">return</font> NULL;
00161     }
00162 
00163   <font class="keywordflow">if</font> (!bus_activation_service_created (bus_context_get_activation (registry-&gt;context),
00164                                        service-&gt;name, transaction, error))
00165     {
00166       bus_service_unref (service);
00167       <font class="keywordflow">return</font> NULL;
00168     }
00169   
00170   <font class="keywordflow">if</font> (!bus_service_add_owner (service, owner_if_created,
00171                               transaction, error))
00172     {
00173       bus_service_unref (service);
00174       <font class="keywordflow">return</font> NULL;
00175     }
00176   
00177   <font class="keywordflow">if</font> (!_dbus_hash_table_insert_string (registry-&gt;service_hash,
00178                                        service-&gt;name,
00179                                        service))
00180     {
00181       <font class="comment">/* The add_owner gets reverted on transaction cancel */</font>
00182       BUS_SET_OOM (error);
00183       <font class="keywordflow">return</font> NULL;
00184     }
00185   
00186   <font class="keywordflow">return</font> service;
00187 }
00188 
00189 <font class="keywordtype">void</font>
00190 bus_registry_foreach (BusRegistry               *registry,
00191                       BusServiceForeachFunction  function,
00192                       <font class="keywordtype">void</font>                      *data)
00193 {
00194   <a class="code" href="structDBusHashIter.html">DBusHashIter</a> iter;
00195   
00196   _dbus_hash_iter_init (registry-&gt;service_hash, &amp;iter);
00197   <font class="keywordflow">while</font> (_dbus_hash_iter_next (&amp;iter))
00198     {
00199       BusService *service = _dbus_hash_iter_get_value (&amp;iter);
00200 
00201       (* function) (service, data);
00202     }
00203 }
00204 
00205 dbus_bool_t
00206 bus_registry_list_services (BusRegistry *registry,
00207                             <font class="keywordtype">char</font>      ***listp,
00208                             <font class="keywordtype">int</font>         *array_len)
00209 {
00210   <font class="keywordtype">int</font> i, j, len;
00211   <font class="keywordtype">char</font> **retval;
00212   <a class="code" href="structDBusHashIter.html">DBusHashIter</a> iter;
00213    
00214   len = _dbus_hash_table_get_n_entries (registry-&gt;service_hash);
00215   retval = dbus_new (<font class="keywordtype">char</font> *, len + 1);
00216 
00217   <font class="keywordflow">if</font> (retval == NULL)
00218     <font class="keywordflow">return</font> FALSE;
00219 
00220   _dbus_hash_iter_init (registry-&gt;service_hash, &amp;iter);
00221   i = 0;
00222   <font class="keywordflow">while</font> (_dbus_hash_iter_next (&amp;iter))
00223     {
00224       BusService *service = _dbus_hash_iter_get_value (&amp;iter);
00225 
00226       retval[i] = _dbus_strdup (service-&gt;name);
00227       <font class="keywordflow">if</font> (retval[i] == NULL)
00228         <font class="keywordflow">goto</font> error;
00229 
00230       i++;
00231     }
00232 
00233   retval[i] = NULL;
00234   
00235   <font class="keywordflow">if</font> (array_len)
00236     *array_len = len;
00237   
00238   *listp = retval;
00239   <font class="keywordflow">return</font> TRUE;
00240   
00241  error:
00242   <font class="keywordflow">for</font> (j = 0; j &lt; i; j++)
00243     dbus_free (retval[i]);
00244   dbus_free (retval);
00245 
00246   <font class="keywordflow">return</font> FALSE;
00247 }
00248 
00249 dbus_bool_t
00250 bus_registry_acquire_service (BusRegistry      *registry,
00251                               <a class="code" href="structDBusConnection.html">DBusConnection</a>   *connection,
00252                               <font class="keyword">const</font> <a class="code" href="structDBusString.html">DBusString</a> *service_name,
00253                               dbus_uint32_t     flags,
00254                               dbus_uint32_t    *result,
00255                               BusTransaction   *transaction,
00256                               <a class="code" href="structDBusError.html">DBusError</a>        *error)
00257 {
00258   dbus_bool_t retval;
00259   <a class="code" href="structDBusConnection.html">DBusConnection</a> *old_owner;
00260   <a class="code" href="structDBusConnection.html">DBusConnection</a> *current_owner;
00261   BusClientPolicy *policy;
00262   BusService *service;
00263   
00264   retval = FALSE;
00265 
00266   <font class="keywordflow">if</font> (_dbus_string_get_length (service_name) == 0)
00267     {
00268       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
00269                       <font class="stringliteral">"Zero-length service name is not allowed"</font>);
00270       
00271       _dbus_verbose (<font class="stringliteral">"Attempt to acquire zero-length service name\n"</font>);
00272       
00273       <font class="keywordflow">goto</font> out;
00274     }
00275   
00276   <font class="keywordflow">if</font> (_dbus_string_get_byte (service_name, 0) == <font class="charliteral">':'</font>)
00277     {
00278       <font class="comment">/* Not allowed; only base services can start with ':' */</font>
00279       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
00280                       <font class="stringliteral">"Cannot acquire a service starting with ':' such as \"%s\""</font>,
00281                       _dbus_string_get_const_data (service_name));
00282       
00283       _dbus_verbose (<font class="stringliteral">"Attempt to acquire invalid base service name \"%s\""</font>,
00284                      _dbus_string_get_const_data (service_name));
00285       
00286       <font class="keywordflow">goto</font> out;
00287     }
00288 
00289   policy = bus_connection_get_policy (connection);
00290   _dbus_assert (policy != NULL);
00291 
00292   <font class="keywordflow">if</font> (!bus_client_policy_check_can_own (policy, connection,
00293                                         service_name))
00294     {
00295       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
00296                       <font class="stringliteral">"Connection \"%s\" is not allowed to own the service \"%s\" due "</font>
00297                       <font class="stringliteral">"to security policies in the configuration file"</font>,
00298                       bus_connection_is_active (connection) ?
00299                       bus_connection_get_name (connection) :
00300                       "(inactive)");
00301       <font class="keywordflow">goto</font> out;
00302     }
00303 
00304   <font class="keywordflow">if</font> (bus_connection_get_n_services_owned (connection) &gt;=
00305       bus_context_get_max_services_per_connection (registry-&gt;context))
00306     {
00307       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
00308                       <font class="stringliteral">"Connection \"%s\" is not allowed to own more services "</font>
00309                       <font class="stringliteral">"(increase limits in configuration file if required)"</font>,
00310                       bus_connection_is_active (connection) ?
00311                       bus_connection_get_name (connection) :
00312                       "(inactive)");
00313       <font class="keywordflow">goto</font> out;
00314     }
00315   
00316   service = bus_registry_lookup (registry, service_name);
00317 
00318   <font class="keywordflow">if</font> (service != NULL)
00319     old_owner = bus_service_get_primary_owner (service);
00320   <font class="keywordflow">else</font>
00321     old_owner = NULL;
00322       
00323   <font class="keywordflow">if</font> (service == NULL)
00324     {
00325       service = bus_registry_ensure (registry,
00326                                      service_name, connection, transaction, error);
00327       <font class="keywordflow">if</font> (service == NULL)
00328         <font class="keywordflow">goto</font> out;
00329     }
00330 
00331   current_owner = bus_service_get_primary_owner (service);
00332 
00333   <font class="keywordflow">if</font> (old_owner == NULL)
00334     {
00335       _dbus_assert (current_owner == connection);
00336 
00337       bus_service_set_prohibit_replacement (service,
00338                                             (flags &amp; DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT));      
00339                         
00340       *result = DBUS_SERVICE_REPLY_PRIMARY_OWNER;      
00341     }
00342   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (old_owner == connection)
00343     *result = DBUS_SERVICE_REPLY_ALREADY_OWNER;
00344   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (!((flags &amp; DBUS_SERVICE_FLAG_REPLACE_EXISTING)))
00345     *result = DBUS_SERVICE_REPLY_SERVICE_EXISTS;
00346   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (bus_service_get_prohibit_replacement (service))
00347     {
00348       <font class="comment">/* Queue the connection */</font>
00349       <font class="keywordflow">if</font> (!bus_service_add_owner (service, connection,
00350                                   transaction, error))
00351         <font class="keywordflow">goto</font> out;
00352       
00353       *result = DBUS_SERVICE_REPLY_IN_QUEUE;
00354     }
00355   <font class="keywordflow">else</font>
00356     {
00357       <font class="comment">/* Replace the current owner */</font>
00358 
00359       <font class="comment">/* We enqueue the new owner and remove the first one because</font>
00360 <font class="comment">       * that will cause ServiceAcquired and ServiceLost messages to</font>
00361 <font class="comment">       * be sent.</font>
00362 <font class="comment">       */</font>
00363       
00364       <font class="keywordflow">if</font> (!bus_service_add_owner (service, connection,
00365                                   transaction, error))
00366         <font class="keywordflow">goto</font> out;
00367 
00368       <font class="keywordflow">if</font> (!bus_service_remove_owner (service, old_owner,
00369                                      transaction, error))
00370         <font class="keywordflow">goto</font> out;
00371       
00372       _dbus_assert (connection == bus_service_get_primary_owner (service));
00373       *result = DBUS_SERVICE_REPLY_PRIMARY_OWNER;
00374     }
00375 
00376   retval = TRUE;
00377   
00378  out:
00379   <font class="keywordflow">return</font> retval;
00380 }
00381 
00382 <font class="keyword">static</font> <font class="keywordtype">void</font>
00383 bus_service_unlink_owner (BusService      *service,
00384                           <a class="code" href="structDBusConnection.html">DBusConnection</a>  *owner)
00385 {
00386   _dbus_list_remove_last (&amp;service-&gt;owners, owner);
00387   bus_connection_remove_owned_service (owner, service);
00388 }
00389 
00390 <font class="keyword">static</font> <font class="keywordtype">void</font>
00391 bus_service_unlink (BusService *service)
00392 {
00393   _dbus_assert (service-&gt;owners == NULL);
00394 
00395   <font class="comment">/* the service may not be in the hash, if</font>
00396 <font class="comment">   * the failure causing transaction cancel</font>
00397 <font class="comment">   * was in the right place, but that's OK</font>
00398 <font class="comment">   */</font>
00399   _dbus_hash_table_remove_string (service-&gt;registry-&gt;service_hash,
00400                                   service-&gt;name);
00401   
00402   bus_service_unref (service);
00403 }
00404 
00405 <font class="keyword">static</font> <font class="keywordtype">void</font>
00406 bus_service_relink (BusService           *service,
00407                     DBusPreallocatedHash *preallocated)
00408 {
00409   _dbus_assert (service-&gt;owners == NULL);
00410   _dbus_assert (preallocated != NULL);
00411 
00412   _dbus_hash_table_insert_string_preallocated (service-&gt;registry-&gt;service_hash,
00413                                                preallocated,
00414                                                service-&gt;name,
00415                                                service);
00416   
00417   bus_service_ref (service);
00418 }
00419 
<a name="l00424"></a><a class="code" href="structOwnershipCancelData.html">00424</a> <font class="keyword">typedef</font> <font class="keyword">struct</font>
00425 <font class="keyword"></font>{
<a name="l00426"></a><a class="code" href="structOwnershipCancelData.html#m0">00426</a>   <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection; 
<a name="l00427"></a><a class="code" href="structOwnershipCancelData.html#m1">00427</a>   BusService *service;        
00428 } <a class="code" href="structOwnershipCancelData.html">OwnershipCancelData</a>;
00429 
00430 <font class="keyword">static</font> <font class="keywordtype">void</font>
00431 cancel_ownership (<font class="keywordtype">void</font> *data)
00432 {
00433   <a class="code" href="structOwnershipCancelData.html">OwnershipCancelData</a> *d = data;
00434 
00435   <font class="comment">/* We don't need to send messages notifying of these</font>
00436 <font class="comment">   * changes, since we're reverting something that was</font>
00437 <font class="comment">   * cancelled (effectively never really happened)</font>
00438 <font class="comment">   */</font>
00439   bus_service_unlink_owner (d-&gt;<a class="code" href="structOwnershipCancelData.html#m1">service</a>, d-&gt;<a class="code" href="structOwnershipCancelData.html#m0">connection</a>);
00440   
00441   <font class="keywordflow">if</font> (d-&gt;<a class="code" href="structOwnershipCancelData.html#m1">service</a>-&gt;owners == NULL)
00442     bus_service_unlink (d-&gt;<a class="code" href="structOwnershipCancelData.html#m1">service</a>);
00443 }
00444 
00445 <font class="keyword">static</font> <font class="keywordtype">void</font>
00446 free_ownership_cancel_data (<font class="keywordtype">void</font> *data)
00447 {
00448   <a class="code" href="structOwnershipCancelData.html">OwnershipCancelData</a> *d = data;
00449 
00450   dbus_connection_unref (d-&gt;<a class="code" href="structOwnershipCancelData.html#m0">connection</a>);
00451   bus_service_unref (d-&gt;<a class="code" href="structOwnershipCancelData.html#m1">service</a>);
00452   
00453   dbus_free (d);
00454 }
00455 
00456 <font class="keyword">static</font> dbus_bool_t
00457 add_cancel_ownership_to_transaction (BusTransaction *transaction,
00458                                      BusService     *service,
00459                                      <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection)
00460 {
00461   <a class="code" href="structOwnershipCancelData.html">OwnershipCancelData</a> *d;
00462 
00463   d = dbus_new (<a class="code" href="structOwnershipCancelData.html">OwnershipCancelData</a>, 1);
00464   <font class="keywordflow">if</font> (d == NULL)
00465     <font class="keywordflow">return</font> FALSE;
00466   
00467   d-&gt;<a class="code" href="structOwnershipCancelData.html#m1">service</a> = service;
00468   d-&gt;<a class="code" href="structOwnershipCancelData.html#m0">connection</a> = connection;
00469 
00470   <font class="keywordflow">if</font> (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
00471                                         free_ownership_cancel_data))
00472     {
00473       dbus_free (d);
00474       <font class="keywordflow">return</font> FALSE;
00475     }
00476 
00477   bus_service_ref (d-&gt;<a class="code" href="structOwnershipCancelData.html#m1">service</a>);
00478   dbus_connection_ref (d-&gt;<a class="code" href="structOwnershipCancelData.html#m0">connection</a>);
00479   
00480   <font class="keywordflow">return</font> TRUE;
00481 }
00482 
00483 <font class="comment">/* this function is self-cancelling if you cancel the transaction */</font>
00484 dbus_bool_t
00485 bus_service_add_owner (BusService     *service,
00486                        <a class="code" href="structDBusConnection.html">DBusConnection</a> *owner,
00487                        BusTransaction *transaction,
00488                        <a class="code" href="structDBusError.html">DBusError</a>      *error)
00489 {
00490   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00491   
00492  <font class="comment">/* Send service acquired message first, OOM will result</font>
00493 <font class="comment">  * in cancelling the transaction</font>
00494 <font class="comment">  */</font>
00495   <font class="keywordflow">if</font> (service-&gt;owners == NULL)
00496     {
00497       <font class="keywordflow">if</font> (!bus_driver_send_service_acquired (owner, service-&gt;name, transaction, error))
00498         <font class="keywordflow">return</font> FALSE;
00499     }
00500   
00501   <font class="keywordflow">if</font> (!_dbus_list_append (&amp;service-&gt;owners,
00502                           owner))
00503     {
00504       BUS_SET_OOM (error);
00505       <font class="keywordflow">return</font> FALSE;
00506     }
00507 
00508   <font class="keywordflow">if</font> (!bus_connection_add_owned_service (owner, service))
00509     {
00510       _dbus_list_remove_last (&amp;service-&gt;owners, owner);
00511       BUS_SET_OOM (error);
00512       <font class="keywordflow">return</font> FALSE;
00513     }
00514 
00515   <font class="keywordflow">if</font> (!add_cancel_ownership_to_transaction (transaction,
00516                                             service,
00517                                             owner))
00518     {
00519       bus_service_unlink_owner (service, owner);
00520       BUS_SET_OOM (error);
00521       <font class="keywordflow">return</font> FALSE;
00522     }
00523   
00524   <font class="keywordflow">return</font> TRUE;
00525 }
00526 
00527 <font class="keyword">typedef</font> <font class="keyword">struct</font>
00528 <font class="keyword"></font>{
00529   <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection;
00530   BusService     *service;
00531   <a class="code" href="structDBusConnection.html">DBusConnection</a> *before_connection; <font class="comment">/* restore to position before this connection in owners list */</font>
00532   <a class="code" href="structDBusList.html">DBusList</a>       *connection_link;
00533   <a class="code" href="structDBusList.html">DBusList</a>       *service_link;
00534   DBusPreallocatedHash *hash_entry;
00535 } OwnershipRestoreData;
00536 
00537 <font class="keyword">static</font> <font class="keywordtype">void</font>
00538 restore_ownership (<font class="keywordtype">void</font> *data)
00539 {
00540   OwnershipRestoreData *d = data;
00541   <a class="code" href="structDBusList.html">DBusList</a> *link;
00542 
00543   _dbus_assert (d-&gt;service_link != NULL);
00544   _dbus_assert (d-&gt;connection_link != NULL);
00545   
00546   <font class="keywordflow">if</font> (d-&gt;service-&gt;owners == NULL)
00547     {
00548       _dbus_assert (d-&gt;hash_entry != NULL);
00549       bus_service_relink (d-&gt;service, d-&gt;hash_entry);
00550     }
00551   <font class="keywordflow">else</font>
00552     {
00553       _dbus_assert (d-&gt;hash_entry == NULL);
00554     }
00555   
00556   <font class="comment">/* We don't need to send messages notifying of these</font>
00557 <font class="comment">   * changes, since we're reverting something that was</font>
00558 <font class="comment">   * cancelled (effectively never really happened)</font>
00559 <font class="comment">   */</font>
00560   link = _dbus_list_get_first_link (&amp;d-&gt;service-&gt;owners);
00561   <font class="keywordflow">while</font> (link != NULL)
00562     {
00563       <font class="keywordflow">if</font> (link-&gt;<a class="code" href="structDBusList.html#m2">data</a> == d-&gt;before_connection)
00564         <font class="keywordflow">break</font>;
00565 
00566       link = _dbus_list_get_next_link (&amp;d-&gt;service-&gt;owners, link);
00567     }
00568   
00569   _dbus_list_insert_before_link (&amp;d-&gt;service-&gt;owners, link, d-&gt;connection_link);
00570 
00571   <font class="comment">/* Note that removing then restoring this changes the order in which</font>
00572 <font class="comment">   * ServiceDeleted messages are sent on destruction of the</font>
00573 <font class="comment">   * connection.  This should be OK as the only guarantee there is</font>
00574 <font class="comment">   * that the base service is destroyed last, and we never even</font>
00575 <font class="comment">   * tentatively remove the base service.</font>
00576 <font class="comment">   */</font>
00577   bus_connection_add_owned_service_link (d-&gt;connection, d-&gt;service_link);
00578   
00579   d-&gt;hash_entry = NULL;
00580   d-&gt;service_link = NULL;
00581   d-&gt;connection_link = NULL;
00582 }
00583 
00584 <font class="keyword">static</font> <font class="keywordtype">void</font>
00585 free_ownership_restore_data (<font class="keywordtype">void</font> *data)
00586 {
00587   OwnershipRestoreData *d = data;
00588 
00589   <font class="keywordflow">if</font> (d-&gt;service_link)
00590     _dbus_list_free_link (d-&gt;service_link);
00591   <font class="keywordflow">if</font> (d-&gt;connection_link)
00592     _dbus_list_free_link (d-&gt;connection_link);
00593   <font class="keywordflow">if</font> (d-&gt;hash_entry)
00594     _dbus_hash_table_free_preallocated_entry (d-&gt;service-&gt;registry-&gt;service_hash,
00595                                               d-&gt;hash_entry);
00596 
00597   dbus_connection_unref (d-&gt;connection);
00598   bus_service_unref (d-&gt;service);
00599   
00600   dbus_free (d);
00601 }
00602 
00603 <font class="keyword">static</font> dbus_bool_t
00604 add_restore_ownership_to_transaction (BusTransaction *transaction,
00605                                       BusService     *service,
00606                                       <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection)
00607 {
00608   OwnershipRestoreData *d;
00609   <a class="code" href="structDBusList.html">DBusList</a> *link;
00610 
00611   d = dbus_new (OwnershipRestoreData, 1);
00612   <font class="keywordflow">if</font> (d == NULL)
00613     <font class="keywordflow">return</font> FALSE;
00614   
00615   d-&gt;service = service;
00616   d-&gt;connection = connection;
00617   d-&gt;service_link = _dbus_list_alloc_link (service);
00618   d-&gt;connection_link = _dbus_list_alloc_link (connection);
00619   d-&gt;hash_entry = _dbus_hash_table_preallocate_entry (service-&gt;registry-&gt;service_hash);
00620   
00621   bus_service_ref (d-&gt;service);
00622   dbus_connection_ref (d-&gt;connection);
00623 
00624   d-&gt;before_connection = NULL;
00625   link = _dbus_list_get_first_link (&amp;service-&gt;owners);
00626   <font class="keywordflow">while</font> (link != NULL)
00627     {
00628       <font class="keywordflow">if</font> (link-&gt;<a class="code" href="structDBusList.html#m2">data</a> == connection)
00629         {
00630           link = _dbus_list_get_next_link (&amp;service-&gt;owners, link);
00631 
00632           <font class="keywordflow">if</font> (link)
00633             d-&gt;before_connection = link-&gt;<a class="code" href="structDBusList.html#m2">data</a>;
00634 
00635           <font class="keywordflow">break</font>;
00636         }
00637       
00638       link = _dbus_list_get_next_link (&amp;service-&gt;owners, link);
00639     }
00640   
00641   <font class="keywordflow">if</font> (d-&gt;service_link == NULL ||
00642       d-&gt;connection_link == NULL ||
00643       d-&gt;hash_entry == NULL ||
00644       !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
00645                                         free_ownership_restore_data))
00646     {
00647       free_ownership_restore_data (d);
00648       <font class="keywordflow">return</font> FALSE;
00649     }
00650   
00651   <font class="keywordflow">return</font> TRUE;
00652 }
00653 
00654 <font class="comment">/* this function is self-cancelling if you cancel the transaction */</font>
00655 dbus_bool_t
00656 bus_service_remove_owner (BusService     *service,
00657                           <a class="code" href="structDBusConnection.html">DBusConnection</a> *owner,
00658                           BusTransaction *transaction,
00659                           <a class="code" href="structDBusError.html">DBusError</a>      *error)
00660 {
00661   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00662   
00663   <font class="comment">/* We send out notifications before we do any work we</font>
00664 <font class="comment">   * might have to undo if the notification-sending failed</font>
00665 <font class="comment">   */</font>
00666   
00667   <font class="comment">/* Send service lost message */</font>
00668   <font class="keywordflow">if</font> (bus_service_get_primary_owner (service) == owner)
00669     {
00670       <font class="keywordflow">if</font> (!bus_driver_send_service_lost (owner, service-&gt;name,
00671                                          transaction, error))
00672         <font class="keywordflow">return</font> FALSE;
00673     }
00674 
00675   <font class="keywordflow">if</font> (service-&gt;owners == NULL)
00676     {
00677       _dbus_assert_not_reached (<font class="stringliteral">"Tried to remove owner of a service that has no owners"</font>);
00678     }
00679   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (_dbus_list_length_is_one (&amp;service-&gt;owners))
00680     {
00681       <font class="keywordflow">if</font> (!bus_driver_send_service_deleted (service-&gt;name,
00682                                             transaction, error))
00683         <font class="keywordflow">return</font> FALSE;
00684     }
00685   <font class="keywordflow">else</font>
00686     {
00687       <a class="code" href="structDBusList.html">DBusList</a> *link;
00688       link = _dbus_list_get_first (&amp;service-&gt;owners);
00689       _dbus_assert (link != NULL);
00690       link = _dbus_list_get_next_link (&amp;service-&gt;owners, link);
00691 
00692       _dbus_assert (link != NULL);
00693 
00694       <font class="comment">/* This will be our new owner */</font>
00695       <font class="keywordflow">if</font> (!bus_driver_send_service_acquired (link-&gt;<a class="code" href="structDBusList.html#m2">data</a>,
00696                                              service-&gt;name,
00697                                              transaction,
00698                                              error))
00699         <font class="keywordflow">return</font> FALSE;
00700     }
00701 
00702   <font class="keywordflow">if</font> (!add_restore_ownership_to_transaction (transaction, service, owner))
00703     {
00704       BUS_SET_OOM (error);
00705       <font class="keywordflow">return</font> FALSE;
00706     }
00707   
00708   bus_service_unlink_owner (service, owner);
00709 
00710   <font class="keywordflow">if</font> (service-&gt;owners == NULL)
00711     bus_service_unlink (service);
00712 
00713   <font class="keywordflow">return</font> TRUE;
00714 }
00715 
00716 <font class="keywordtype">void</font>
00717 bus_service_ref (BusService *service)
00718 {
00719   _dbus_assert (service-&gt;refcount &gt; 0);
00720   
00721   service-&gt;refcount += 1;
00722 }
00723 
00724 <font class="keywordtype">void</font>
00725 bus_service_unref (BusService *service)
00726 {
00727   _dbus_assert (service-&gt;refcount &gt; 0);
00728   
00729   service-&gt;refcount -= 1;
00730 
00731   <font class="keywordflow">if</font> (service-&gt;refcount == 0)
00732     {
00733       _dbus_assert (service-&gt;owners == NULL);
00734       
00735       dbus_free (service-&gt;name);
00736       _dbus_mem_pool_dealloc (service-&gt;registry-&gt;service_pool, service);
00737     }
00738 }
00739 
00740 <a class="code" href="structDBusConnection.html">DBusConnection</a>*
00741 bus_service_get_primary_owner (BusService *service)
00742 {
00743   <font class="keywordflow">return</font> _dbus_list_get_first (&amp;service-&gt;owners);
00744 }
00745 
00746 <font class="keyword">const</font> <font class="keywordtype">char</font>*
00747 bus_service_get_name (BusService *service)
00748 {
00749   <font class="keywordflow">return</font> service-&gt;name;
00750 }
00751 
00752 <font class="keywordtype">void</font>
00753 bus_service_set_prohibit_replacement (BusService  *service,
00754                                       dbus_bool_t  prohibit_replacement)
00755 {
00756   service-&gt;prohibit_replacement = prohibit_replacement != FALSE;
00757 }
00758 
00759 dbus_bool_t
00760 bus_service_get_prohibit_replacement (BusService *service)
00761 {
00762   <font class="keywordflow">return</font> service-&gt;prohibit_replacement;
00763 }
00764 
00765 dbus_bool_t
00766 bus_service_has_owner (BusService     *service,
00767                        <a class="code" href="structDBusConnection.html">DBusConnection</a> *owner)
00768 {
00769   <a class="code" href="structDBusList.html">DBusList</a> *link;
00770 
00771   link = _dbus_list_get_first_link (&amp;service-&gt;owners);
00772   
00773   <font class="keywordflow">while</font> (link != NULL)
00774     {
00775       <font class="keywordflow">if</font> (link-&gt;<a class="code" href="structDBusList.html#m2">data</a> == owner)
00776         <font class="keywordflow">return</font> TRUE;
00777       
00778       link = _dbus_list_get_next_link (&amp;service-&gt;owners, link);
00779     }
00780 
00781   <font class="keywordflow">return</font> FALSE;
00782 }
</pre></div><hr><address align="right"><small>Generated on Mon Sep 29 21:31:02 2003 for D-BUS by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 
width=110 height=53></a>1.2.15 </small></address>
</body>
</html>