<!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> <a class="qindex" href="modules.html">Modules</a> <a class="qindex" href="annotated.html">Data Structures</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="functions.html">Data Fields</a> <a class="qindex" href="pages.html">Related Pages</a> </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 <dbus/dbus-hash.h></font> 00025 <font class="preprocessor">#include <dbus/dbus-list.h></font> 00026 <font class="preprocessor">#include <dbus/dbus-mempool.h></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->refcount = 1; 00066 registry->context = context; 00067 00068 registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING, 00069 NULL, NULL); 00070 <font class="keywordflow">if</font> (registry->service_hash == NULL) 00071 <font class="keywordflow">goto</font> failed; 00072 00073 registry->service_pool = _dbus_mem_pool_new (<font class="keyword">sizeof</font> (BusService), 00074 TRUE); 00075 <font class="keywordflow">if</font> (registry->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->refcount > 0); 00089 registry->refcount += 1; 00090 } 00091 00092 <font class="keywordtype">void</font> 00093 bus_registry_unref (BusRegistry *registry) 00094 { 00095 _dbus_assert (registry->refcount > 0); 00096 registry->refcount -= 1; 00097 00098 <font class="keywordflow">if</font> (registry->refcount == 0) 00099 { 00100 <font class="keywordflow">if</font> (registry->service_hash) 00101 _dbus_hash_table_unref (registry->service_hash); 00102 <font class="keywordflow">if</font> (registry->service_pool) 00103 _dbus_mem_pool_free (registry->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->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->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->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->registry = registry; 00148 service->refcount = 1; 00149 00150 <font class="keywordflow">if</font> (!_dbus_string_copy_data (service_name, &service->name)) 00151 { 00152 _dbus_mem_pool_dealloc (registry->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->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->context), 00164 service->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->service_hash, 00178 service->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->service_hash, &iter); 00197 <font class="keywordflow">while</font> (_dbus_hash_iter_next (&iter)) 00198 { 00199 BusService *service = _dbus_hash_iter_get_value (&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->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->service_hash, &iter); 00221 i = 0; 00222 <font class="keywordflow">while</font> (_dbus_hash_iter_next (&iter)) 00223 { 00224 BusService *service = _dbus_hash_iter_get_value (&iter); 00225 00226 retval[i] = _dbus_strdup (service->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 < 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) >= 00305 bus_context_get_max_services_per_connection (registry->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 & 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 & 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 (&service->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->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->registry->service_hash, 00400 service->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->owners == NULL); 00410 _dbus_assert (preallocated != NULL); 00411 00412 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash, 00413 preallocated, 00414 service->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-><a class="code" href="structOwnershipCancelData.html#m1">service</a>, d-><a class="code" href="structOwnershipCancelData.html#m0">connection</a>); 00440 00441 <font class="keywordflow">if</font> (d-><a class="code" href="structOwnershipCancelData.html#m1">service</a>->owners == NULL) 00442 bus_service_unlink (d-><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-><a class="code" href="structOwnershipCancelData.html#m0">connection</a>); 00451 bus_service_unref (d-><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-><a class="code" href="structOwnershipCancelData.html#m1">service</a> = service; 00468 d-><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-><a class="code" href="structOwnershipCancelData.html#m1">service</a>); 00478 dbus_connection_ref (d-><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->owners == NULL) 00496 { 00497 <font class="keywordflow">if</font> (!bus_driver_send_service_acquired (owner, service->name, transaction, error)) 00498 <font class="keywordflow">return</font> FALSE; 00499 } 00500 00501 <font class="keywordflow">if</font> (!_dbus_list_append (&service->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 (&service->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->service_link != NULL); 00544 _dbus_assert (d->connection_link != NULL); 00545 00546 <font class="keywordflow">if</font> (d->service->owners == NULL) 00547 { 00548 _dbus_assert (d->hash_entry != NULL); 00549 bus_service_relink (d->service, d->hash_entry); 00550 } 00551 <font class="keywordflow">else</font> 00552 { 00553 _dbus_assert (d->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 (&d->service->owners); 00561 <font class="keywordflow">while</font> (link != NULL) 00562 { 00563 <font class="keywordflow">if</font> (link-><a class="code" href="structDBusList.html#m2">data</a> == d->before_connection) 00564 <font class="keywordflow">break</font>; 00565 00566 link = _dbus_list_get_next_link (&d->service->owners, link); 00567 } 00568 00569 _dbus_list_insert_before_link (&d->service->owners, link, d->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->connection, d->service_link); 00578 00579 d->hash_entry = NULL; 00580 d->service_link = NULL; 00581 d->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->service_link) 00590 _dbus_list_free_link (d->service_link); 00591 <font class="keywordflow">if</font> (d->connection_link) 00592 _dbus_list_free_link (d->connection_link); 00593 <font class="keywordflow">if</font> (d->hash_entry) 00594 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash, 00595 d->hash_entry); 00596 00597 dbus_connection_unref (d->connection); 00598 bus_service_unref (d->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->service = service; 00616 d->connection = connection; 00617 d->service_link = _dbus_list_alloc_link (service); 00618 d->connection_link = _dbus_list_alloc_link (connection); 00619 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash); 00620 00621 bus_service_ref (d->service); 00622 dbus_connection_ref (d->connection); 00623 00624 d->before_connection = NULL; 00625 link = _dbus_list_get_first_link (&service->owners); 00626 <font class="keywordflow">while</font> (link != NULL) 00627 { 00628 <font class="keywordflow">if</font> (link-><a class="code" href="structDBusList.html#m2">data</a> == connection) 00629 { 00630 link = _dbus_list_get_next_link (&service->owners, link); 00631 00632 <font class="keywordflow">if</font> (link) 00633 d->before_connection = link-><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 (&service->owners, link); 00639 } 00640 00641 <font class="keywordflow">if</font> (d->service_link == NULL || 00642 d->connection_link == NULL || 00643 d->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->name, 00671 transaction, error)) 00672 <font class="keywordflow">return</font> FALSE; 00673 } 00674 00675 <font class="keywordflow">if</font> (service->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 (&service->owners)) 00680 { 00681 <font class="keywordflow">if</font> (!bus_driver_send_service_deleted (service->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 (&service->owners); 00689 _dbus_assert (link != NULL); 00690 link = _dbus_list_get_next_link (&service->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-><a class="code" href="structDBusList.html#m2">data</a>, 00696 service->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->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->refcount > 0); 00720 00721 service->refcount += 1; 00722 } 00723 00724 <font class="keywordtype">void</font> 00725 bus_service_unref (BusService *service) 00726 { 00727 _dbus_assert (service->refcount > 0); 00728 00729 service->refcount -= 1; 00730 00731 <font class="keywordflow">if</font> (service->refcount == 0) 00732 { 00733 _dbus_assert (service->owners == NULL); 00734 00735 dbus_free (service->name); 00736 _dbus_mem_pool_dealloc (service->registry->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 (&service->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->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->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->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 (&service->owners); 00772 00773 <font class="keywordflow">while</font> (link != NULL) 00774 { 00775 <font class="keywordflow">if</font> (link-><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 (&service->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>