diff options
Diffstat (limited to 'dbus')
92 files changed, 3519 insertions, 1997 deletions
diff --git a/dbus/.gitignore b/dbus/.gitignore index 34eace4d..fd91ccee 100644 --- a/dbus/.gitignore +++ b/dbus/.gitignore @@ -4,7 +4,7 @@ Makefile Makefile.in *.lo *.la -dbus-test +test-dbus *.bb *.bbg *.gcov diff --git a/dbus/Makefile.am b/dbus/Makefile.am index bb5cccaf..b2481073 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -12,6 +12,10 @@ AM_CPPFLAGS = \ -DDBUS_SESSION_CONFIG_FILE=\""$(configdir)/session.conf"\" \ $(NULL) +# On Linux with glibc 2.17, sd-daemon.c support for POSIX message queues +# results in an otherwise unnecessary dependency on librt. Disable it. +AM_CPPFLAGS += -DSD_DAEMON_DISABLE_MQ + # if assertions are enabled, improve backtraces AM_LDFLAGS = @R_DYNAMIC_LDFLAG@ @@ -35,7 +39,7 @@ dbus_res_ldflag = -Wl,$(dbus_res) no_undefined = -no-undefined export_symbols = -libdbus_1_la_DEPENDENCIES = $(dbus_res) +EXTRA_libdbus_1_la_DEPENDENCIES = $(dbus_res) intllibs = else @@ -233,6 +237,8 @@ DBUS_SHARED_SOURCES= \ ### should be underscore-prefixed but don't really need ### to be unless they move to DBUS_SHARED_SOURCES later) DBUS_UTIL_SOURCES= \ + dbus-asv-util.c \ + dbus-asv-util.h \ dbus-auth-script.c \ dbus-auth-script.h \ dbus-auth-util.c \ @@ -291,22 +297,33 @@ libdbus_internal_la_CPPFLAGS = \ $(NULL) libdbus_internal_la_LIBADD=$(LIBDBUS_LIBS) $(SYSTEMD_LIBS) +if DBUS_WIN +# This must be a separate convenience library, otherwise libtool notices +# that libdbus-1 might contain C++, links it with g++ and links in libstdc++, +# even on Unix where in fact it doesn't contain any C++. For Windows, where +# this code is used, we don't actually need libstdc++. +noinst_LTLIBRARIES += libdbus-init-win.la +libdbus_init_win_la_SOURCES = dbus-init-win.cpp +libdbus_1_la_LIBADD += libdbus-init-win.la +libdbus_internal_la_LIBADD += libdbus-init-win.la +endif + noinst_PROGRAMS = -if DBUS_BUILD_TESTS +if DBUS_ENABLE_EMBEDDED_TESTS # We can't actually run this til we've reached test/ -noinst_PROGRAMS += dbus-test +noinst_PROGRAMS += test-dbus endif -dbus_test_SOURCES= \ +test_dbus_SOURCES= \ dbus-test-main.c -dbus_test_LDADD = libdbus-internal.la +test_dbus_LDADD = libdbus-internal.la ## mop up the gcov files clean-local: /bin/rm *.bb *.bbg *.da *.gcov .libs/*.da .libs/*.bbg || true update-systemd: - curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c > sd-daemon.c - curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h > sd-daemon.h + curl http://cgit.freedesktop.org/systemd/systemd/plain/src/libsystemd-daemon/sd-daemon.c > $(srcdir)/sd-daemon.c + curl http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h > $(srcdir)/sd-daemon.h diff --git a/dbus/dbus-address.c b/dbus/dbus-address.c index 90484dc1..c4cfbbe5 100644 --- a/dbus/dbus-address.c +++ b/dbus/dbus-address.c @@ -104,15 +104,15 @@ dbus_bool_t _dbus_address_append_escaped (DBusString *escaped, const DBusString *unescaped) { - const char *p; - const char *end; + const unsigned char *p; + const unsigned char *end; dbus_bool_t ret; int orig_len; ret = FALSE; orig_len = _dbus_string_get_length (escaped); - p = _dbus_string_get_const_data (unescaped); + p = (const unsigned char *) _dbus_string_get_const_data (unescaped); end = p + _dbus_string_get_length (unescaped); while (p != end) { @@ -648,7 +648,7 @@ dbus_address_unescape_value (const char *value, /** @} */ /* End of public API */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -678,7 +678,9 @@ static const EscapeTest escape_tests[] = { { "Z", "Z" }, { "a", "a" }, { "i", "i" }, - { "z", "z" } + { "z", "z" }, + /* Bug: https://bugs.freedesktop.org/show_bug.cgi?id=53499 */ + { "%c3%b6", "\xc3\xb6" } }; static const char* invalid_escaped_values[] = { diff --git a/dbus/dbus-arch-deps.h.in b/dbus/dbus-arch-deps.h.in index 45952cfb..dfc3589e 100644 --- a/dbus/dbus-arch-deps.h.in +++ b/dbus/dbus-arch-deps.h.in @@ -31,7 +31,7 @@ DBUS_BEGIN_DECLS -#if @DBUS_HAVE_INT64@ +/* D-Bus no longer supports platforms with no 64-bit integer type. */ #define DBUS_HAVE_INT64 1 _DBUS_GNUC_EXTENSION typedef @DBUS_INT64_TYPE@ dbus_int64_t; _DBUS_GNUC_EXTENSION typedef unsigned @DBUS_INT64_TYPE@ dbus_uint64_t; @@ -39,12 +39,6 @@ _DBUS_GNUC_EXTENSION typedef unsigned @DBUS_INT64_TYPE@ dbus_uint64_t; #define DBUS_INT64_CONSTANT(val) (_DBUS_GNUC_EXTENSION @DBUS_INT64_CONSTANT@) #define DBUS_UINT64_CONSTANT(val) (_DBUS_GNUC_EXTENSION @DBUS_UINT64_CONSTANT@) -#else -#undef DBUS_HAVE_INT64 -#undef DBUS_INT64_CONSTANT -#undef DBUS_UINT64_CONSTANT -#endif - typedef @DBUS_INT32_TYPE@ dbus_int32_t; typedef unsigned @DBUS_INT32_TYPE@ dbus_uint32_t; diff --git a/dbus/dbus-asv-util.c b/dbus/dbus-asv-util.c new file mode 100644 index 00000000..583e41fa --- /dev/null +++ b/dbus/dbus-asv-util.c @@ -0,0 +1,260 @@ +/* dbus-asv-util.c - utility functions for a{sv} + * + * Copyright © 2011-2012 Nokia Corporation + * Copyright © 2012-2013 Collabora Ltd. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include <config.h> + +#include <dbus/dbus.h> + +#include "dbus/dbus-asv-util.h" + +/** + * Convenience function to create a method-call reply whose type is a{sv} + * (map from string to variant). + * + * Append values with 0 or more sequences of _dbus_asv_open_entry(), + * appending a value to var_iter, and _dbus_asv_close_entry(), + * then close the a{sv} with _dbus_asv_close() or _dbus_asv_abandon(). + * + * This must be paired with a call to _dbus_asv_close() or _dbus_asv_abandon(). + * + * @param message a method call message + * @param iter an iterator which will be initialized to append to the message + * @param arr_iter an iterator which will be initialized to append to the array + * @returns a new message, or #NULL if not enough memory + */ +DBusMessage * +_dbus_asv_new_method_return (DBusMessage *message, + DBusMessageIter *iter, + DBusMessageIter *arr_iter) +{ + DBusMessage *reply = dbus_message_new_method_return (message); + + if (reply == NULL) + return NULL; + + dbus_message_iter_init_append (reply, iter); + + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{sv}", + arr_iter)) + { + dbus_message_unref (reply); + return NULL; + } + + return reply; +} + +/* + * Open a new entry in an a{sv} (map from string to variant). + * + * This must be paired with a call to either _dbus_asv_close_entry() + * or _dbus_asv_abandon_entry(). + * + * If this function fails, the a{sv} must be abandoned, for instance + * with _dbus_asv_abandon(). + * + * @param arr_iter the iterator which is appending to the array + * @param entry_iter will be initialized to append to the dict-entry + * @param key a UTF-8 key for the map + * @param type the type of the variant value, e.g. DBUS_TYPE_STRING_AS_STRING + * @param var_iter will be initialized to append (i.e. write) to the variant + * @returns #TRUE on success, or #FALSE if not enough memory + */ +static dbus_bool_t +_dbus_asv_open_entry (DBusMessageIter *arr_iter, + DBusMessageIter *entry_iter, + const char *key, + const char *type, + DBusMessageIter *var_iter) +{ + if (!dbus_message_iter_open_container (arr_iter, DBUS_TYPE_DICT_ENTRY, + NULL, entry_iter)) + return FALSE; + + if (!dbus_message_iter_append_basic (entry_iter, DBUS_TYPE_STRING, &key)) + { + dbus_message_iter_abandon_container (arr_iter, entry_iter); + return FALSE; + } + + if (!dbus_message_iter_open_container (entry_iter, DBUS_TYPE_VARIANT, + type, var_iter)) + { + dbus_message_iter_abandon_container (arr_iter, entry_iter); + return FALSE; + } + + return TRUE; +} + +/* + * Closes an a{sv} entry after successfully appending the value. + * + * If this function fails, the a{sv} must be abandoned, for instance + * with _dbus_asv_abandon(). + * + * @param arr_iter the iterator which is appending to the array + * @param entry_iter the iterator appending to the dict-entry, will be closed + * @param var_iter the iterator appending to the variant, will be closed + * @returns #TRUE on success, or #FALSE if not enough memory + */ +static dbus_bool_t +_dbus_asv_close_entry (DBusMessageIter *arr_iter, + DBusMessageIter *entry_iter, + DBusMessageIter *var_iter) +{ + if (!dbus_message_iter_close_container (entry_iter, var_iter)) + { + dbus_message_iter_abandon_container (arr_iter, entry_iter); + return FALSE; + } + + if (!dbus_message_iter_close_container (arr_iter, entry_iter)) + return FALSE; + + return TRUE; +} + +/** + * Closes an a{sv} after successfully appending all values. + * + * If this function fails, you must abandon iter and whatever + * larger data structure (message, etc.) the a{sv} was embedded in. + * + * @param iter the iterator which is appending to the message or other data structure containing the a{sv} + * @param arr_iter the iterator appending to the array, will be closed + * @returns #TRUE on success, or #FALSE if not enough memory + */ +dbus_bool_t +_dbus_asv_close (DBusMessageIter *iter, + DBusMessageIter *arr_iter) +{ + return dbus_message_iter_close_container (iter, arr_iter); +} + +/* + * Closes an a{sv} entry after unsuccessfully appending a value. + * You must also abandon the a{sv} itself (for instance with + * _dbus_asv_abandon()), and abandon whatever larger data structure + * the a{sv} was embedded in. + * + * @param iter the iterator which is appending to the message or other data structure containing the a{sv} + * @param arr_iter the iterator appending to the array, will be closed + * @returns #TRUE on success, or #FALSE if not enough memory + */ +static void +_dbus_asv_abandon_entry (DBusMessageIter *arr_iter, + DBusMessageIter *entry_iter, + DBusMessageIter *var_iter) +{ + dbus_message_iter_abandon_container (entry_iter, var_iter); + dbus_message_iter_abandon_container (arr_iter, entry_iter); +} + +/** + * Closes an a{sv} after unsuccessfully appending a value. + * + * You must also abandon whatever larger data structure (message, etc.) + * the a{sv} was embedded in. + * + * @param iter the iterator which is appending to the message or other data structure containing the a{sv} + * @param arr_iter the iterator appending to the array, will be closed + */ +void +_dbus_asv_abandon (DBusMessageIter *iter, + DBusMessageIter *arr_iter) +{ + dbus_message_iter_abandon_container (iter, arr_iter); +} + +/** + * Create a new entry in an a{sv} (map from string to variant) + * with a 32-bit unsigned integer value. + * + * If this function fails, the a{sv} must be abandoned, for instance + * with _dbus_asv_abandon(). + * + * @param arr_iter the iterator which is appending to the array + * @param key a UTF-8 key for the map + * @param value the value + * @returns #TRUE on success, or #FALSE if not enough memory + */ +dbus_bool_t +_dbus_asv_add_uint32 (DBusMessageIter *arr_iter, + const char *key, + dbus_uint32_t value) +{ + DBusMessageIter entry_iter, var_iter; + + if (!_dbus_asv_open_entry (arr_iter, &entry_iter, key, + DBUS_TYPE_UINT32_AS_STRING, &var_iter)) + return FALSE; + + if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UINT32, + &value)) + { + _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter); + return FALSE; + } + + if (!_dbus_asv_close_entry (arr_iter, &entry_iter, &var_iter)) + return FALSE; + + return TRUE; +} + +/** + * Create a new entry in an a{sv} (map from string to variant) + * with a UTF-8 string value. + * + * If this function fails, the a{sv} must be abandoned, for instance + * with _dbus_asv_abandon(). + * + * @param arr_iter the iterator which is appending to the array + * @param key a UTF-8 key for the map + * @param value the value + * @returns #TRUE on success, or #FALSE if not enough memory + */ +dbus_bool_t +_dbus_asv_add_string (DBusMessageIter *arr_iter, + const char *key, + const char *value) +{ + DBusMessageIter entry_iter, var_iter; + + if (!_dbus_asv_open_entry (arr_iter, &entry_iter, key, + DBUS_TYPE_STRING_AS_STRING, &var_iter)) + return FALSE; + + if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_STRING, + &value)) + { + _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter); + return FALSE; + } + + if (!_dbus_asv_close_entry (arr_iter, &entry_iter, &var_iter)) + return FALSE; + + return TRUE; +} diff --git a/dbus/dbus-asv-util.h b/dbus/dbus-asv-util.h new file mode 100644 index 00000000..0337260a --- /dev/null +++ b/dbus/dbus-asv-util.h @@ -0,0 +1,46 @@ +/* dbus-asv-util.h - utility functions for a{sv} + * + * Copyright © 2011-2012 Nokia Corporation + * Copyright © 2012-2013 Collabora Ltd. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef DBUS_ASV_UTIL_H +#define DBUS_ASV_UTIL_H + +#include <dbus/dbus-internals.h> + +DBUS_BEGIN_DECLS + +DBusMessage *_dbus_asv_new_method_return (DBusMessage *message, + DBusMessageIter *iter, + DBusMessageIter *arr_iter); +dbus_bool_t _dbus_asv_close (DBusMessageIter *iter, + DBusMessageIter *arr_iter); +void _dbus_asv_abandon (DBusMessageIter *iter, + DBusMessageIter *arr_iter); + +dbus_bool_t _dbus_asv_add_uint32 (DBusMessageIter *arr_iter, + const char *key, + dbus_uint32_t value); +dbus_bool_t _dbus_asv_add_string (DBusMessageIter *arr_iter, + const char *key, + const char *value); + +#endif diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c index 6285e3ba..164743b0 100644 --- a/dbus/dbus-auth-script.c +++ b/dbus/dbus-auth-script.c @@ -22,7 +22,7 @@ */ #include <config.h> -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-auth-script.h" #include "dbus-auth.h" @@ -223,7 +223,7 @@ auth_set_unix_credentials(DBusAuth *auth, if (uid != DBUS_UID_UNSET) _dbus_credentials_add_unix_uid (credentials, uid); if (pid != DBUS_PID_UNSET) - _dbus_credentials_add_unix_pid (credentials, pid); + _dbus_credentials_add_pid (credentials, pid); _dbus_auth_set_credentials (auth, credentials); @@ -584,11 +584,11 @@ _dbus_auth_script_run (const DBusString *filename) { _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n"); _dbus_string_free (&to_send); - _dbus_auth_return_buffer (auth, buffer, 0); + _dbus_auth_return_buffer (auth, buffer); goto out; } - _dbus_auth_return_buffer (auth, buffer, _dbus_string_get_length (&to_send)); + _dbus_auth_return_buffer (auth, buffer); } _dbus_string_free (&to_send); @@ -800,4 +800,4 @@ _dbus_auth_script_run (const DBusString *filename) } /** @} */ -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-auth-util.c b/dbus/dbus-auth-util.c index 776e8e27..e88d6696 100644 --- a/dbus/dbus-auth-util.c +++ b/dbus/dbus-auth-util.c @@ -33,7 +33,7 @@ /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include "dbus-auth-script.h" #include <stdio.h> @@ -167,4 +167,4 @@ _dbus_auth_test (const char *test_data_dir) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index d2c37a7a..6a07665f 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -2238,8 +2238,8 @@ process_command (DBusAuth *auth) /** * Creates a new auth conversation object for the server side. - * See doc/dbus-sasl-profile.txt for full details on what - * this object does. + * See http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol + * for full details on what this object does. * * @returns the new object or #NULL if no memory */ @@ -2284,8 +2284,8 @@ _dbus_auth_server_new (const DBusString *guid) /** * Creates a new auth conversation object for the client side. - * See doc/dbus-sasl-profile.txt for full details on what - * this object does. + * See http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol + * for full details on what this object does. * * @returns the new object or #NULL if no memory */ @@ -2533,12 +2533,10 @@ _dbus_auth_get_buffer (DBusAuth *auth, * * @param auth the auth conversation * @param buffer the buffer being returned - * @param bytes_read number of new bytes added */ void _dbus_auth_return_buffer (DBusAuth *auth, - DBusString *buffer, - int bytes_read) + DBusString *buffer) { _dbus_assert (buffer == &auth->incoming); _dbus_assert (auth->buffer_outstanding); diff --git a/dbus/dbus-auth.h b/dbus/dbus-auth.h index ae3f3647..ba1975f7 100644 --- a/dbus/dbus-auth.h +++ b/dbus/dbus-auth.h @@ -55,8 +55,7 @@ void _dbus_auth_bytes_sent (DBusAuth *auth, void _dbus_auth_get_buffer (DBusAuth *auth, DBusString **buffer); void _dbus_auth_return_buffer (DBusAuth *auth, - DBusString *buffer, - int bytes_read); + DBusString *buffer); void _dbus_auth_get_unused_bytes (DBusAuth *auth, const DBusString **str); void _dbus_auth_delete_unused_bytes (DBusAuth *auth); diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index fadc3a8b..0fd48311 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -28,6 +28,7 @@ #include "dbus-internals.h" #include "dbus-message.h" #include "dbus-marshal-validate.h" +#include "dbus-misc.h" #include "dbus-threads-internal.h" #include "dbus-connection-internal.h" #include "dbus-string.h" @@ -95,19 +96,6 @@ static DBusBusType activation_bus_type = DBUS_BUS_STARTER; static dbus_bool_t initialized = FALSE; -/** - * Lock for globals in this file - */ -_DBUS_DEFINE_GLOBAL_LOCK (bus); - -/** - * Global lock covering all BusData on any connection. The bet is - * that some lock contention is better than more memory - * for a per-connection lock, but it's tough to imagine it mattering - * either way. - */ -_DBUS_DEFINE_GLOBAL_LOCK (bus_datas); - static void addresses_shutdown_func (void *data) { @@ -192,12 +180,12 @@ init_session_address (void) if (!retval) return FALSE; - /* The DBUS_SESSION_BUS_DEFAULT_ADDRESS should have really been named - * DBUS_SESSION_BUS_FALLBACK_ADDRESS. - */ + /* We have a hard-coded (but compile-time-configurable) fallback address for + * the session bus. */ if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL) bus_connection_addresses[DBUS_BUS_SESSION] = - _dbus_strdup (DBUS_SESSION_BUS_DEFAULT_ADDRESS); + _dbus_strdup (DBUS_SESSION_BUS_CONNECT_ADDRESS); + if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL) return FALSE; @@ -306,12 +294,6 @@ init_connections_unlocked (void) * the above code will work right */ - if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL)) - return FALSE; - - if (!_dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL)) - return FALSE; - if (!_dbus_register_shutdown_func (addresses_shutdown_func, NULL)) return FALSE; @@ -330,7 +312,11 @@ bus_data_free (void *data) if (bd->is_well_known) { int i; - _DBUS_LOCK (bus); + + if (!_DBUS_LOCK (bus)) + _dbus_assert_not_reached ("global locks should have been initialized " + "when we attached bus data"); + /* We may be stored in more than one slot */ /* This should now be impossible - these slots are supposed to * be cleared on disconnect, so should not need to be cleared on @@ -401,8 +387,13 @@ void _dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connection) { int i; - - _DBUS_LOCK (bus); + + if (!_DBUS_LOCK (bus)) + { + /* If it was in bus_connections, we would have initialized global locks + * when we added it. So, it can't be. */ + return; + } /* We are expecting to have the connection saved in only one of these * slots, but someone could in a pathological case set system and session @@ -436,7 +427,12 @@ internal_bus_get (DBusBusType type, connection = NULL; - _DBUS_LOCK (bus); + if (!_DBUS_LOCK (bus)) + { + _DBUS_SET_OOM (error); + /* do not "goto out", that would try to unlock */ + return NULL; + } if (!init_connections_unlocked ()) { @@ -506,8 +502,10 @@ internal_bus_get (DBusBusType type, */ dbus_connection_set_exit_on_disconnect (connection, TRUE); - - _DBUS_LOCK (bus_datas); + + if (!_DBUS_LOCK (bus_datas)) + _dbus_assert_not_reached ("global locks were initialized already"); + bd = ensure_bus_data (connection); _dbus_assert (bd != NULL); /* it should have been created on register, so OOM not possible */ @@ -554,7 +552,7 @@ out: * * @param type bus type * @param error address where an error can be returned. - * @returns a #DBusConnection with new ref + * @returns a #DBusConnection with new ref or #NULL on error */ DBusConnection * dbus_bus_get (DBusBusType type, @@ -660,7 +658,12 @@ dbus_bus_register (DBusConnection *connection, message = NULL; reply = NULL; - _DBUS_LOCK (bus_datas); + if (!_DBUS_LOCK (bus_datas)) + { + _DBUS_SET_OOM (error); + /* do not "goto out", that would try to unlock */ + return FALSE; + } bd = ensure_bus_data (connection); if (bd == NULL) @@ -769,8 +772,12 @@ dbus_bus_set_unique_name (DBusConnection *connection, _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (unique_name != NULL, FALSE); - _DBUS_LOCK (bus_datas); - + if (!_DBUS_LOCK (bus_datas)) + { + /* do not "goto out", that would try to unlock */ + return FALSE; + } + bd = ensure_bus_data (connection); if (bd == NULL) goto out; @@ -812,8 +819,13 @@ dbus_bus_get_unique_name (DBusConnection *connection) _dbus_return_val_if_fail (connection != NULL, NULL); - _DBUS_LOCK (bus_datas); - + if (!_DBUS_LOCK (bus_datas)) + { + /* We'd have initialized locks when we gave it its unique name, if it + * had one. Don't "goto out", that would try to unlock. */ + return NULL; + } + bd = ensure_bus_data (connection); if (bd == NULL) goto out; diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h index 3d37f188..2842f2f4 100644 --- a/dbus/dbus-connection-internal.h +++ b/dbus/dbus-connection-internal.h @@ -115,7 +115,7 @@ void _dbus_connection_get_stats (DBusConnection *connection, dbus_uint32_t *out_peak_fds); -/* if DBUS_BUILD_TESTS */ +/* if DBUS_ENABLE_EMBEDDED_TESTS */ const char* _dbus_connection_get_address (DBusConnection *connection); /* This _dbus_bus_* stuff doesn't really belong here, but dbus-bus-internal.h seems diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index ee33b6cc..f0b6871e 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -203,26 +203,19 @@ * @{ */ -#ifdef DBUS_ENABLE_VERBOSE_MODE static void _dbus_connection_trace_ref (DBusConnection *connection, int old_refcount, int new_refcount, const char *why) { +#ifdef DBUS_ENABLE_VERBOSE_MODE static int enabled = -1; _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount, why, "DBUS_CONNECTION_TRACE", &enabled); -} -#else -#define _dbus_connection_trace_ref(c,o,n,w) \ - do \ - {\ - (void) (o); \ - (void) (n); \ - } while (0) #endif +} /** * Internal struct representing a message filter function @@ -336,8 +329,8 @@ struct DBusConnection #ifndef DBUS_DISABLE_CHECKS unsigned int have_connection_lock : 1; /**< Used to check locking */ #endif - -#ifndef DBUS_DISABLE_CHECKS + +#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT) int generation; /**< _dbus_current_generation that should correspond to this connection */ #endif }; @@ -446,7 +439,7 @@ _dbus_connection_wakeup_mainloop (DBusConnection *connection) (*connection->wakeup_main_function) (connection->wakeup_main_data); } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * Gets the locks so we can examine them * @@ -490,9 +483,9 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection, DBusPendingCall *pending; dbus_uint32_t reply_serial; DBusMessage *message; - - _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); - + + _dbus_assert (_dbus_transport_peek_is_authenticated (connection->transport)); + _dbus_list_append_link (&connection->incoming_messages, link); message = link->data; @@ -1354,7 +1347,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) connection->disconnected_message_arrived = FALSE; connection->disconnected_message_processed = FALSE; -#ifndef DBUS_DISABLE_CHECKS +#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT) connection->generation = _dbus_current_generation; #endif @@ -1531,7 +1524,7 @@ _dbus_connection_handle_watch (DBusWatch *watch, return retval; } -_DBUS_DEFINE_GLOBAL_LOCK (shared_connections); +/* Protected by _DBUS_LOCK (shared_connections) */ static DBusHashTable *shared_connections = NULL; static DBusList *shared_connections_no_guid = NULL; @@ -1555,9 +1548,14 @@ static void shared_connections_shutdown (void *data) { int n_entries; - - _DBUS_LOCK (shared_connections); - + + if (!_DBUS_LOCK (shared_connections)) + { + /* We'd have initialized locks before adding anything, so there + * can't be anything there. */ + return; + } + /* This is a little bit unpleasant... better ideas? */ while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0) { @@ -1571,7 +1569,8 @@ shared_connections_shutdown (void *data) _DBUS_UNLOCK (shared_connections); close_connection_on_shutdown (connection); - _DBUS_LOCK (shared_connections); + if (!_DBUS_LOCK (shared_connections)) + _dbus_assert_not_reached ("global locks were already initialized"); /* The connection should now be dead and not in our hash ... */ _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries); @@ -1590,7 +1589,8 @@ shared_connections_shutdown (void *data) { _DBUS_UNLOCK (shared_connections); close_connection_on_shutdown (connection); - _DBUS_LOCK (shared_connections); + if (!_DBUS_LOCK (shared_connections)) + _dbus_assert_not_reached ("global locks were already initialized"); connection = _dbus_list_pop_first (&shared_connections_no_guid); } } @@ -1607,8 +1607,13 @@ connection_lookup_shared (DBusAddressEntry *entry, _dbus_verbose ("checking for existing connection\n"); *result = NULL; - - _DBUS_LOCK (shared_connections); + + if (!_DBUS_LOCK (shared_connections)) + { + /* If it was shared, we'd have initialized global locks when we put + * it in shared_connections. */ + return FALSE; + } if (shared_connections == NULL) { @@ -1706,7 +1711,8 @@ connection_record_shared_unlocked (DBusConnection *connection, if (guid == NULL) { - _DBUS_LOCK (shared_connections); + if (!_DBUS_LOCK (shared_connections)) + return FALSE; if (!_dbus_list_prepend (&shared_connections_no_guid, connection)) { @@ -1733,8 +1739,14 @@ connection_record_shared_unlocked (DBusConnection *connection, dbus_free (guid_key); return FALSE; } - - _DBUS_LOCK (shared_connections); + + if (!_DBUS_LOCK (shared_connections)) + { + dbus_free (guid_in_connection); + dbus_free (guid_key); + return FALSE; + } + _dbus_assert (shared_connections != NULL); if (!_dbus_hash_table_insert_string (shared_connections, @@ -1765,9 +1777,14 @@ connection_forget_shared_unlocked (DBusConnection *connection) if (!connection->shareable) return; - - _DBUS_LOCK (shared_connections); - + + if (!_DBUS_LOCK (shared_connections)) + { + /* If it was shared, we'd have initialized global locks when we put + * it in the table; so it can't be there. */ + return; + } + if (connection->server_guid != NULL) { _dbus_verbose ("dropping connection to %s out of the shared table\n", @@ -2150,7 +2167,7 @@ _dbus_connection_close_if_only_one_ref (DBusConnection *connection) * relatively long time for memory, if they were only willing to block * briefly then we retry for memory at a rapid rate. * - * @timeout_milliseconds the timeout requested for blocking + * @param timeout_milliseconds the timeout requested for blocking */ static void _dbus_memory_pause_based_on_timeout (int timeout_milliseconds) @@ -2683,6 +2700,7 @@ _dbus_connection_last_unref (DBusConnection *connection) dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); + dbus_connection_set_windows_user_function (connection, NULL, NULL, NULL); _dbus_watch_list_free (connection->watches); connection->watches = NULL; @@ -2952,9 +2970,9 @@ dbus_connection_get_is_authenticated (DBusConnection *connection) dbus_bool_t res; _dbus_return_val_if_fail (connection != NULL, FALSE); - + CONNECTION_LOCK (connection); - res = _dbus_transport_get_is_authenticated (connection->transport); + res = _dbus_transport_try_to_authenticate (connection->transport); CONNECTION_UNLOCK (connection); return res; @@ -3938,7 +3956,7 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) link = _dbus_list_pop_first_link (&connection->incoming_messages); connection->n_incoming -= 1; - _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n", + _dbus_verbose ("Message %p (%s %s %s %s sig:'%s' serial:%u) removed from incoming queue %p, %d incoming\n", link->data, dbus_message_type_to_string (dbus_message_get_type (link->data)), dbus_message_get_path (link->data) ? @@ -3951,6 +3969,7 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) dbus_message_get_member (link->data) : "no member", dbus_message_get_signature (link->data), + dbus_message_get_serial (link->data), connection, connection->n_incoming); _dbus_message_trace_ref (link->data, -1, -1, @@ -5148,10 +5167,10 @@ dbus_connection_get_unix_user (DBusConnection *connection, _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (uid != NULL, FALSE); - + CONNECTION_LOCK (connection); - if (!_dbus_transport_get_is_authenticated (connection->transport)) + if (!_dbus_transport_try_to_authenticate (connection->transport)) result = FALSE; else result = _dbus_transport_get_unix_user (connection->transport, @@ -5184,10 +5203,10 @@ dbus_connection_get_unix_process_id (DBusConnection *connection, _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (pid != NULL, FALSE); - + CONNECTION_LOCK (connection); - if (!_dbus_transport_get_is_authenticated (connection->transport)) + if (!_dbus_transport_try_to_authenticate (connection->transport)) result = FALSE; else result = _dbus_transport_get_unix_process_id (connection->transport, @@ -5205,7 +5224,8 @@ dbus_connection_get_unix_process_id (DBusConnection *connection, * connection. * * @param connection the connection - * @param data return location for audit data + * @param data return location for audit data + * @param data_size return location for length of audit data * @returns #TRUE if audit data is filled in with a valid ucred pointer */ dbus_bool_t @@ -5218,10 +5238,10 @@ dbus_connection_get_adt_audit_session_data (DBusConnection *connection, _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (data != NULL, FALSE); _dbus_return_val_if_fail (data_size != NULL, FALSE); - + CONNECTION_LOCK (connection); - if (!_dbus_transport_get_is_authenticated (connection->transport)) + if (!_dbus_transport_try_to_authenticate (connection->transport)) result = FALSE; else result = _dbus_transport_get_adt_audit_session_data (connection->transport, @@ -5314,10 +5334,10 @@ dbus_connection_get_windows_user (DBusConnection *connection, _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); - + CONNECTION_LOCK (connection); - if (!_dbus_transport_get_is_authenticated (connection->transport)) + if (!_dbus_transport_try_to_authenticate (connection->transport)) result = FALSE; else result = _dbus_transport_get_windows_user (connection->transport, @@ -5435,7 +5455,7 @@ dbus_connection_set_route_peer_messages (DBusConnection *connection, _dbus_return_if_fail (connection != NULL); CONNECTION_LOCK (connection); - connection->route_peer_messages = TRUE; + connection->route_peer_messages = value; CONNECTION_UNLOCK (connection); } @@ -5852,8 +5872,8 @@ dbus_connection_list_registered (DBusConnection *connection, return retval; } -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (connection_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots)); /** * Allocates an integer ID to be used for storing application-specific @@ -5873,7 +5893,6 @@ dbus_bool_t dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - &_DBUS_LOCK_NAME (connection_slots), slot_p); } @@ -5974,7 +5993,8 @@ dbus_connection_get_data (DBusConnection *connection, void *res; _dbus_return_val_if_fail (connection != NULL, NULL); - + _dbus_return_val_if_fail (slot >= 0, NULL); + SLOTS_LOCK (connection); res = _dbus_data_slot_list_get (&slot_allocator, @@ -6043,7 +6063,7 @@ dbus_connection_get_max_message_size (DBusConnection *connection) * result in disconnecting the connection. * * @param connection a #DBusConnection - * @param size maximum message unix fds the connection can receive + * @param n maximum message unix fds the connection can receive */ void dbus_connection_set_max_message_unix_fds (DBusConnection *connection, @@ -6141,7 +6161,7 @@ dbus_connection_get_max_received_size (DBusConnection *connection) * The semantics are analogous to those of dbus_connection_set_max_received_size(). * * @param connection the connection - * @param size the maximum size in bytes of all outstanding messages + * @param n the maximum size in bytes of all outstanding messages */ void dbus_connection_set_max_received_unix_fds (DBusConnection *connection, @@ -6258,7 +6278,7 @@ dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) return res; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * Returns the address of the transport object of this connection * diff --git a/dbus/dbus-credentials-util.c b/dbus/dbus-credentials-util.c index 02771966..d2d164f7 100644 --- a/dbus/dbus-credentials-util.c +++ b/dbus/dbus-credentials-util.c @@ -33,14 +33,14 @@ /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> #include <string.h> static DBusCredentials* make_credentials(dbus_uid_t unix_uid, - dbus_pid_t unix_pid, + dbus_pid_t pid, const char *windows_sid) { DBusCredentials *credentials; @@ -56,9 +56,9 @@ make_credentials(dbus_uid_t unix_uid, } } - if (unix_pid != DBUS_PID_UNSET) + if (pid != DBUS_PID_UNSET) { - if (!_dbus_credentials_add_unix_pid (credentials, unix_pid)) + if (!_dbus_credentials_add_pid (credentials, pid)) { _dbus_credentials_unref (credentials); return NULL; @@ -102,7 +102,7 @@ _dbus_credentials_test (const char *test_data_dir) _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID)); _dbus_assert (_dbus_credentials_get_unix_uid (creds) == 12); - _dbus_assert (_dbus_credentials_get_unix_pid (creds) == 511); + _dbus_assert (_dbus_credentials_get_pid (creds) == 511); _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds), SAMPLE_SID) == 0); _dbus_assert (!_dbus_credentials_are_empty (creds)); @@ -118,7 +118,7 @@ _dbus_credentials_test (const char *test_data_dir) _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_WINDOWS_SID)); _dbus_assert (_dbus_credentials_get_unix_uid (creds2) == 12); - _dbus_assert (_dbus_credentials_get_unix_pid (creds2) == 511); + _dbus_assert (_dbus_credentials_get_pid (creds2) == 511); _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds2), SAMPLE_SID) == 0); _dbus_assert (_dbus_credentials_are_superset (creds, creds2)); @@ -192,7 +192,7 @@ _dbus_credentials_test (const char *test_data_dir) _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID)); _dbus_assert (_dbus_credentials_get_unix_uid (creds) == DBUS_UID_UNSET); - _dbus_assert (_dbus_credentials_get_unix_pid (creds) == DBUS_PID_UNSET); + _dbus_assert (_dbus_credentials_get_pid (creds) == DBUS_PID_UNSET); _dbus_assert (_dbus_credentials_get_windows_sid (creds) == NULL); _dbus_assert (_dbus_credentials_are_empty (creds)); @@ -203,4 +203,4 @@ _dbus_credentials_test (const char *test_data_dir) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c index ff69f3b0..7325125c 100644 --- a/dbus/dbus-credentials.c +++ b/dbus/dbus-credentials.c @@ -48,7 +48,7 @@ struct DBusCredentials { int refcount; dbus_uid_t unix_uid; - dbus_pid_t unix_pid; + dbus_pid_t pid; char *windows_sid; void *adt_audit_data; dbus_int32_t adt_audit_data_size; @@ -77,7 +77,7 @@ _dbus_credentials_new (void) creds->refcount = 1; creds->unix_uid = DBUS_UID_UNSET; - creds->unix_pid = DBUS_PID_UNSET; + creds->pid = DBUS_PID_UNSET; creds->windows_sid = NULL; creds->adt_audit_data = NULL; creds->adt_audit_data_size = 0; @@ -146,10 +146,10 @@ _dbus_credentials_unref (DBusCredentials *credentials) * @returns #FALSE if no memory */ dbus_bool_t -_dbus_credentials_add_unix_pid (DBusCredentials *credentials, - dbus_pid_t pid) +_dbus_credentials_add_pid (DBusCredentials *credentials, + dbus_pid_t pid) { - credentials->unix_pid = pid; + credentials->pid = pid; return TRUE; } @@ -231,7 +231,7 @@ _dbus_credentials_include (DBusCredentials *credentials, switch (type) { case DBUS_CREDENTIAL_UNIX_PROCESS_ID: - return credentials->unix_pid != DBUS_PID_UNSET; + return credentials->pid != DBUS_PID_UNSET; case DBUS_CREDENTIAL_UNIX_USER_ID: return credentials->unix_uid != DBUS_UID_UNSET; case DBUS_CREDENTIAL_WINDOWS_SID: @@ -252,9 +252,9 @@ _dbus_credentials_include (DBusCredentials *credentials, * @returns UNIX process ID */ dbus_pid_t -_dbus_credentials_get_unix_pid (DBusCredentials *credentials) +_dbus_credentials_get_pid (DBusCredentials *credentials) { - return credentials->unix_pid; + return credentials->pid; } /** @@ -322,8 +322,8 @@ _dbus_credentials_are_superset (DBusCredentials *credentials, DBusCredentials *possible_subset) { return - (possible_subset->unix_pid == DBUS_PID_UNSET || - possible_subset->unix_pid == credentials->unix_pid) && + (possible_subset->pid == DBUS_PID_UNSET || + possible_subset->pid == credentials->pid) && (possible_subset->unix_uid == DBUS_UID_UNSET || possible_subset->unix_uid == credentials->unix_uid) && (possible_subset->windows_sid == NULL || @@ -345,7 +345,7 @@ dbus_bool_t _dbus_credentials_are_empty (DBusCredentials *credentials) { return - credentials->unix_pid == DBUS_PID_UNSET && + credentials->pid == DBUS_PID_UNSET && credentials->unix_uid == DBUS_UID_UNSET && credentials->windows_sid == NULL && credentials->adt_audit_data == NULL; @@ -410,9 +410,9 @@ _dbus_credentials_add_credential (DBusCredentials *credentials, DBusCredentials *other_credentials) { if (which == DBUS_CREDENTIAL_UNIX_PROCESS_ID && - other_credentials->unix_pid != DBUS_PID_UNSET) + other_credentials->pid != DBUS_PID_UNSET) { - if (!_dbus_credentials_add_unix_pid (credentials, other_credentials->unix_pid)) + if (!_dbus_credentials_add_pid (credentials, other_credentials->pid)) return FALSE; } else if (which == DBUS_CREDENTIAL_UNIX_USER_ID && @@ -445,7 +445,7 @@ _dbus_credentials_add_credential (DBusCredentials *credentials, void _dbus_credentials_clear (DBusCredentials *credentials) { - credentials->unix_pid = DBUS_PID_UNSET; + credentials->pid = DBUS_PID_UNSET; credentials->unix_uid = DBUS_UID_UNSET; dbus_free (credentials->windows_sid); credentials->windows_sid = NULL; @@ -523,9 +523,9 @@ _dbus_credentials_to_string_append (DBusCredentials *credentials, goto oom; join = TRUE; } - if (credentials->unix_pid != DBUS_PID_UNSET) + if (credentials->pid != DBUS_PID_UNSET) { - if (!_dbus_string_append_printf (string, "%spid=" DBUS_PID_FORMAT, join ? " " : "", credentials->unix_pid)) + if (!_dbus_string_append_printf (string, "%spid=" DBUS_PID_FORMAT, join ? " " : "", credentials->pid)) goto oom; join = TRUE; } diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h index ef6124fd..abcc4bb3 100644 --- a/dbus/dbus-credentials.h +++ b/dbus/dbus-credentials.h @@ -41,7 +41,7 @@ DBusCredentials* _dbus_credentials_new_from_current_process (void); DBusCredentials* _dbus_credentials_new (void); void _dbus_credentials_ref (DBusCredentials *credentials); void _dbus_credentials_unref (DBusCredentials *credentials); -dbus_bool_t _dbus_credentials_add_unix_pid (DBusCredentials *credentials, +dbus_bool_t _dbus_credentials_add_pid (DBusCredentials *credentials, dbus_pid_t pid); dbus_bool_t _dbus_credentials_add_unix_uid (DBusCredentials *credentials, dbus_uid_t uid); @@ -52,7 +52,7 @@ dbus_bool_t _dbus_credentials_add_adt_audit_data (DBusCredentials dbus_int32_t size); dbus_bool_t _dbus_credentials_include (DBusCredentials *credentials, DBusCredentialType type); -dbus_pid_t _dbus_credentials_get_unix_pid (DBusCredentials *credentials); +dbus_pid_t _dbus_credentials_get_pid (DBusCredentials *credentials); dbus_uid_t _dbus_credentials_get_unix_uid (DBusCredentials *credentials); const char* _dbus_credentials_get_windows_sid (DBusCredentials *credentials); void * _dbus_credentials_get_adt_audit_data (DBusCredentials *credentials); diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c index 0369612e..e37c9dd5 100644 --- a/dbus/dbus-dataslot.c +++ b/dbus/dbus-dataslot.c @@ -43,13 +43,14 @@ * @param allocator the allocator to initialize */ dbus_bool_t -_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator) +_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator, + DBusGlobalLock lock) { allocator->allocated_slots = NULL; allocator->n_allocated_slots = 0; allocator->n_used_slots = 0; - allocator->lock_loc = NULL; - + allocator->lock = lock; + return TRUE; } @@ -61,29 +62,17 @@ _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator) * is allocated and stored at *slot_id_p. * * @param allocator the allocator - * @param mutex_loc the location lock for this allocator * @param slot_id_p address to fill with the slot ID * @returns #TRUE on success */ dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, - DBusRMutex **mutex_loc, dbus_int32_t *slot_id_p) { dbus_int32_t slot; - _dbus_rmutex_lock (*mutex_loc); - - if (allocator->n_allocated_slots == 0) - { - _dbus_assert (allocator->lock_loc == NULL); - allocator->lock_loc = mutex_loc; - } - else if (allocator->lock_loc != mutex_loc) - { - _dbus_warn_check_failed ("D-Bus threads were initialized after first using the D-Bus library. If your application does not directly initialize threads or use D-Bus, keep in mind that some library or plugin may have used D-Bus or initialized threads behind your back. You can often fix this problem by calling dbus_init_threads() or dbus_g_threads_init() early in your main() method, before D-Bus is used.\n"); - _dbus_assert_not_reached ("exiting"); - } + if (!_dbus_lock (allocator->lock)) + return FALSE; if (*slot_id_p >= 0) { @@ -146,7 +135,7 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots); out: - _dbus_rmutex_unlock (*(allocator->lock_loc)); + _dbus_unlock (allocator->lock); return slot >= 0; } @@ -165,8 +154,10 @@ void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p) { - _dbus_rmutex_lock (*(allocator->lock_loc)); - + if (!_dbus_lock (allocator->lock)) + _dbus_assert_not_reached ("we should have initialized global locks " + "before we allocated this slot"); + _dbus_assert (*slot_id_p < allocator->n_allocated_slots); _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p); _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0); @@ -175,7 +166,7 @@ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, if (allocator->allocated_slots[*slot_id_p].refcount > 0) { - _dbus_rmutex_unlock (*(allocator->lock_loc)); + _dbus_unlock (allocator->lock); return; } @@ -190,19 +181,12 @@ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, if (allocator->n_used_slots == 0) { - DBusRMutex **mutex_loc = allocator->lock_loc; - dbus_free (allocator->allocated_slots); allocator->allocated_slots = NULL; allocator->n_allocated_slots = 0; - allocator->lock_loc = NULL; - - _dbus_rmutex_unlock (*mutex_loc); - } - else - { - _dbus_rmutex_unlock (*(allocator->lock_loc)); } + + _dbus_unlock (allocator->lock); } /** @@ -247,10 +231,13 @@ _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator, * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts * are disabled, since then the asserts are empty. */ - _dbus_rmutex_lock (*(allocator->lock_loc)); + if (!_dbus_lock (allocator->lock)) + _dbus_assert_not_reached ("we should have initialized global locks " + "before we allocated this slot"); + _dbus_assert (slot < allocator->n_allocated_slots); _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); - _dbus_rmutex_unlock (*(allocator->lock_loc)); + _dbus_unlock (allocator->lock); #endif if (slot >= list->n_slots) @@ -304,11 +291,14 @@ _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator, * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts * are disabled, since then the asserts are empty. */ - _dbus_rmutex_lock (*(allocator->lock_loc)); + if (!_dbus_lock (allocator->lock)) + _dbus_assert_not_reached ("we should have initialized global locks " + "before we allocated this slot"); + _dbus_assert (slot >= 0); _dbus_assert (slot < allocator->n_allocated_slots); _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); - _dbus_rmutex_unlock (*(allocator->lock_loc)); + _dbus_unlock (allocator->lock); #endif if (slot >= list->n_slots) @@ -358,7 +348,7 @@ _dbus_data_slot_list_free (DBusDataSlotList *list) /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> @@ -384,17 +374,12 @@ _dbus_data_slot_test (void) int i; DBusFreeFunction old_free_func; void *old_data; - DBusRMutex *mutex; - - if (!_dbus_data_slot_allocator_init (&allocator)) + + if (!_dbus_data_slot_allocator_init (&allocator, _DBUS_LOCK_server_slots)) _dbus_assert_not_reached ("no memory for allocator"); _dbus_data_slot_list_init (&list); - _dbus_rmutex_new_at_location (&mutex); - if (mutex == NULL) - _dbus_assert_not_reached ("failed to alloc mutex"); - #define N_SLOTS 100 i = 0; @@ -405,8 +390,8 @@ _dbus_data_slot_test (void) * here. */ dbus_int32_t tmp = -1; - - _dbus_data_slot_allocator_alloc (&allocator, &mutex, &tmp); + + _dbus_data_slot_allocator_alloc (&allocator, &tmp); if (tmp != i) _dbus_assert_not_reached ("did not allocate slots in numeric order\n"); @@ -471,9 +456,7 @@ _dbus_data_slot_test (void) ++i; } - _dbus_rmutex_free_at_location (&mutex); - return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-dataslot.h b/dbus/dbus-dataslot.h index 3d9d5edd..1e04fcbc 100644 --- a/dbus/dbus-dataslot.h +++ b/dbus/dbus-dataslot.h @@ -57,9 +57,11 @@ struct DBusDataSlotAllocator DBusAllocatedSlot *allocated_slots; /**< Allocated slots */ int n_allocated_slots; /**< number of slots malloc'd */ int n_used_slots; /**< number of slots used */ - DBusRMutex **lock_loc; /**< location of thread lock */ + DBusGlobalLock lock; /**< index of thread lock */ }; +#define _DBUS_DATA_SLOT_ALLOCATOR_INIT(x) { NULL, 0, 0, x } + /** * Data structure that stores the actual user data set at a given * slot. @@ -70,9 +72,9 @@ struct DBusDataSlotList int n_slots; /**< Slots we have storage for in data_slots */ }; -dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator); +dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator, + DBusGlobalLock lock); dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, - DBusRMutex **mutex_loc, int *slot_id_p); void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, int *slot_id_p); diff --git a/dbus/dbus-errors.c b/dbus/dbus-errors.c index db3305b9..a0571a50 100644 --- a/dbus/dbus-errors.c +++ b/dbus/dbus-errors.c @@ -235,7 +235,7 @@ dbus_error_free (DBusError *error) * must ensure the name and message are global data that won't be * freed. You probably want dbus_set_error() instead, in most cases. * - * @param error the error.or #NULL + * @param error the error or #NULL * @param name the error name (not copied!!!) * @param message the error message (not copied!!!) */ @@ -379,7 +379,6 @@ dbus_set_error (DBusError *error, message_from_error (name))) { _dbus_string_free (&str); - va_end (args); goto nomem; } } diff --git a/dbus/dbus-hash.c b/dbus/dbus-hash.c index c4c6f935..c80835aa 100644 --- a/dbus/dbus-hash.c +++ b/dbus/dbus-hash.c @@ -1401,7 +1401,7 @@ _dbus_hash_table_get_n_entries (DBusHashTable *table) /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> @@ -1828,4 +1828,4 @@ _dbus_hash_test (void) return ret; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-init-win.cpp b/dbus/dbus-init-win.cpp new file mode 100644 index 00000000..687f248c --- /dev/null +++ b/dbus/dbus-init-win.cpp @@ -0,0 +1,52 @@ +/* + * dbus-init-win.cpp - once-per-process initialization + * + * Copyright © 2013 Intel Corporation + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <config.h> + +extern "C" +{ +#include "dbus-sysdeps-win.h" +} + +class DBusInternalInit + { + public: + DBusInternalInit () + { + _dbus_threads_windows_init_global (); + } + + void must_not_be_omitted () + { + } + }; + +static DBusInternalInit init; + +extern "C" void +_dbus_threads_windows_ensure_ctor_linked () +{ + /* Do nothing significant, just ensure that the global initializer gets + * linked in. */ + init.must_not_be_omitted (); +} diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c index 0e5d807e..e2482597 100644 --- a/dbus/dbus-internals.c +++ b/dbus/dbus-internals.c @@ -163,26 +163,11 @@ */ /** - * @def _DBUS_DEFINE_GLOBAL_LOCK - * - * Defines a global lock variable with the given name. - * The lock must be added to the list to initialize - * in dbus_threads_init(). - */ - -/** - * @def _DBUS_DECLARE_GLOBAL_LOCK - * - * Expands to declaration of a global lock defined - * with _DBUS_DEFINE_GLOBAL_LOCK. - * The lock must be added to the list to initialize - * in dbus_threads_init(). - */ - -/** * @def _DBUS_LOCK * - * Locks a global lock + * Locks a global lock, initializing it first if necessary. + * + * @returns #FALSE if not enough memory */ /** @@ -347,25 +332,22 @@ _dbus_verbose_init (void) */ static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level) { - static int prefix = -1; + int prefix = 0; + char *p = (char *)file + strlen(file); + int i = 0; - if (prefix == -1) + for (;p >= file;p--) { - char *p = (char *)file + strlen(file); - int i = 0; - prefix = 0; - for (;p >= file;p--) + if (DBUS_IS_DIR_SEPARATOR(*p)) { - if (DBUS_IS_DIR_SEPARATOR(*p)) + if (++i >= level) { - if (++i >= level) - { - prefix = p-file+1; - break; - } - } - } + prefix = p-file+1; + break; + } + } } + return (char *)file+prefix; } @@ -847,7 +829,7 @@ _dbus_read_uuid_file (const DBusString *filename, } } -_DBUS_DEFINE_GLOBAL_LOCK (machine_uuid); +/* Protected by _DBUS_LOCK (machine_uuid) */ static int machine_uuid_initialized_generation = 0; static DBusGUID machine_uuid; @@ -866,7 +848,9 @@ _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str) { dbus_bool_t ok; - _DBUS_LOCK (machine_uuid); + if (!_DBUS_LOCK (machine_uuid)) + return FALSE; + if (machine_uuid_initialized_generation != _dbus_current_generation) { DBusError error = DBUS_ERROR_INIT; @@ -874,7 +858,7 @@ _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str) if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE, &error)) { -#ifndef DBUS_BUILD_TESTS +#ifndef DBUS_ENABLE_EMBEDDED_TESTS /* For the test suite, we may not be installed so just continue silently * here. But in a production build, we want to be nice and loud about * this. @@ -953,7 +937,7 @@ _dbus_real_assert_not_reached (const char *explanation, } #endif /* DBUS_DISABLE_ASSERT */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS static dbus_bool_t run_failing_each_malloc (int n_mallocs, const char *description, @@ -1048,6 +1032,6 @@ _dbus_test_oom_handling (const char *description, return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ /** @} */ diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index 8036a2ba..c5a3c9b8 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -35,10 +35,6 @@ DBUS_BEGIN_DECLS -#ifndef DBUS_SESSION_BUS_DEFAULT_ADDRESS -#define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:" -#endif - void _dbus_warn (const char *format, ...) _DBUS_GNUC_PRINTF (1, 2); @@ -234,10 +230,8 @@ char** _dbus_dup_string_array (const char **array); #define _DBUS_INT_MIN _DBUS_INT32_MIN #define _DBUS_INT_MAX _DBUS_INT32_MAX #define _DBUS_UINT_MAX _DBUS_UINT32_MAX -#ifdef DBUS_HAVE_INT64 #define _DBUS_INT64_MAX DBUS_INT64_CONSTANT (0x7fffffffffffffff) #define _DBUS_UINT64_MAX DBUS_UINT64_CONSTANT (0xffffffffffffffff) -#endif #define _DBUS_ONE_KILOBYTE 1024 #define _DBUS_ONE_MEGABYTE 1024 * _DBUS_ONE_KILOBYTE #define _DBUS_ONE_HOUR_IN_MILLISECONDS (1000 * 60 * 60) @@ -270,7 +264,7 @@ void _dbus_verbose_bytes_of_string (const DBusString *str, extern const char *_dbus_no_memory_message; #define _DBUS_SET_OOM(error) dbus_set_error_const ((error), DBUS_ERROR_NO_MEMORY, _dbus_no_memory_message) -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /* Memory debugging */ void _dbus_set_fail_alloc_counter (int until_next_fail); int _dbus_get_fail_alloc_counter (void); @@ -294,45 +288,46 @@ dbus_bool_t _dbus_test_oom_handling (const char *description, #define _dbus_decrement_fail_alloc_counter() (FALSE) #define _dbus_disable_mem_pools() (FALSE) #define _dbus_get_malloc_blocks_outstanding (0) -#endif /* !DBUS_BUILD_TESTS */ +#endif /* !DBUS_ENABLE_EMBEDDED_TESTS */ typedef void (* DBusShutdownFunction) (void *data); -dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction function, - void *data); +dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction function, + void *data); +dbus_bool_t _dbus_register_shutdown_func_unlocked (DBusShutdownFunction function, + void *data); extern int _dbus_current_generation; -/* Thread initializers */ -#define _DBUS_LOCK_NAME(name) _dbus_lock_##name -#define _DBUS_DECLARE_GLOBAL_LOCK(name) extern DBusRMutex *_dbus_lock_##name -#define _DBUS_DEFINE_GLOBAL_LOCK(name) DBusRMutex *_dbus_lock_##name -#define _DBUS_LOCK(name) _dbus_rmutex_lock (_dbus_lock_##name) -#define _DBUS_UNLOCK(name) _dbus_rmutex_unlock (_dbus_lock_##name) - -/* 1-5 */ -_DBUS_DECLARE_GLOBAL_LOCK (list); -_DBUS_DECLARE_GLOBAL_LOCK (connection_slots); -_DBUS_DECLARE_GLOBAL_LOCK (pending_call_slots); -_DBUS_DECLARE_GLOBAL_LOCK (server_slots); -_DBUS_DECLARE_GLOBAL_LOCK (message_slots); -/* 5-10 */ -_DBUS_DECLARE_GLOBAL_LOCK (bus); -_DBUS_DECLARE_GLOBAL_LOCK (bus_datas); -_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs); -_DBUS_DECLARE_GLOBAL_LOCK (system_users); -_DBUS_DECLARE_GLOBAL_LOCK (message_cache); -/* 10-14 */ -_DBUS_DECLARE_GLOBAL_LOCK (shared_connections); -_DBUS_DECLARE_GLOBAL_LOCK (win_fds); -_DBUS_DECLARE_GLOBAL_LOCK (sid_atom_cache); -_DBUS_DECLARE_GLOBAL_LOCK (machine_uuid); - -#if !DBUS_USE_SYNC -_DBUS_DECLARE_GLOBAL_LOCK (atomic); -#define _DBUS_N_GLOBAL_LOCKS (15) -#else -#define _DBUS_N_GLOBAL_LOCKS (14) -#endif +/* The weird case convention is to avoid having to change all the callers, + * which would be quite a mega-patch. */ +typedef enum +{ + /* index 0-4 */ + _DBUS_LOCK_list, + _DBUS_LOCK_connection_slots, + _DBUS_LOCK_pending_call_slots, + _DBUS_LOCK_server_slots, + _DBUS_LOCK_message_slots, + /* index 5-9 */ + _DBUS_LOCK_bus, + _DBUS_LOCK_bus_datas, + _DBUS_LOCK_shutdown_funcs, + _DBUS_LOCK_system_users, + _DBUS_LOCK_message_cache, + /* index 10-12 */ + _DBUS_LOCK_shared_connections, + _DBUS_LOCK_machine_uuid, + _DBUS_LOCK_sysdeps, + + _DBUS_N_GLOBAL_LOCKS +} DBusGlobalLock; + +dbus_bool_t _dbus_lock (DBusGlobalLock lock) _DBUS_GNUC_WARN_UNUSED_RESULT; +void _dbus_unlock (DBusGlobalLock lock); + +#define _DBUS_LOCK_NAME(name) _DBUS_LOCK_##name +#define _DBUS_LOCK(name) _dbus_lock (_DBUS_LOCK_##name) +#define _DBUS_UNLOCK(name) _dbus_unlock (_DBUS_LOCK_##name) dbus_bool_t _dbus_threads_init_debug (void); diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c index 23b9df5a..f0c64de3 100644 --- a/dbus/dbus-keyring.c +++ b/dbus/dbus-keyring.c @@ -80,7 +80,7 @@ * Maximum number of keys in the keyring before * we just ignore the rest */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #define MAX_KEYS_IN_FILE 10 #else #define MAX_KEYS_IN_FILE 256 @@ -697,10 +697,10 @@ _dbus_keyring_unref (DBusKeyring *keyring) /** * Creates a new keyring that lives in the ~/.dbus-keyrings directory - * of the given user credentials. If the credentials are #NULL or - * empty, uses those of the current process. + * of the user represented by @p credentials. If the @p credentials are + * #NULL or empty, uses those of the current process. * - * @param username username to get keyring for, or #NULL + * @param credentials a set of credentials representing a user or #NULL * @param context which keyring to get * @param error return location for errors * @returns the keyring or #NULL on error @@ -717,6 +717,13 @@ _dbus_keyring_new_for_credentials (DBusCredentials *credentials, DBusCredentials *our_credentials; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to create DBus keyring when setuid"); + return NULL; + } keyring = NULL; error_set = FALSE; @@ -1016,7 +1023,7 @@ _dbus_keyring_get_hex_key (DBusKeyring *keyring, /** @} */ /* end of exposed API */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> @@ -1149,5 +1156,5 @@ _dbus_keyring_test (void) return FALSE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c index 7e11cc8d..c4c1856f 100644 --- a/dbus/dbus-list.c +++ b/dbus/dbus-list.c @@ -35,8 +35,8 @@ * Types and functions related to DBusList. */ +/* Protected by _DBUS_LOCK (list) */ static DBusMemPool *list_pool; -_DBUS_DEFINE_GLOBAL_LOCK (list); /** * @defgroup DBusListInternals Linked list implementation details @@ -56,7 +56,8 @@ alloc_link (void *data) { DBusList *link; - _DBUS_LOCK (list); + if (!_DBUS_LOCK (list)) + return FALSE; if (list_pool == NULL) { @@ -93,7 +94,10 @@ alloc_link (void *data) static void free_link (DBusList *link) { - _DBUS_LOCK (list); + if (!_DBUS_LOCK (list)) + _dbus_assert_not_reached ("we should have initialized global locks " + "before we allocated a linked-list link"); + if (_dbus_mem_pool_dealloc (list_pool, link)) { _dbus_mem_pool_free (list_pool); @@ -152,7 +156,14 @@ _dbus_list_get_stats (dbus_uint32_t *in_use_p, dbus_uint32_t *in_free_list_p, dbus_uint32_t *allocated_p) { - _DBUS_LOCK (list); + if (!_DBUS_LOCK (list)) + { + *in_use_p = 0; + *in_free_list_p = 0; + *allocated_p = 0; + return; + } + _dbus_mem_pool_get_stats (list_pool, in_use_p, in_free_list_p, allocated_p); _DBUS_UNLOCK (list); } @@ -777,7 +788,7 @@ _dbus_list_length_is_one (DBusList **list) /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> diff --git a/dbus/dbus-macros.h b/dbus/dbus-macros.h index dcd3eebd..cae4100e 100644 --- a/dbus/dbus-macros.h +++ b/dbus/dbus-macros.h @@ -88,13 +88,21 @@ #define DBUS_ALLOC_SIZE2(x,y) #endif +#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define _DBUS_GNUC_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +#define _DBUS_GNUC_WARN_UNUSED_RESULT +#endif + /** @def _DBUS_GNUC_PRINTF * used to tell gcc about printf format strings */ /** @def _DBUS_GNUC_NORETURN * used to tell gcc about functions that never return, such as _dbus_abort() */ - +/** @def _DBUS_GNUC_WARN_UNUSED_RESULT + * used to tell gcc about functions whose result must be used + */ /* Normally docs are in .c files, but there isn't a .c file for this. */ /** diff --git a/dbus/dbus-mainloop.c b/dbus/dbus-mainloop.c index cef676a3..7ff9dc2c 100644 --- a/dbus/dbus-mainloop.c +++ b/dbus/dbus-mainloop.c @@ -34,27 +34,6 @@ #define MAINLOOP_SPEW 0 -#if MAINLOOP_SPEW -#ifdef DBUS_ENABLE_VERBOSE_MODE -static const char* -watch_flags_to_string (int flags) -{ - const char *watch_type; - - if ((flags & DBUS_WATCH_READABLE) && - (flags & DBUS_WATCH_WRITABLE)) - watch_type = "readwrite"; - else if (flags & DBUS_WATCH_READABLE) - watch_type = "read"; - else if (flags & DBUS_WATCH_WRITABLE) - watch_type = "write"; - else - watch_type = "not read or write"; - return watch_type; -} -#endif /* DBUS_ENABLE_VERBOSE_MODE */ -#endif /* MAINLOOP_SPEW */ - struct DBusLoop { int refcount; @@ -675,7 +654,7 @@ _dbus_loop_iterate (DBusLoop *loop, timeout = MIN (timeout, _dbus_get_oom_wait ()); #if MAINLOOP_SPEW - _dbus_verbose (" polling on %d descriptors timeout %ld\n", n_fds, timeout); + _dbus_verbose (" polling on %d descriptors timeout %ld\n", _DBUS_N_ELEMENTS (ready_fds), timeout); #endif n_ready = _dbus_socket_set_poll (loop->socket_set, ready_fds, @@ -922,7 +901,7 @@ _dbus_loop_quit (DBusLoop *loop) int _dbus_get_oom_wait (void) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /* make tests go fast */ return 0; #else diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c index 88b19f36..eafc2a9a 100644 --- a/dbus/dbus-marshal-basic.c +++ b/dbus/dbus-marshal-basic.c @@ -58,12 +58,10 @@ _DBUS_ASSERT_ALIGNMENT (dbus_bool_t, <=, 4); _DBUS_STATIC_ASSERT (sizeof (double) == 8); _DBUS_ASSERT_ALIGNMENT (double, <=, 8); -#ifdef DBUS_HAVE_INT64 _DBUS_STATIC_ASSERT (sizeof (dbus_int64_t) == 8); _DBUS_ASSERT_ALIGNMENT (dbus_int64_t, <=, 8); _DBUS_STATIC_ASSERT (sizeof (dbus_uint64_t) == 8); _DBUS_ASSERT_ALIGNMENT (dbus_uint64_t, <=, 8); -#endif _DBUS_STATIC_ASSERT (sizeof (DBusBasicValue) >= 8); /* The alignment of a DBusBasicValue might conceivably be > 8 because of the @@ -120,15 +118,10 @@ pack_8_octets (DBusBasicValue value, { _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data); -#ifdef DBUS_HAVE_INT64 if ((byte_order) == DBUS_LITTLE_ENDIAN) *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64); else *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64); -#else - *(DBus8ByteStruct*)data = value.eight; - swap_8_octets ((DBusBasicValue*)data, byte_order); -#endif } /** @@ -146,65 +139,16 @@ _dbus_pack_uint32 (dbus_uint32_t value, pack_4_octets (value, byte_order, data); } -#ifndef DBUS_HAVE_INT64 -/* from ORBit */ -static void -swap_bytes (unsigned char *data, - unsigned int len) -{ - unsigned char *p1 = data; - unsigned char *p2 = data + len - 1; - - while (p1 < p2) - { - unsigned char tmp = *p1; - *p1 = *p2; - *p2 = tmp; - - --p2; - ++p1; - } -} -#endif /* !DBUS_HAVE_INT64 */ - static void swap_8_octets (DBusBasicValue *value, int byte_order) { if (byte_order != DBUS_COMPILER_BYTE_ORDER) { -#ifdef DBUS_HAVE_INT64 value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64); -#else - swap_bytes (&value->bytes, 8); -#endif } } -#if 0 -static DBusBasicValue -unpack_8_octets (int byte_order, - const unsigned char *data) -{ - DBusBasicValue r; - - _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data); - _dbus_assert (sizeof (r) == 8); - -#ifdef DBUS_HAVE_INT64 - if (byte_order == DBUS_LITTLE_ENDIAN) - r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data); - else - r.u64 = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data); -#else - r.eight = *(DBus8ByteStruct*)data; - swap_8_octets (&r, byte_order); -#endif - - return r; -} -#endif - #ifndef _dbus_unpack_uint16 /** * Unpacks a 16 bit unsigned integer from a data pointer @@ -601,15 +545,10 @@ _dbus_marshal_read_basic (const DBusString *str, { volatile dbus_uint64_t *vp = value; pos = _DBUS_ALIGN_VALUE (pos, 8); -#ifdef DBUS_HAVE_INT64 if (byte_order != DBUS_COMPILER_BYTE_ORDER) *vp = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos)); else *vp = *(dbus_uint64_t*)(str_data + pos); -#else - *vp = *(DBus8ByteStruct*) (str_data + pos); - swap_8_octets (vp, byte_order); -#endif pos += 8; } break; @@ -965,11 +904,7 @@ _dbus_swap_array (unsigned char *data, { while (d != end) { -#ifdef DBUS_HAVE_INT64 *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d)); -#else - swap_8_bytes ((DBusBasicValue*) d); -#endif d += 8; } } @@ -1501,7 +1436,7 @@ _dbus_first_type_in_signature_c_str (const char *str, /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> @@ -1674,12 +1609,10 @@ _dbus_marshal_test (void) unsigned char array1[5] = { 3, 4, 0, 1, 9 }; dbus_int16_t array2[3] = { 124, 457, 780 }; dbus_int32_t array4[3] = { 123, 456, 789 }; -#ifdef DBUS_HAVE_INT64 dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), DBUS_INT64_CONSTANT (0x456ffffffff), DBUS_INT64_CONSTANT (0x789ffffffff) }; dbus_int64_t *v_ARRAY_INT64; -#endif unsigned char *v_ARRAY_BYTE; dbus_int16_t *v_ARRAY_INT16; dbus_uint16_t *v_ARRAY_UINT16; @@ -1735,7 +1668,6 @@ _dbus_marshal_test (void) MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678); MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678); -#ifdef DBUS_HAVE_INT64 /* Marshal signed integers */ MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)); MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)); @@ -1743,7 +1675,6 @@ _dbus_marshal_test (void) /* Marshal unsigned integers */ MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)); MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)); -#endif /* DBUS_HAVE_INT64 */ /* Marshal byte */ MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5); @@ -1785,10 +1716,8 @@ _dbus_marshal_test (void) MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1); MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1); -#ifdef DBUS_HAVE_INT64 MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8); MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8); -#endif #if 0 @@ -1796,7 +1725,6 @@ _dbus_marshal_test (void) * FIXME restore the set/pack tests */ -#ifdef DBUS_HAVE_INT64 /* set/pack 64-bit integers */ _dbus_string_set_length (&str, 8); @@ -1867,7 +1795,6 @@ _dbus_marshal_test (void) _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == _dbus_unpack_uint64 (DBUS_BIG_ENDIAN, _dbus_string_get_const_data (&str))); -#endif /* DBUS_HAVE_INT64 */ /* set/pack 32-bit integers */ _dbus_string_set_length (&str, 4); @@ -1992,4 +1919,4 @@ _dbus_marshal_test (void) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h index 034fdaba..9df67cb8 100644 --- a/dbus/dbus-marshal-basic.h +++ b/dbus/dbus-marshal-basic.h @@ -57,8 +57,6 @@ #endif /* HAVE_BYTESWAP_H */ -#ifdef DBUS_HAVE_INT64 - #ifdef HAVE_BYTESWAP_H #define DBUS_UINT64_SWAP_LE_BE_CONSTANT(val) bswap_64(val) #else /* HAVE_BYTESWAP_H */ @@ -80,7 +78,6 @@ (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00ff000000000000)) >> 40) | \ (((dbus_uint64_t) (val) & \ (dbus_uint64_t) DBUS_UINT64_CONSTANT (0xff00000000000000)) >> 56))) -#endif /* DBUS_HAVE_INT64 */ #endif /* HAVE_BYTESWAP_H */ @@ -90,10 +87,8 @@ #define DBUS_UINT32_SWAP_LE_BE(val) (DBUS_UINT32_SWAP_LE_BE_CONSTANT (val)) #define DBUS_INT32_SWAP_LE_BE(val) ((dbus_int32_t)DBUS_UINT32_SWAP_LE_BE_CONSTANT (val)) -#ifdef DBUS_HAVE_INT64 -# define DBUS_UINT64_SWAP_LE_BE(val) (DBUS_UINT64_SWAP_LE_BE_CONSTANT (val)) -# define DBUS_INT64_SWAP_LE_BE(val) ((dbus_int64_t)DBUS_UINT64_SWAP_LE_BE_CONSTANT (val)) -#endif /* DBUS_HAVE_INT64 */ +#define DBUS_UINT64_SWAP_LE_BE(val) (DBUS_UINT64_SWAP_LE_BE_CONSTANT (val)) +#define DBUS_INT64_SWAP_LE_BE(val) ((dbus_int64_t)DBUS_UINT64_SWAP_LE_BE_CONSTANT (val)) #ifdef WORDS_BIGENDIAN @@ -105,12 +100,10 @@ # define DBUS_UINT32_TO_BE(val) ((dbus_uint32_t) (val)) # define DBUS_INT32_TO_LE(val) (DBUS_INT32_SWAP_LE_BE (val)) # define DBUS_UINT32_TO_LE(val) (DBUS_UINT32_SWAP_LE_BE (val)) -# ifdef DBUS_HAVE_INT64 -# define DBUS_INT64_TO_BE(val) ((dbus_int64_t) (val)) -# define DBUS_UINT64_TO_BE(val) ((dbus_uint64_t) (val)) -# define DBUS_INT64_TO_LE(val) (DBUS_INT64_SWAP_LE_BE (val)) -# define DBUS_UINT64_TO_LE(val) (DBUS_UINT64_SWAP_LE_BE (val)) -# endif /* DBUS_HAVE_INT64 */ +# define DBUS_INT64_TO_BE(val) ((dbus_int64_t) (val)) +# define DBUS_UINT64_TO_BE(val) ((dbus_uint64_t) (val)) +# define DBUS_INT64_TO_LE(val) (DBUS_INT64_SWAP_LE_BE (val)) +# define DBUS_UINT64_TO_LE(val) (DBUS_UINT64_SWAP_LE_BE (val)) #else /* WORDS_BIGENDIAN */ @@ -122,12 +115,10 @@ # define DBUS_UINT32_TO_LE(val) ((dbus_uint32_t) (val)) # define DBUS_INT32_TO_BE(val) ((dbus_int32_t) DBUS_UINT32_SWAP_LE_BE (val)) # define DBUS_UINT32_TO_BE(val) (DBUS_UINT32_SWAP_LE_BE (val)) -# ifdef DBUS_HAVE_INT64 -# define DBUS_INT64_TO_LE(val) ((dbus_int64_t) (val)) -# define DBUS_UINT64_TO_LE(val) ((dbus_uint64_t) (val)) -# define DBUS_INT64_TO_BE(val) ((dbus_int64_t) DBUS_UINT64_SWAP_LE_BE (val)) -# define DBUS_UINT64_TO_BE(val) (DBUS_UINT64_SWAP_LE_BE (val)) -# endif /* DBUS_HAVE_INT64 */ +# define DBUS_INT64_TO_LE(val) ((dbus_int64_t) (val)) +# define DBUS_UINT64_TO_LE(val) ((dbus_uint64_t) (val)) +# define DBUS_INT64_TO_BE(val) ((dbus_int64_t) DBUS_UINT64_SWAP_LE_BE (val)) +# define DBUS_UINT64_TO_BE(val) (DBUS_UINT64_SWAP_LE_BE (val)) #endif /* The transformation is symmetric, so the FROM just maps to the TO. */ @@ -139,12 +130,10 @@ #define DBUS_UINT32_FROM_LE(val) (DBUS_UINT32_TO_LE (val)) #define DBUS_INT32_FROM_BE(val) (DBUS_INT32_TO_BE (val)) #define DBUS_UINT32_FROM_BE(val) (DBUS_UINT32_TO_BE (val)) -#ifdef DBUS_HAVE_INT64 -# define DBUS_INT64_FROM_LE(val) (DBUS_INT64_TO_LE (val)) -# define DBUS_UINT64_FROM_LE(val) (DBUS_UINT64_TO_LE (val)) -# define DBUS_INT64_FROM_BE(val) (DBUS_INT64_TO_BE (val)) -# define DBUS_UINT64_FROM_BE(val) (DBUS_UINT64_TO_BE (val)) -#endif /* DBUS_HAVE_INT64 */ +#define DBUS_INT64_FROM_LE(val) (DBUS_INT64_TO_LE (val)) +#define DBUS_UINT64_FROM_LE(val) (DBUS_UINT64_TO_LE (val)) +#define DBUS_INT64_FROM_BE(val) (DBUS_INT64_TO_BE (val)) +#define DBUS_UINT64_FROM_BE(val) (DBUS_UINT64_TO_BE (val)) #ifdef DBUS_DISABLE_ASSERT #define _dbus_unpack_uint16(byte_order, data) \ diff --git a/dbus/dbus-marshal-byteswap-util.c b/dbus/dbus-marshal-byteswap-util.c index edb74cad..57874859 100644 --- a/dbus/dbus-marshal-byteswap-util.c +++ b/dbus/dbus-marshal-byteswap-util.c @@ -23,7 +23,7 @@ #include <config.h> -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-marshal-byteswap.h" #include "dbus-test.h" #include <stdio.h> @@ -102,4 +102,4 @@ _dbus_marshal_byteswap_test (void) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c index 22d7e22b..e6711be6 100644 --- a/dbus/dbus-marshal-byteswap.c +++ b/dbus/dbus-marshal-byteswap.c @@ -73,11 +73,7 @@ byteswap_body_helper (DBusTypeReader *reader, case DBUS_TYPE_DOUBLE: { p = _DBUS_ALIGN_ADDRESS (p, 8); -#ifdef DBUS_HAVE_INT64 *((dbus_uint64_t*)p) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)p)); -#else - _dbus_swap_array (p, 1, 8); -#endif p += 8; } break; diff --git a/dbus/dbus-marshal-header.c b/dbus/dbus-marshal-header.c index 88887a82..48151c62 100644 --- a/dbus/dbus-marshal-header.c +++ b/dbus/dbus-marshal-header.c @@ -276,6 +276,7 @@ _dbus_header_cache_known_nonexistent (DBusHeader *header, * Writes a struct of { byte, variant } with the given basic type. * * @param writer the writer (should be ready to write a struct) + * @param field the header field * @param type the type of the value * @param value the value as for _dbus_marshal_set_basic() * @returns #FALSE if no memory @@ -336,6 +337,7 @@ write_basic_field (DBusTypeWriter *writer, * Sets a struct of { byte, variant } with the given basic type. * * @param reader the reader (should be iterating over the array pointing at the field to set) + * @param field the header field * @param type the type of the value * @param value the value as for _dbus_marshal_set_basic() * @param realign_root where to realign from @@ -452,7 +454,6 @@ _dbus_header_reinit (DBusHeader *header) * to make the header valid, you have to call _dbus_header_create(). * * @param header header to initialize - * @param byte_order byte order of the header * @returns #FALSE if not enough memory */ dbus_bool_t @@ -514,6 +515,7 @@ _dbus_header_copy (const DBusHeader *header, * sense, and passing them in will trigger an assertion failure. * * @param header the header + * @param byte_order byte order of the header * @param message_type the message type * @param destination destination field or #NULL * @param path path field or #NULL diff --git a/dbus/dbus-marshal-recursive-util.c b/dbus/dbus-marshal-recursive-util.c index 95124140..0e2b4201 100644 --- a/dbus/dbus-marshal-recursive-util.c +++ b/dbus/dbus-marshal-recursive-util.c @@ -23,7 +23,7 @@ #include <config.h> -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-marshal-recursive.h" #include "dbus-marshal-basic.h" @@ -34,13 +34,7 @@ static void basic_value_zero (DBusBasicValue *value) { - -#ifdef DBUS_HAVE_INT64 value->u64 = 0; -#else - value->eight.first32 = 0; - value->eight.second32 = 0; -#endif } static dbus_bool_t @@ -56,12 +50,7 @@ basic_value_equal (int type, } else { -#ifdef DBUS_HAVE_INT64 return lhs->u64 == rhs->u64; -#else - return lhs->eight.first32 == rhs->eight.first32 && - lhs->eight.second32 == rhs->eight.second32; -#endif } } @@ -1785,10 +1774,13 @@ make_and_run_test_nodes (void) start_next_test ("All values in one big toplevel %d iteration\n", 1); { TestTypeNode *nodes[N_VALUES]; + TestTypeNode *node; i = 0; - while ((nodes[i] = value_generator (&i))) - ; + while ((node = value_generator (&i))) + { + nodes[i - 1] = node; + } run_test_nodes (nodes, N_VALUES); @@ -2337,7 +2329,6 @@ int32_read_multi (TestTypeNode *node, return TRUE; } -#ifdef DBUS_HAVE_INT64 static dbus_int64_t int64_from_seed (int seed) { @@ -2351,7 +2342,6 @@ int64_from_seed (int seed) return v; } -#endif static dbus_bool_t int64_write_value (TestTypeNode *node, @@ -2359,7 +2349,6 @@ int64_write_value (TestTypeNode *node, DBusTypeWriter *writer, int seed) { -#ifdef DBUS_HAVE_INT64 /* also used for uint64 */ dbus_int64_t v; @@ -2368,9 +2357,6 @@ int64_write_value (TestTypeNode *node, return _dbus_type_writer_write_basic (writer, node->klass->typecode, &v); -#else - return TRUE; -#endif } static dbus_bool_t @@ -2378,7 +2364,6 @@ int64_read_value (TestTypeNode *node, DBusTypeReader *reader, int seed) { -#ifdef DBUS_HAVE_INT64 /* also used for uint64 */ dbus_int64_t v; @@ -2390,9 +2375,6 @@ int64_read_value (TestTypeNode *node, _dbus_assert (v == int64_from_seed (seed)); return TRUE; -#else - return TRUE; -#endif } static dbus_bool_t @@ -2401,7 +2383,6 @@ int64_set_value (TestTypeNode *node, DBusTypeReader *realign_root, int seed) { -#ifdef DBUS_HAVE_INT64 /* also used for uint64 */ dbus_int64_t v; @@ -2410,9 +2391,6 @@ int64_set_value (TestTypeNode *node, return _dbus_type_reader_set_basic (reader, &v, realign_root); -#else - return TRUE; -#endif } #define MAX_SAMPLE_STRING_LEN 10 @@ -3574,4 +3552,4 @@ container_destroy (TestTypeNode *node) #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-marshal-validate-util.c b/dbus/dbus-marshal-validate-util.c index 81135bcf..d52cb6d8 100644 --- a/dbus/dbus-marshal-validate-util.c +++ b/dbus/dbus-marshal-validate-util.c @@ -22,7 +22,7 @@ */ #include <config.h> -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -585,4 +585,4 @@ _dbus_marshal_validate_test (void) #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c index a033b540..22e80727 100644 --- a/dbus/dbus-memory.c +++ b/dbus/dbus-memory.c @@ -26,6 +26,7 @@ #include "dbus-internals.h" #include "dbus-sysdeps.h" #include "dbus-list.h" +#include "dbus-threads.h" #include <stdlib.h> /** @@ -96,7 +97,7 @@ * @{ */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS static dbus_bool_t debug_initialized = FALSE; static int fail_nth = -1; static size_t fail_size = 0; @@ -239,7 +240,7 @@ _dbus_get_fail_alloc_failures (void) return n_failures_per_failure; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * Called when about to alloc some memory; if * it returns #TRUE, then the allocation should @@ -293,7 +294,7 @@ _dbus_decrement_fail_alloc_counter (void) return FALSE; } } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ /** * Get the number of outstanding malloc()'d blocks. @@ -459,7 +460,7 @@ set_guards (void *real_block, void* dbus_malloc (size_t bytes) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) @@ -471,7 +472,7 @@ dbus_malloc (size_t bytes) if (bytes == 0) /* some system mallocs handle this, some don't */ return NULL; -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) @@ -498,7 +499,7 @@ dbus_malloc (size_t bytes) void *mem; mem = malloc (bytes); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (mem) { _dbus_atomic_inc (&n_blocks_outstanding); @@ -529,7 +530,7 @@ dbus_malloc (size_t bytes) void* dbus_malloc0 (size_t bytes) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) @@ -542,7 +543,7 @@ dbus_malloc0 (size_t bytes) if (bytes == 0) return NULL; -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) @@ -570,7 +571,7 @@ dbus_malloc0 (size_t bytes) void *mem; mem = calloc (bytes, 1); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (mem) { _dbus_atomic_inc (&n_blocks_outstanding); @@ -600,7 +601,7 @@ void* dbus_realloc (void *memory, size_t bytes) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) @@ -616,7 +617,7 @@ dbus_realloc (void *memory, dbus_free (memory); return NULL; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) @@ -676,7 +677,7 @@ dbus_realloc (void *memory, void *mem; mem = realloc (memory, bytes); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (mem == NULL && malloc_cannot_fail) { _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes); @@ -699,7 +700,7 @@ dbus_realloc (void *memory, void dbus_free (void *memory) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (guards) { check_guards (memory, TRUE); @@ -723,7 +724,7 @@ dbus_free (void *memory) if (memory) /* we guarantee it's safe to free (NULL) */ { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #ifdef DBUS_DISABLE_ASSERT _dbus_atomic_dec (&n_blocks_outstanding); #else @@ -794,7 +795,7 @@ struct ShutdownClosure void *data; /**< Data for function */ }; -_DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs); +/* Protected by _DBUS_LOCK (shutdown_funcs) */ static ShutdownClosure *registered_globals = NULL; /** @@ -809,6 +810,20 @@ dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction func, void *data) { + dbus_bool_t ok; + + if (!_DBUS_LOCK (shutdown_funcs)) + return FALSE; + + ok = _dbus_register_shutdown_func_unlocked (func, data); + _DBUS_UNLOCK (shutdown_funcs); + return ok; +} + +dbus_bool_t +_dbus_register_shutdown_func_unlocked (DBusShutdownFunction func, + void *data) +{ ShutdownClosure *c; c = dbus_new (ShutdownClosure, 1); @@ -819,13 +834,9 @@ _dbus_register_shutdown_func (DBusShutdownFunction func, c->func = func; c->data = data; - _DBUS_LOCK (shutdown_funcs); - c->next = registered_globals; registered_globals = c; - _DBUS_UNLOCK (shutdown_funcs); - return TRUE; } @@ -845,7 +856,7 @@ _dbus_register_shutdown_func (DBusShutdownFunction func, * can be useful to free these internal data structures. * * dbus_shutdown() does NOT free memory that was returned - * to the application. It only returns libdbus-internal + * to the application. It only frees libdbus-internal * data structures. * * You MUST free all memory and release all reference counts @@ -890,12 +901,18 @@ dbus_shutdown (void) dbus_free (c); } + /* We wrap this in the thread-initialization lock because + * dbus_threads_init() uses the current generation to tell whether + * we're initialized, so we need to make sure that un-initializing + * propagates into all threads. */ + _dbus_threads_lock_platform_specific (); _dbus_current_generation += 1; + _dbus_threads_unlock_platform_specific (); } /** @} */ /** End of public API docs block */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" /** diff --git a/dbus/dbus-mempool.c b/dbus/dbus-mempool.c index 33aabf9c..52466151 100644 --- a/dbus/dbus-mempool.c +++ b/dbus/dbus-mempool.c @@ -173,7 +173,7 @@ _dbus_mem_pool_new (int element_size, _dbus_assert ((pool->block_size % pool->element_size) == 0); - VALGRIND_CREATE_MEMPOOL (pool, 0, zero_elements) + VALGRIND_CREATE_MEMPOOL (pool, 0, zero_elements); return pool; } @@ -188,7 +188,7 @@ _dbus_mem_pool_free (DBusMemPool *pool) { DBusMemBlock *block; - VALGRIND_DESTROY_MEMPOOL (pool) + VALGRIND_DESTROY_MEMPOOL (pool); block = pool->blocks; while (block != NULL) @@ -213,7 +213,7 @@ _dbus_mem_pool_free (DBusMemPool *pool) void* _dbus_mem_pool_alloc (DBusMemPool *pool) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (_dbus_disable_mem_pools ()) { DBusMemBlock *block; @@ -241,7 +241,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) pool->allocated_elements += 1; VALGRIND_MEMPOOL_ALLOC (pool, (void *) &block->elements[0], - pool->element_size) + pool->element_size); return (void*) &block->elements[0]; } else @@ -261,7 +261,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) pool->free_elements = pool->free_elements->next; - VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size) + VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size); if (pool->zero_elements) memset (element, '\0', pool->element_size); @@ -280,7 +280,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) /* Need a new block */ DBusMemBlock *block; int alloc_size; -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS int saved_counter; #endif @@ -294,7 +294,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING + pool->block_size; -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /* We save/restore the counter, so that memory pools won't * cause a given function to have different number of * allocations on different invocations. i.e. when testing @@ -310,7 +310,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) else block = dbus_malloc (alloc_size); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_set_fail_alloc_counter (saved_counter); _dbus_assert (saved_counter == _dbus_get_fail_alloc_counter ()); #endif @@ -329,7 +329,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) pool->allocated_elements += 1; - VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size) + VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size); return element; } } @@ -347,9 +347,9 @@ dbus_bool_t _dbus_mem_pool_dealloc (DBusMemPool *pool, void *element) { - VALGRIND_MEMPOOL_FREE (pool, element) + VALGRIND_MEMPOOL_FREE (pool, element); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (_dbus_disable_mem_pools ()) { DBusMemBlock *block; @@ -393,7 +393,7 @@ _dbus_mem_pool_dealloc (DBusMemPool *pool, freed = element; /* used for internal mempool administration */ - VALGRIND_MAKE_MEM_UNDEFINED (freed, sizeof (freed)); + VALGRIND_MAKE_MEM_UNDEFINED (freed, sizeof (*freed)); freed->next = pool->free_elements; pool->free_elements = freed; @@ -449,7 +449,7 @@ _dbus_mem_pool_get_stats (DBusMemPool *pool, /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> #include <time.h> @@ -459,8 +459,10 @@ time_for_size (int size) { int i; int j; +#ifdef DBUS_ENABLE_VERBOSE_MODE clock_t start; clock_t end; +#endif #define FREE_ARRAY_SIZE 512 #define N_ITERATIONS FREE_ARRAY_SIZE * 512 void *to_free[FREE_ARRAY_SIZE]; @@ -470,8 +472,10 @@ time_for_size (int size) _dbus_verbose (" malloc\n"); +#ifdef DBUS_ENABLE_VERBOSE_MODE start = clock (); - +#endif + i = 0; j = 0; while (i < N_ITERATIONS) @@ -496,6 +500,7 @@ time_for_size (int size) ++i; } +#ifdef DBUS_ENABLE_VERBOSE_MODE end = clock (); _dbus_verbose (" created/destroyed %d elements in %g seconds\n", @@ -506,6 +511,7 @@ time_for_size (int size) _dbus_verbose (" mempools\n"); start = clock (); +#endif pool = _dbus_mem_pool_new (size, FALSE); @@ -535,6 +541,7 @@ time_for_size (int size) _dbus_mem_pool_free (pool); +#ifdef DBUS_ENABLE_VERBOSE_MODE end = clock (); _dbus_verbose (" created/destroyed %d elements in %g seconds\n", @@ -543,6 +550,7 @@ time_for_size (int size) _dbus_verbose (" zeroed malloc\n"); start = clock (); +#endif i = 0; j = 0; @@ -568,6 +576,7 @@ time_for_size (int size) ++i; } +#ifdef DBUS_ENABLE_VERBOSE_MODE end = clock (); _dbus_verbose (" created/destroyed %d elements in %g seconds\n", @@ -576,6 +585,7 @@ time_for_size (int size) _dbus_verbose (" zeroed mempools\n"); start = clock (); +#endif pool = _dbus_mem_pool_new (size, TRUE); @@ -605,10 +615,12 @@ time_for_size (int size) _dbus_mem_pool_free (pool); +#ifdef DBUS_ENABLE_VERBOSE_MODE end = clock (); _dbus_verbose (" created/destroyed %d elements in %g seconds\n", N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC); +#endif } /** @@ -632,4 +644,4 @@ _dbus_mem_pool_test (void) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-message-factory.c b/dbus/dbus-message-factory.c index efa4e029..b742e4c1 100644 --- a/dbus/dbus-message-factory.c +++ b/dbus/dbus-message-factory.c @@ -24,7 +24,7 @@ #ifndef DOXYGEN_SHOULD_SKIP_THIS -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-message-factory.h" #include "dbus-message-private.h" #include "dbus-signature.h" @@ -1302,4 +1302,4 @@ _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter, #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-message-factory.h b/dbus/dbus-message-factory.h index b0747504..fd7a4764 100644 --- a/dbus/dbus-message-factory.h +++ b/dbus/dbus-message-factory.h @@ -24,7 +24,7 @@ #ifndef DBUS_MESSAGE_FACTORY_H #define DBUS_MESSAGE_FACTORY_H -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include <dbus/dbus-string.h> #include <dbus/dbus-marshal-basic.h> @@ -56,6 +56,6 @@ dbus_bool_t _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter, DBUS_END_DECLS -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ #endif /* DBUS_MESSAGE_FACTORY_H */ diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h index c1948732..5d6594e3 100644 --- a/dbus/dbus-message-internal.h +++ b/dbus/dbus-message-internal.h @@ -70,8 +70,7 @@ void _dbus_message_loader_unref (DBusMessageLoader void _dbus_message_loader_get_buffer (DBusMessageLoader *loader, DBusString **buffer); void _dbus_message_loader_return_buffer (DBusMessageLoader *loader, - DBusString *buffer, - int bytes_read); + DBusString *buffer); dbus_bool_t _dbus_message_loader_get_unix_fds (DBusMessageLoader *loader, int **fds, diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c index f7859520..f615af83 100644 --- a/dbus/dbus-message-util.c +++ b/dbus/dbus-message-util.c @@ -45,7 +45,7 @@ * @{ */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * Reads arguments from a message iterator given a variable argument * list. Only arguments of basic type and arrays of fixed-length @@ -76,11 +76,11 @@ dbus_message_iter_get_args (DBusMessageIter *iter, return retval; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include "dbus-message-factory.h" #include <stdio.h> @@ -493,7 +493,7 @@ dbus_internal_do_not_use_try_message_data (const DBusString *data, _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, _dbus_string_get_byte (data, i)); - _dbus_message_loader_return_buffer (loader, buffer, 1); + _dbus_message_loader_return_buffer (loader, buffer); } if (!check_loader_results (loader, expected_validity)) @@ -512,7 +512,7 @@ dbus_internal_do_not_use_try_message_data (const DBusString *data, _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_copy (data, 0, buffer, _dbus_string_get_length (buffer)); - _dbus_message_loader_return_buffer (loader, buffer, 1); + _dbus_message_loader_return_buffer (loader, buffer); } if (!check_loader_results (loader, expected_validity)) @@ -536,7 +536,7 @@ dbus_internal_do_not_use_try_message_data (const DBusString *data, if ((i+1) < len) _dbus_string_append_byte (buffer, _dbus_string_get_byte (data, i+1)); - _dbus_message_loader_return_buffer (loader, buffer, 1); + _dbus_message_loader_return_buffer (loader, buffer); } if (!check_loader_results (loader, expected_validity)) @@ -754,10 +754,8 @@ message_iter_test (DBusMessage *message) dbus_uint16_t v_UINT16; dbus_int32_t v_INT32; dbus_uint32_t v_UINT32; -#ifdef DBUS_HAVE_INT64 dbus_int64_t v_INT64; dbus_uint64_t v_UINT64; -#endif unsigned char v_BYTE; dbus_bool_t v_BOOLEAN; @@ -830,14 +828,12 @@ verify_test_message (DBusMessage *message) int our_uint32_array_len; dbus_int32_t *our_int32_array = (void*)0xdeadbeef; int our_int32_array_len; -#ifdef DBUS_HAVE_INT64 dbus_int64_t our_int64; dbus_uint64_t our_uint64; dbus_int64_t *our_uint64_array = (void*)0xdeadbeef; int our_uint64_array_len; const dbus_int64_t *our_int64_array = (void*)0xdeadbeef; int our_int64_array_len; -#endif const double *our_double_array = (void*)0xdeadbeef; int our_double_array_len; const unsigned char *our_byte_array = (void*)0xdeadbeef; @@ -854,10 +850,8 @@ verify_test_message (DBusMessage *message) DBUS_TYPE_UINT16, &our_uint16, DBUS_TYPE_INT32, &our_int, DBUS_TYPE_UINT32, &our_uint, -#ifdef DBUS_HAVE_INT64 DBUS_TYPE_INT64, &our_int64, DBUS_TYPE_UINT64, &our_uint64, -#endif DBUS_TYPE_STRING, &our_str, DBUS_TYPE_DOUBLE, &our_double, DBUS_TYPE_BOOLEAN, &our_bool, @@ -867,12 +861,10 @@ verify_test_message (DBusMessage *message) &our_uint32_array, &our_uint32_array_len, DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &our_int32_array, &our_int32_array_len, -#ifdef DBUS_HAVE_INT64 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &our_uint64_array, &our_uint64_array_len, DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &our_int64_array, &our_int64_array_len, -#endif DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &our_double_array, &our_double_array_len, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, @@ -900,12 +892,10 @@ verify_test_message (DBusMessage *message) if (our_uint != 0x12300042) _dbus_assert_not_reached ("uints differ!"); -#ifdef DBUS_HAVE_INT64 if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd)) _dbus_assert_not_reached ("64-bit integers differ!"); if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd)) _dbus_assert_not_reached ("64-bit unsigned integers differ!"); -#endif v_DOUBLE = 3.14159; if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double, v_DOUBLE)) @@ -937,7 +927,6 @@ verify_test_message (DBusMessage *message) our_int32_array[3] != -0x45678123) _dbus_assert_not_reached ("int array differs"); -#ifdef DBUS_HAVE_INT64 if (our_uint64_array_len != 4 || our_uint64_array[0] != 0x12345678 || our_uint64_array[1] != 0x23456781 || @@ -951,7 +940,6 @@ verify_test_message (DBusMessage *message) our_int64_array[2] != 0x34567812 || our_int64_array[3] != -0x45678123) _dbus_assert_not_reached ("int64 array differs"); -#endif /* DBUS_HAVE_INT64 */ if (our_double_array_len != 3) _dbus_assert_not_reached ("double array had wrong length"); @@ -1003,6 +991,161 @@ verify_test_message (DBusMessage *message) _dbus_assert_not_reached ("Didn't reach end of arguments"); } +static void +verify_test_message_args_ignored (DBusMessage *message) +{ + DBusMessageIter iter; + DBusError error = DBUS_ERROR_INIT; + dbus_uint32_t our_uint; + DBusInitialFDs *initial_fds; + + initial_fds = _dbus_check_fdleaks_enter (); + + /* parse with empty signature: "" */ + dbus_message_iter_init (message, &iter); + if (!dbus_message_iter_get_args (&iter, &error, + DBUS_TYPE_INVALID)) + { + _dbus_warn ("error: %s - %s\n", error.name, + (error.message != NULL) ? error.message : "no message"); + } + else + { + _dbus_assert (!dbus_error_is_set (&error)); + _dbus_verbose ("arguments ignored.\n"); + } + + /* parse with shorter signature: "u" */ + dbus_message_iter_init (message, &iter); + if (!dbus_message_iter_get_args (&iter, &error, + DBUS_TYPE_UINT32, &our_uint, + DBUS_TYPE_INVALID)) + { + _dbus_warn ("error: %s - %s\n", error.name, + (error.message != NULL) ? error.message : "no message"); + } + else + { + _dbus_assert (!dbus_error_is_set (&error)); + _dbus_verbose ("arguments ignored.\n"); + } + + _dbus_check_fdleaks_leave (initial_fds); +} + +static void +verify_test_message_memleak (DBusMessage *message) +{ + DBusMessageIter iter; + DBusError error = DBUS_ERROR_INIT; + dbus_uint32_t our_uint1; + dbus_uint32_t our_uint2; + dbus_uint32_t our_uint3; + char **our_string_array1; + int our_string_array_len1; + char **our_string_array2; + int our_string_array_len2; + int our_unix_fd1; + int our_unix_fd2; + DBusInitialFDs *initial_fds; + + initial_fds = _dbus_check_fdleaks_enter (); + + /* parse with wrong signature: "uashuu" */ + dbus_error_free (&error); + dbus_message_iter_init (message, &iter); + if (!dbus_message_iter_get_args (&iter, &error, + DBUS_TYPE_UINT32, &our_uint1, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &our_string_array1, &our_string_array_len1, +#ifdef HAVE_UNIX_FD_PASSING + DBUS_TYPE_UNIX_FD, &our_unix_fd1, +#endif + DBUS_TYPE_UINT32, &our_uint2, + DBUS_TYPE_UINT32, &our_uint3, + DBUS_TYPE_INVALID)) + { + _dbus_verbose ("expected error: %s - %s\n", error.name, + (error.message != NULL) ? error.message : "no message"); + /* ensure array of string and unix fd not leaked */ + _dbus_assert (our_string_array1 == NULL); +#ifdef HAVE_UNIX_FD_PASSING + _dbus_assert (our_unix_fd1 == -1); +#endif + } + else + { + _dbus_warn ("error: parse with wrong signature: 'uashuu'.\n"); + } + + /* parse with wrong signature: "uashuashu" */ + dbus_message_iter_init (message, &iter); + dbus_error_free (&error); + if (!dbus_message_iter_get_args (&iter, &error, + DBUS_TYPE_UINT32, &our_uint1, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &our_string_array1, &our_string_array_len1, +#ifdef HAVE_UNIX_FD_PASSING + DBUS_TYPE_UNIX_FD, &our_unix_fd1, +#endif + DBUS_TYPE_UINT32, &our_uint2, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &our_string_array2, &our_string_array_len2, +#ifdef HAVE_UNIX_FD_PASSING + DBUS_TYPE_UNIX_FD, &our_unix_fd2, +#endif + DBUS_TYPE_UINT32, &our_uint3, + DBUS_TYPE_INVALID)) + { + _dbus_verbose ("expected error: %s - %s\n", error.name, + (error.message != NULL) ? error.message : "no message"); + /* ensure array of string and unix fd not leaked */ + _dbus_assert (our_string_array1 == NULL); + _dbus_assert (our_string_array2 == NULL); +#ifdef HAVE_UNIX_FD_PASSING + _dbus_assert (our_unix_fd1 == -1); + _dbus_assert (our_unix_fd2 == -1); +#endif + } + else + { + _dbus_warn ("error: parse with wrong signature: 'uashuashu'.\n"); + } + + /* parse with correct signature: "uashuash" */ + dbus_message_iter_init (message, &iter); + dbus_error_free (&error); + if (!dbus_message_iter_get_args (&iter, &error, + DBUS_TYPE_UINT32, &our_uint1, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &our_string_array1, &our_string_array_len1, +#ifdef HAVE_UNIX_FD_PASSING + DBUS_TYPE_UNIX_FD, &our_unix_fd1, +#endif + DBUS_TYPE_UINT32, &our_uint2, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &our_string_array2, &our_string_array_len2, +#ifdef HAVE_UNIX_FD_PASSING + DBUS_TYPE_UNIX_FD, &our_unix_fd2, +#endif + DBUS_TYPE_INVALID)) + { + _dbus_warn ("error: %s - %s\n", error.name, + (error.message != NULL) ? error.message : "no message"); + _dbus_assert_not_reached ("Could not get arguments"); + } + else + { + dbus_free_string_array (our_string_array1); + dbus_free_string_array (our_string_array2); +#ifdef HAVE_UNIX_FD_PASSING + _dbus_close (our_unix_fd1, &error); + _dbus_close (our_unix_fd2, &error); +#endif + } + _dbus_check_fdleaks_leave (initial_fds); +} + /** * @ingroup DBusMessageInternals * Unit test for DBusMessage. @@ -1025,16 +1168,16 @@ _dbus_message_test (const char *test_data_dir) { 0x12345678, -0x23456781, 0x34567812, -0x45678123 }; const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array; const dbus_int32_t *v_ARRAY_INT32 = our_int32_array; -#ifdef DBUS_HAVE_INT64 const dbus_uint64_t our_uint64_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 }; const dbus_int64_t our_int64_array[] = { 0x12345678, -0x23456781, 0x34567812, -0x45678123 }; const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array; const dbus_int64_t *v_ARRAY_INT64 = our_int64_array; -#endif const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" }; + const char *our_string_array1[] = { "foo", "Bar", "", "Woo woo Woo woo" }; const char **v_ARRAY_STRING = our_string_array; + const char **v1_ARRAY_STRING = our_string_array1; const double our_double_array[] = { 0.1234, 9876.54321, -300.0 }; const double *v_ARRAY_DOUBLE = our_double_array; const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 }; @@ -1049,16 +1192,16 @@ _dbus_message_test (const char *test_data_dir) dbus_uint16_t v_UINT16; dbus_int32_t v_INT32; dbus_uint32_t v_UINT32; -#ifdef DBUS_HAVE_INT64 + dbus_uint32_t v1_UINT32; dbus_int64_t v_INT64; dbus_uint64_t v_UINT64; -#endif unsigned char v_BYTE; unsigned char v2_BYTE; dbus_bool_t v_BOOLEAN; DBusMessageIter iter, array_iter, struct_iter; #ifdef HAVE_UNIX_FD_PASSING int v_UNIX_FD; + int v1_UNIX_FD; #endif char **decomposed; DBusInitialFDs *initial_fds; @@ -1201,10 +1344,8 @@ _dbus_message_test (const char *test_data_dir) v_UINT16 = 0x123; v_INT32 = -0x12345678; v_UINT32 = 0x12300042; -#ifdef DBUS_HAVE_INT64 v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd); v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd); -#endif v_STRING = "Test string"; v_DOUBLE = 3.14159; v_BOOLEAN = TRUE; @@ -1212,6 +1353,7 @@ _dbus_message_test (const char *test_data_dir) v2_BYTE = 24; #ifdef HAVE_UNIX_FD_PASSING v_UNIX_FD = 1; + v1_UNIX_FD = 2; #endif dbus_message_append_args (message, @@ -1219,10 +1361,8 @@ _dbus_message_test (const char *test_data_dir) DBUS_TYPE_UINT16, &v_UINT16, DBUS_TYPE_INT32, &v_INT32, DBUS_TYPE_UINT32, &v_UINT32, -#ifdef DBUS_HAVE_INT64 DBUS_TYPE_INT64, &v_INT64, DBUS_TYPE_UINT64, &v_UINT64, -#endif DBUS_TYPE_STRING, &v_STRING, DBUS_TYPE_DOUBLE, &v_DOUBLE, DBUS_TYPE_BOOLEAN, &v_BOOLEAN, @@ -1232,12 +1372,10 @@ _dbus_message_test (const char *test_data_dir) _DBUS_N_ELEMENTS (our_uint32_array), DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32, _DBUS_N_ELEMENTS (our_int32_array), -#ifdef DBUS_HAVE_INT64 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64, _DBUS_N_ELEMENTS (our_uint64_array), DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64, _DBUS_N_ELEMENTS (our_int64_array), -#endif DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE, _DBUS_N_ELEMENTS (our_double_array), DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE, @@ -1254,10 +1392,8 @@ _dbus_message_test (const char *test_data_dir) sig[i++] = DBUS_TYPE_UINT16; sig[i++] = DBUS_TYPE_INT32; sig[i++] = DBUS_TYPE_UINT32; -#ifdef DBUS_HAVE_INT64 sig[i++] = DBUS_TYPE_INT64; sig[i++] = DBUS_TYPE_UINT64; -#endif sig[i++] = DBUS_TYPE_STRING; sig[i++] = DBUS_TYPE_DOUBLE; sig[i++] = DBUS_TYPE_BOOLEAN; @@ -1267,12 +1403,10 @@ _dbus_message_test (const char *test_data_dir) sig[i++] = DBUS_TYPE_UINT32; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_INT32; -#ifdef DBUS_HAVE_INT64 sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_UINT64; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_INT64; -#endif sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_DOUBLE; sig[i++] = DBUS_TYPE_ARRAY; @@ -1353,7 +1487,7 @@ _dbus_message_test (const char *test_data_dir) _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, data[i]); - _dbus_message_loader_return_buffer (loader, buffer, 1); + _dbus_message_loader_return_buffer (loader, buffer); } /* Write the body data one byte at a time */ @@ -1364,7 +1498,7 @@ _dbus_message_test (const char *test_data_dir) _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, data[i]); - _dbus_message_loader_return_buffer (loader, buffer, 1); + _dbus_message_loader_return_buffer (loader, buffer); } #ifdef HAVE_UNIX_FD_PASSING @@ -1489,6 +1623,51 @@ _dbus_message_test (const char *test_data_dir) dbus_message_unref (message); + /* Check we should not leak array of string or unix fd, fd.o#21259 */ + message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService", + "/org/freedesktop/TestPath", + "Foo.TestInterface", + "Method"); + + /* signature "uashuash" */ + dbus_message_append_args (message, + DBUS_TYPE_UINT32, &v_UINT32, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING, + _DBUS_N_ELEMENTS (our_string_array), +#ifdef HAVE_UNIX_FD_PASSING + DBUS_TYPE_UNIX_FD, &v_UNIX_FD, +#endif + DBUS_TYPE_UINT32, &v1_UINT32, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v1_ARRAY_STRING, + _DBUS_N_ELEMENTS (our_string_array1), +#ifdef HAVE_UNIX_FD_PASSING + DBUS_TYPE_UNIX_FD, &v1_UNIX_FD, +#endif + + DBUS_TYPE_INVALID); + + i = 0; + sig[i++] = DBUS_TYPE_UINT32; + sig[i++] = DBUS_TYPE_ARRAY; + sig[i++] = DBUS_TYPE_STRING; +#ifdef HAVE_UNIX_FD_PASSING + sig[i++] = DBUS_TYPE_UNIX_FD; +#endif + sig[i++] = DBUS_TYPE_UINT32; + sig[i++] = DBUS_TYPE_ARRAY; + sig[i++] = DBUS_TYPE_STRING; +#ifdef HAVE_UNIX_FD_PASSING + sig[i++] = DBUS_TYPE_UNIX_FD; +#endif + sig[i++] = DBUS_TYPE_INVALID; + + _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig)); + + verify_test_message_args_ignored (message); + verify_test_message_memleak (message); + + dbus_message_unref (message); + /* Load all the sample messages from the message factory */ { DBusMessageDataIter diter; @@ -1542,4 +1721,4 @@ _dbus_message_test (const char *test_data_dir) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index f48977ca..2c30482c 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -56,7 +56,7 @@ static void dbus_message_finalize (DBusMessage *message); * @{ */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS static dbus_bool_t _dbus_enable_message_cache (void) { @@ -462,7 +462,7 @@ set_or_delete_string_field (DBusMessage *message, /** Avoid caching too many messages */ #define MAX_MESSAGE_CACHE_SIZE 5 -_DBUS_DEFINE_GLOBAL_LOCK (message_cache); +/* Protected by _DBUS_LOCK (message_cache) */ static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; static int message_cache_count = 0; static dbus_bool_t message_cache_shutdown_registered = FALSE; @@ -472,7 +472,9 @@ dbus_message_cache_shutdown (void *data) { int i; - _DBUS_LOCK (message_cache); + if (!_DBUS_LOCK (message_cache)) + _dbus_assert_not_reached ("we would have initialized global locks " + "before registering a shutdown function"); i = 0; while (i < MAX_MESSAGE_CACHE_SIZE) @@ -504,7 +506,12 @@ dbus_message_get_cached (void) message = NULL; - _DBUS_LOCK (message_cache); + if (!_DBUS_LOCK (message_cache)) + { + /* we'd have initialized global locks before caching anything, + * so there can't be anything in the cache */ + return NULL; + } _dbus_assert (message_cache_count >= 0); @@ -616,7 +623,13 @@ dbus_message_cache_or_finalize (DBusMessage *message) was_cached = FALSE; - _DBUS_LOCK (message_cache); + if (!_DBUS_LOCK (message_cache)) + { + /* The only way to get a non-null message goes through + * dbus_message_get_cached() which takes the lock. */ + _dbus_assert_not_reached ("we would have initialized global locks " + "the first time we constructed a message"); + } if (!message_cache_shutdown_registered) { @@ -672,7 +685,7 @@ dbus_message_cache_or_finalize (DBusMessage *message) dbus_message_finalize (message); } -#ifndef DBUS_DISABLE_CHECKS +#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT) static dbus_bool_t _dbus_message_iter_check (DBusMessageRealIter *iter) { @@ -720,15 +733,13 @@ _dbus_message_iter_check (DBusMessageRealIter *iter) return TRUE; } -#endif /* DBUS_DISABLE_CHECKS */ +#endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */ /** * Implementation of the varargs arg-getting functions. * dbus_message_get_args() is the place to go for complete * documentation. * - * @todo This may leak memory and file descriptors if parsing fails. See #21259 - * * @see dbus_message_get_args * @param iter the message iter * @param error error to be filled in @@ -743,8 +754,9 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter, va_list var_args) { DBusMessageRealIter *real = (DBusMessageRealIter *)iter; - int spec_type, msg_type, i; + int spec_type, msg_type, i, j; dbus_bool_t retval; + va_list copy_args; _dbus_assert (_dbus_message_iter_check (real)); @@ -753,12 +765,17 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter, spec_type = first_arg_type; i = 0; + /* copy var_args first, then we can do another iteration over it to + * free memory and close unix fds if parse failed at some point. + */ + DBUS_VA_COPY (copy_args, var_args); + while (spec_type != DBUS_TYPE_INVALID) { msg_type = dbus_message_iter_get_arg_type (iter); if (msg_type != spec_type) - { + { dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Argument %d is specified to be of type \"%s\", but " "is actually of type \"%s\"\n", i, @@ -766,7 +783,7 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter, _dbus_type_to_string (msg_type)); goto out; - } + } if (spec_type == DBUS_TYPE_UNIX_FD) { @@ -879,30 +896,30 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter, /* Now go through and dup each string */ _dbus_type_reader_recurse (&real->u.reader, &array); - i = 0; - while (i < n_elements) + j = 0; + while (j < n_elements) { const char *s; _dbus_type_reader_read_basic (&array, (void *) &s); - str_array[i] = _dbus_strdup (s); - if (str_array[i] == NULL) + str_array[j] = _dbus_strdup (s); + if (str_array[j] == NULL) { dbus_free_string_array (str_array); _DBUS_SET_OOM (error); goto out; } - ++i; + ++j; if (!_dbus_type_reader_next (&array)) - _dbus_assert (i == n_elements); + _dbus_assert (j == n_elements); } _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); - _dbus_assert (i == n_elements); - _dbus_assert (str_array[i] == NULL); + _dbus_assert (j == n_elements); + _dbus_assert (str_array[j] == NULL); *str_array_p = str_array; *n_elements_p = n_elements; @@ -925,6 +942,9 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter, } #endif + /* how many arguments already handled */ + i++; + spec_type = va_arg (var_args, int); if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) { @@ -932,14 +952,71 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter, "Message has only %d arguments, but more were expected", i); goto out; } - - i++; } retval = TRUE; out: + /* there may memory or unix fd leak in the above iteration if parse failed. + * so we have another iteration over copy_args to free memory and close + * unix fds. + */ + if (!retval) + { + spec_type = first_arg_type; + j = 0; + while (j < i) + { + if (spec_type == DBUS_TYPE_UNIX_FD) + { +#ifdef HAVE_UNIX_FD_PASSING + int *pfd; + + pfd = va_arg (copy_args, int *); + _dbus_assert(pfd); + if (*pfd >= 0) + { + _dbus_close (*pfd, NULL); + *pfd = -1; + } +#endif + } + else if (dbus_type_is_basic (spec_type)) + { + /* move the index forward */ + va_arg (copy_args, DBusBasicValue *); + } + else if (spec_type == DBUS_TYPE_ARRAY) + { + int spec_element_type; + + spec_element_type = va_arg (copy_args, int); + if (dbus_type_is_fixed (spec_element_type)) + { + /* move the index forward */ + va_arg (copy_args, const DBusBasicValue **); + va_arg (copy_args, int *); + } + else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type)) + { + char ***str_array_p; + + str_array_p = va_arg (copy_args, char ***); + /* move the index forward */ + va_arg (copy_args, int *); + _dbus_assert (str_array_p != NULL); + dbus_free_string_array (*str_array_p); + *str_array_p = NULL; + } + } + + spec_type = va_arg (copy_args, int); + j++; + } + } + + va_end (copy_args); return retval; } @@ -1202,7 +1279,7 @@ dbus_message_new (int message_type) * * @param destination name that the message should be sent to or #NULL * @param path object path the message should be sent to - * @param interface interface to invoke method on, or #NULL + * @param iface interface to invoke method on, or #NULL * @param method method to invoke * * @returns a new DBusMessage, free with dbus_message_unref() @@ -1210,7 +1287,7 @@ dbus_message_new (int message_type) DBusMessage* dbus_message_new_method_call (const char *destination, const char *path, - const char *interface, + const char *iface, const char *method) { DBusMessage *message; @@ -1220,8 +1297,8 @@ dbus_message_new_method_call (const char *destination, _dbus_return_val_if_fail (destination == NULL || _dbus_check_is_valid_bus_name (destination), NULL); _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); - _dbus_return_val_if_fail (interface == NULL || - _dbus_check_is_valid_interface (interface), NULL); + _dbus_return_val_if_fail (iface == NULL || + _dbus_check_is_valid_interface (iface), NULL); _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); message = dbus_message_new_empty_header (); @@ -1231,7 +1308,7 @@ dbus_message_new_method_call (const char *destination, if (!_dbus_header_create (&message->header, DBUS_COMPILER_BYTE_ORDER, DBUS_MESSAGE_TYPE_METHOD_CALL, - destination, path, interface, method, NULL)) + destination, path, iface, method, NULL)) { dbus_message_unref (message); return NULL; @@ -1294,22 +1371,22 @@ dbus_message_new_method_return (DBusMessage *method_call) * specification defines the syntax of these fields). * * @param path the path to the object emitting the signal - * @param interface the interface the signal is emitted from + * @param iface the interface the signal is emitted from * @param name name of the signal * @returns a new DBusMessage, free with dbus_message_unref() */ DBusMessage* dbus_message_new_signal (const char *path, - const char *interface, + const char *iface, const char *name) { DBusMessage *message; _dbus_return_val_if_fail (path != NULL, NULL); - _dbus_return_val_if_fail (interface != NULL, NULL); + _dbus_return_val_if_fail (iface != NULL, NULL); _dbus_return_val_if_fail (name != NULL, NULL); _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); - _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL); + _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL); _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); message = dbus_message_new_empty_header (); @@ -1319,7 +1396,7 @@ dbus_message_new_signal (const char *path, if (!_dbus_header_create (&message->header, DBUS_COMPILER_BYTE_ORDER, DBUS_MESSAGE_TYPE_SIGNAL, - NULL, path, interface, name, NULL)) + NULL, path, iface, name, NULL)) { dbus_message_unref (message); return NULL; @@ -3069,23 +3146,23 @@ dbus_message_get_path_decomposed (DBusMessage *message, * in the D-Bus specification. * * @param message the message - * @param interface the interface or #NULL to unset + * @param iface the interface or #NULL to unset * @returns #FALSE if not enough memory */ dbus_bool_t dbus_message_set_interface (DBusMessage *message, - const char *interface) + const char *iface) { _dbus_return_val_if_fail (message != NULL, FALSE); _dbus_return_val_if_fail (!message->locked, FALSE); - _dbus_return_val_if_fail (interface == NULL || - _dbus_check_is_valid_interface (interface), + _dbus_return_val_if_fail (iface == NULL || + _dbus_check_is_valid_interface (iface), FALSE); return set_or_delete_string_field (message, DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING, - interface); + iface); } /** @@ -3120,28 +3197,28 @@ dbus_message_get_interface (DBusMessage *message) * Checks if the message has an interface * * @param message the message - * @param interface the interface name + * @param iface the interface name * @returns #TRUE if the interface field in the header matches */ dbus_bool_t dbus_message_has_interface (DBusMessage *message, - const char *interface) + const char *iface) { const char *msg_interface; msg_interface = dbus_message_get_interface (message); if (msg_interface == NULL) { - if (interface == NULL) + if (iface == NULL) return TRUE; else return FALSE; } - if (interface == NULL) + if (iface == NULL) return FALSE; - if (strcmp (msg_interface, interface) == 0) + if (strcmp (msg_interface, iface) == 0) return TRUE; return FALSE; @@ -3474,13 +3551,13 @@ dbus_message_get_signature (DBusMessage *message) static dbus_bool_t _dbus_message_has_type_interface_member (DBusMessage *message, int type, - const char *interface, + const char *iface, const char *member) { const char *n; _dbus_assert (message != NULL); - _dbus_assert (interface != NULL); + _dbus_assert (iface != NULL); _dbus_assert (member != NULL); if (dbus_message_get_type (message) != type) @@ -3496,7 +3573,7 @@ _dbus_message_has_type_interface_member (DBusMessage *message, { n = dbus_message_get_interface (message); - if (n == NULL || strcmp (n, interface) == 0) + if (n == NULL || strcmp (n, iface) == 0) return TRUE; } @@ -3512,18 +3589,18 @@ _dbus_message_has_type_interface_member (DBusMessage *message, * protocol allows method callers to leave out the interface name. * * @param message the message - * @param interface the name to check (must not be #NULL) + * @param iface the name to check (must not be #NULL) * @param method the name to check (must not be #NULL) * * @returns #TRUE if the message is the specified method call */ dbus_bool_t dbus_message_is_method_call (DBusMessage *message, - const char *interface, + const char *iface, const char *method) { _dbus_return_val_if_fail (message != NULL, FALSE); - _dbus_return_val_if_fail (interface != NULL, FALSE); + _dbus_return_val_if_fail (iface != NULL, FALSE); _dbus_return_val_if_fail (method != NULL, FALSE); /* don't check that interface/method are valid since it would be * expensive, and not catch many common errors @@ -3531,7 +3608,7 @@ dbus_message_is_method_call (DBusMessage *message, return _dbus_message_has_type_interface_member (message, DBUS_MESSAGE_TYPE_METHOD_CALL, - interface, method); + iface, method); } /** @@ -3540,18 +3617,18 @@ dbus_message_is_method_call (DBusMessage *message, * has a different interface or member field, returns #FALSE. * * @param message the message - * @param interface the name to check (must not be #NULL) + * @param iface the name to check (must not be #NULL) * @param signal_name the name to check (must not be #NULL) * * @returns #TRUE if the message is the specified signal */ dbus_bool_t dbus_message_is_signal (DBusMessage *message, - const char *interface, + const char *iface, const char *signal_name) { _dbus_return_val_if_fail (message != NULL, FALSE); - _dbus_return_val_if_fail (interface != NULL, FALSE); + _dbus_return_val_if_fail (iface != NULL, FALSE); _dbus_return_val_if_fail (signal_name != NULL, FALSE); /* don't check that interface/name are valid since it would be * expensive, and not catch many common errors @@ -3559,7 +3636,7 @@ dbus_message_is_signal (DBusMessage *message, return _dbus_message_has_type_interface_member (message, DBUS_MESSAGE_TYPE_SIGNAL, - interface, signal_name); + iface, signal_name); } /** @@ -3799,7 +3876,7 @@ _dbus_message_loader_new (void) SCM_RIGHTS works we need to preallocate an fd array of the maximum number of unix fds we want to receive in advance. A try-and-reallocate loop is not possible. */ - loader->max_message_unix_fds = 1024; + loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS; if (!_dbus_string_init (&loader->data)) { @@ -3896,12 +3973,10 @@ _dbus_message_loader_get_buffer (DBusMessageLoader *loader, * * @param loader the loader. * @param buffer the buffer. - * @param bytes_read number of bytes that were read into the buffer. */ void _dbus_message_loader_return_buffer (DBusMessageLoader *loader, - DBusString *buffer, - int bytes_read) + DBusString *buffer) { _dbus_assert (loader->buffer_outstanding); _dbus_assert (buffer == &loader->data); @@ -3965,7 +4040,7 @@ _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, * * @param loader the message loader. * @param fds the array fds were read into - * @param max_n_fds how many fds were read + * @param n_fds how many fds were read */ void @@ -4393,7 +4468,7 @@ _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) * Sets the maximum unix fds per message we allow. * * @param loader the loader - * @param size the max number of unix fds in a message + * @param n the max number of unix fds in a message */ void _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, @@ -4420,8 +4495,8 @@ _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) return loader->max_message_unix_fds; } -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (message_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots)); /** * Allocates an integer ID to be used for storing application-specific @@ -4441,7 +4516,6 @@ dbus_bool_t dbus_message_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - &_DBUS_LOCK_NAME (message_slots), slot_p); } @@ -4737,7 +4811,7 @@ dbus_message_demarshal (const char *str, _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_len (buffer, str, len); - _dbus_message_loader_return_buffer (loader, buffer, len); + _dbus_message_loader_return_buffer (loader, buffer); if (!_dbus_message_loader_queue_messages (loader)) goto fail_oom; @@ -4772,9 +4846,8 @@ dbus_message_demarshal (const char *str, * Generally, this function is only useful for encapsulating D-Bus messages in * a different protocol. * - * @param str data to be marshalled - * @param len the length of str - * @param error the location to save errors to + * @param buf data to be marshalled + * @param len the length of @p buf * @returns -1 if there was no valid data to be demarshalled, 0 if there wasn't enough data to determine how much should be demarshalled. Otherwise returns the number of bytes to be demarshalled * */ diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 55388ac1..01b7344e 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -71,13 +71,13 @@ DBusMessage* dbus_message_new (int message_type); DBUS_EXPORT DBusMessage* dbus_message_new_method_call (const char *bus_name, const char *path, - const char *interface, + const char *iface, const char *method); DBUS_EXPORT DBusMessage* dbus_message_new_method_return (DBusMessage *method_call); DBUS_EXPORT DBusMessage* dbus_message_new_signal (const char *path, - const char *interface, + const char *iface, const char *name); DBUS_EXPORT DBusMessage* dbus_message_new_error (DBusMessage *reply_to, @@ -108,12 +108,12 @@ dbus_bool_t dbus_message_has_path (DBusMessage *message, const char *object_path); DBUS_EXPORT dbus_bool_t dbus_message_set_interface (DBusMessage *message, - const char *interface); + const char *iface); DBUS_EXPORT const char* dbus_message_get_interface (DBusMessage *message); DBUS_EXPORT dbus_bool_t dbus_message_has_interface (DBusMessage *message, - const char *interface); + const char *iface); DBUS_EXPORT dbus_bool_t dbus_message_set_member (DBusMessage *message, const char *member); @@ -149,11 +149,11 @@ DBUS_EXPORT dbus_bool_t dbus_message_get_no_reply (DBusMessage *message); DBUS_EXPORT dbus_bool_t dbus_message_is_method_call (DBusMessage *message, - const char *interface, + const char *iface, const char *method); DBUS_EXPORT dbus_bool_t dbus_message_is_signal (DBusMessage *message, - const char *interface, + const char *iface, const char *signal_name); DBUS_EXPORT dbus_bool_t dbus_message_is_error (DBusMessage *message, diff --git a/dbus/dbus-misc.c b/dbus/dbus-misc.c index b1610133..6ca30f24 100644 --- a/dbus/dbus-misc.c +++ b/dbus/dbus-misc.c @@ -173,7 +173,7 @@ dbus_get_version (int *major_version_p, /** @} */ /* End of public API */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #ifndef DOXYGEN_SHOULD_SKIP_THIS diff --git a/dbus/dbus-misc.h b/dbus/dbus-misc.h index 3504bcaa..6e72d9ed 100644 --- a/dbus/dbus-misc.h +++ b/dbus/dbus-misc.h @@ -44,6 +44,10 @@ void dbus_get_version (int *major_version_p, int *minor_version_p, int *micro_version_p); +DBUS_EXPORT +dbus_bool_t dbus_setenv (const char *variable, + const char *value); + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-nonce.c b/dbus/dbus-nonce.c index e74c2dd5..37f30f00 100644 --- a/dbus/dbus-nonce.c +++ b/dbus/dbus-nonce.c @@ -113,7 +113,15 @@ _dbus_read_nonce (const DBusString *fname, DBusString *nonce, DBusError* error) fp = fopen (_dbus_string_get_const_data (fname), "rb"); if (!fp) - return FALSE; + { + dbus_set_error (error, + _dbus_error_from_system_errno (), + "Failed to open %s for read: %s", + _dbus_string_get_const_data (fname), + _dbus_strerror_from_errno ()); + return FALSE; + } + nread = fread (buffer, 1, sizeof buffer - 1, fp); fclose (fp); if (!nread) @@ -240,6 +248,7 @@ do_noncefile_create (DBusNonceFile *noncefile, dbus_bool_t use_subdir) { DBusString randomStr; + const char *tmp; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -257,8 +266,11 @@ do_noncefile_create (DBusNonceFile *noncefile, goto on_error; } + tmp = _dbus_get_tmpdir (); + if (!_dbus_string_init (&noncefile->dir) - || !_dbus_string_append (&noncefile->dir, _dbus_get_tmpdir())) + || tmp == NULL + || !_dbus_string_append (&noncefile->dir, tmp)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto on_error; diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c index 172c9d95..d256018e 100644 --- a/dbus/dbus-object-tree.c +++ b/dbus/dbus-object-tree.c @@ -434,6 +434,185 @@ _dbus_object_tree_register (DBusObjectTree *tree, } /** + * Attempts to unregister the given subtree. If the subtree is registered, + * stores its unregister function and user data for later use and returns + * #TRUE. If subtree is not registered, simply returns #FALSE. Does not free + * subtree or remove it from the object tree. + * + * @param subtree the subtree to unregister + * @param unregister_function_out stores subtree's unregister_function + * @param user_data_out stores subtree's user_data + * @return #FALSE if the subtree was not registered, #TRUE on success + */ +static dbus_bool_t +unregister_subtree (DBusObjectSubtree *subtree, + DBusObjectPathUnregisterFunction *unregister_function_out, + void **user_data_out) +{ + _dbus_assert (subtree != NULL); + _dbus_assert (unregister_function_out != NULL); + _dbus_assert (user_data_out != NULL); + + /* Confirm subtree is registered */ + if (subtree->message_function != NULL) + { + subtree->message_function = NULL; + + *unregister_function_out = subtree->unregister_function; + *user_data_out = subtree->user_data; + + subtree->unregister_function = NULL; + subtree->user_data = NULL; + + return TRUE; + } + else + { + /* Assert that this unregistered subtree is either the root node or has + children, otherwise we have a dangling path which should never + happen */ + _dbus_assert (subtree->parent == NULL || subtree->n_subtrees > 0); + + /* The subtree is not registered */ + return FALSE; + } +} + +/** + * Attempts to remove a child subtree from its parent. If removal is + * successful, also frees the child. Returns #TRUE on success, #FALSE + * otherwise. A #FALSE return value tells unregister_and_free_path_recurse to + * stop attempting to remove ancestors, i.e., that no ancestors of the + * specified child are eligible for removal. + * + * @param parent parent from which to remove child + * @param child_index parent->subtrees index of child to remove + * @return #TRUE if removal and free succeed, #FALSE otherwise + */ +static dbus_bool_t +attempt_child_removal (DBusObjectSubtree *parent, + int child_index) +{ + /* Candidate for removal */ + DBusObjectSubtree* candidate; + + _dbus_assert (parent != NULL); + _dbus_assert (child_index >= 0 && child_index < parent->n_subtrees); + + candidate = parent->subtrees[child_index]; + _dbus_assert (candidate != NULL); + + if (candidate->n_subtrees == 0 && candidate->message_function == NULL) + { + /* The candidate node is childless and is not a registered + path, so... */ + + /* ... remove it from its parent... */ + /* Assumes a 0-byte memmove is OK */ + memmove (&parent->subtrees[child_index], + &parent->subtrees[child_index + 1], + (parent->n_subtrees - child_index - 1) + * sizeof (parent->subtrees[0])); + parent->n_subtrees -= 1; + + /* ... and free it */ + candidate->parent = NULL; + _dbus_object_subtree_unref (candidate); + + return TRUE; + } + return FALSE; +} + +/** + * Searches the object tree for a registered subtree node at the given path. + * If a registered node is found, it is removed from the tree and freed, and + * TRUE is returned. If a registered subtree node is not found at the given + * path, the tree is not modified and FALSE is returned. + * + * The found node's unregister_function and user_data are returned in the + * corresponding _out arguments. The caller should define these variables and + * pass their addresses as arguments. + * + * Likewise, the caller should define and set to TRUE a boolean variable, then + * pass its address as the continue_removal_attempts argument. + * + * Once a matching registered node is found, removed and freed, the recursive + * return path is traversed. Along the way, eligible ancestor nodes are + * removed and freed. An ancestor node is eligible for removal if and only if + * 1) it has no children, i.e., it has become childless and 2) it is not itself + * a registered handler. + * + * For example, suppose /A/B and /A/C are registered paths, and that these are + * the only paths in the tree. If B is removed and freed, C is still reachable + * through A, so A cannot be removed and freed. If C is subsequently removed + * and freed, then A becomes a childless node and it becomes eligible for + * removal, and will be removed and freed. + * + * Similarly, suppose /A is a registered path, and /A/B is also a registered + * path, and that these are the only paths in the tree. If B is removed and + * freed, then even though A has become childless, it can't be freed because it + * refers to a path that is still registered. + * + * @param subtree subtree from which to start the search, root for initial call + * @param path path to subtree (same as _dbus_object_tree_unregister_and_unlock) + * @param continue_removal_attempts pointer to a bool, #TRUE for initial call + * @param unregister_function_out returns the found node's unregister_function + * @param user_data_out returns the found node's user_data + * @returns #TRUE if a registered node was found at path, #FALSE otherwise + */ +static dbus_bool_t +unregister_and_free_path_recurse +(DBusObjectSubtree *subtree, + const char **path, + dbus_bool_t *continue_removal_attempts, + DBusObjectPathUnregisterFunction *unregister_function_out, + void **user_data_out) +{ + int i, j; + + _dbus_assert (continue_removal_attempts != NULL); + _dbus_assert (*continue_removal_attempts); + _dbus_assert (unregister_function_out != NULL); + _dbus_assert (user_data_out != NULL); + + if (path[0] == NULL) + return unregister_subtree (subtree, unregister_function_out, user_data_out); + + i = 0; + j = subtree->n_subtrees; + while (i < j) + { + int k, v; + + k = (i + j) / 2; + v = strcmp (path[0], subtree->subtrees[k]->name); + + if (v == 0) + { + dbus_bool_t freed; + freed = unregister_and_free_path_recurse (subtree->subtrees[k], + &path[1], + continue_removal_attempts, + unregister_function_out, + user_data_out); + if (freed && *continue_removal_attempts) + *continue_removal_attempts = attempt_child_removal (subtree, k); + return freed; + } + else if (v < 0) + { + j = k; + } + else + { + i = k + 1; + } + } + return FALSE; +} + +/** * Unregisters an object subtree that was registered with the * same path. * @@ -444,66 +623,42 @@ void _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree, const char **path) { - int i; - DBusObjectSubtree *subtree; + dbus_bool_t found_subtree; + dbus_bool_t continue_removal_attempts; DBusObjectPathUnregisterFunction unregister_function; void *user_data; DBusConnection *connection; + _dbus_assert (tree != NULL); _dbus_assert (path != NULL); + continue_removal_attempts = TRUE; unregister_function = NULL; user_data = NULL; - subtree = find_subtree (tree, path, &i); + found_subtree = unregister_and_free_path_recurse (tree->root, + path, + &continue_removal_attempts, + &unregister_function, + &user_data); #ifndef DBUS_DISABLE_CHECKS - if (subtree == NULL) + if (found_subtree == FALSE) { _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered\n", path[0] ? path[0] : "null", - path[1] ? path[1] : "null"); + (path[0] && path[1]) ? path[1] : "null"); goto unlock; } #else - _dbus_assert (subtree != NULL); + _dbus_assert (found_subtree == TRUE); #endif - _dbus_assert (subtree->parent == NULL || - (i >= 0 && subtree->parent->subtrees[i] == subtree)); - - subtree->message_function = NULL; - - unregister_function = subtree->unregister_function; - user_data = subtree->user_data; - - subtree->unregister_function = NULL; - subtree->user_data = NULL; - - /* If we have no subtrees of our own, remove from - * our parent (FIXME could also be more aggressive - * and remove our parent if it becomes empty) - */ - if (subtree->parent && subtree->n_subtrees == 0) - { - /* assumes a 0-byte memmove is OK */ - memmove (&subtree->parent->subtrees[i], - &subtree->parent->subtrees[i+1], - (subtree->parent->n_subtrees - i - 1) * - sizeof (subtree->parent->subtrees[0])); - subtree->parent->n_subtrees -= 1; - - subtree->parent = NULL; - - _dbus_object_subtree_unref (subtree); - } - subtree = NULL; - unlock: connection = tree->connection; /* Unlock and call application code */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (connection) #endif { @@ -515,7 +670,7 @@ unlock: if (unregister_function) (* unregister_function) (connection, user_data); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (connection) #endif dbus_connection_unref (connection); @@ -638,7 +793,7 @@ handle_default_introspect_and_unlock (DBusObjectTree *tree, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -653,7 +808,7 @@ handle_default_introspect_and_unlock (DBusObjectTree *tree, if (!_dbus_string_init (&xml)) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -698,7 +853,7 @@ handle_default_introspect_and_unlock (DBusObjectTree *tree, if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &v_STRING)) goto out; -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -711,7 +866,7 @@ handle_default_introspect_and_unlock (DBusObjectTree *tree, result = DBUS_HANDLER_RESULT_HANDLED; out: -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -741,6 +896,7 @@ handle_default_introspect_and_unlock (DBusObjectTree *tree, * * @param tree the global object tree * @param message the message to dispatch + * @param found_object return location for the object * @returns whether message was handled successfully */ DBusHandlerResult @@ -762,7 +918,7 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, path = NULL; if (!dbus_message_get_path_decomposed (message, &path)) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -777,7 +933,7 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, if (path == NULL) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -846,7 +1002,7 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, _dbus_verbose (" (invoking a handler)\n"); #endif -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -863,7 +1019,7 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, message, user_data); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif _dbus_connection_lock (tree->connection); @@ -886,7 +1042,7 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, } else { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -1057,7 +1213,7 @@ _dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree, parent_path, child_entries); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (tree->connection) #endif { @@ -1214,7 +1370,7 @@ flatten_path (const char **path) } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -1507,6 +1663,17 @@ run_decompose_tests (void) return TRUE; } +static DBusObjectSubtree* +find_subtree_registered_or_unregistered (DBusObjectTree *tree, + const char **path) +{ +#if VERBOSE_FIND + _dbus_verbose ("Looking for exact subtree, registered or unregistered\n"); +#endif + + return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL); +} + static dbus_bool_t object_tree_test_iteration (void *data) { @@ -1519,6 +1686,13 @@ object_tree_test_iteration (void *data) const char *path6[] = { "blah", "boof", NULL }; const char *path7[] = { "blah", "boof", "this", "is", "really", "long", NULL }; const char *path8[] = { "childless", NULL }; + const char *path9[] = { "blah", "a", NULL }; + const char *path10[] = { "blah", "b", NULL }; + const char *path11[] = { "blah", "c", NULL }; + const char *path12[] = { "blah", "a", "d", NULL }; + const char *path13[] = { "blah", "b", "d", NULL }; + const char *path14[] = { "blah", "c", "d", NULL }; + DBusObjectPathVTable test_vtable = { NULL, test_message_function, NULL }; DBusObjectTree *tree; TreeTestData tree_test_data[9]; int i; @@ -1889,6 +2063,200 @@ object_tree_test_iteration (void *data) ++i; } + /* Test removal of newly-childless unregistered nodes */ + if (!do_register (tree, path2, TRUE, 2, tree_test_data)) + goto out; + + _dbus_object_tree_unregister_and_unlock (tree, path2); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); + + /* Test that unregistered parents cannot be freed out from under their + children */ + if (!do_register (tree, path2, TRUE, 2, tree_test_data)) + goto out; + + _dbus_assert (!find_subtree (tree, path1, NULL)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path1)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); + +#if 0 + /* This triggers the "Attempted to unregister path ..." warning message */ + _dbus_object_tree_unregister_and_unlock (tree, path1); +#endif + _dbus_assert (find_subtree (tree, path2, NULL)); + _dbus_assert (!find_subtree (tree, path1, NULL)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path1)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); + + _dbus_object_tree_unregister_and_unlock (tree, path2); + _dbus_assert (!find_subtree (tree, path2, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); + + /* Test that registered parents cannot be freed out from under their + children, and that if they are unregistered before their children, they + are still freed when their children are unregistered */ + if (!do_register (tree, path1, TRUE, 1, tree_test_data)) + goto out; + if (!do_register (tree, path2, TRUE, 2, tree_test_data)) + goto out; + + _dbus_assert (find_subtree (tree, path1, NULL)); + _dbus_assert (find_subtree (tree, path2, NULL)); + + _dbus_object_tree_unregister_and_unlock (tree, path1); + _dbus_assert (!find_subtree (tree, path1, NULL)); + _dbus_assert (find_subtree (tree, path2, NULL)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path1)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); + + _dbus_object_tree_unregister_and_unlock (tree, path2); + _dbus_assert (!find_subtree (tree, path1, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); + _dbus_assert (!find_subtree (tree, path2, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); + + /* Test with NULL unregister_function and user_data */ + if (!_dbus_object_tree_register (tree, TRUE, path2, + &test_vtable, + NULL, + NULL)) + goto out; + + _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path2) == NULL); + _dbus_object_tree_unregister_and_unlock (tree, path2); + _dbus_assert (!find_subtree (tree, path2, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); + + /* Test freeing a long path */ + if (!do_register (tree, path3, TRUE, 3, tree_test_data)) + goto out; + + _dbus_object_tree_unregister_and_unlock (tree, path3); + _dbus_assert (!find_subtree (tree, path3, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); + + /* Test freeing multiple children from the same path */ + if (!do_register (tree, path3, TRUE, 3, tree_test_data)) + goto out; + if (!do_register (tree, path4, TRUE, 4, tree_test_data)) + goto out; + + _dbus_assert (find_subtree (tree, path3, NULL)); + _dbus_assert (find_subtree (tree, path4, NULL)); + + _dbus_object_tree_unregister_and_unlock (tree, path3); + _dbus_assert (!find_subtree (tree, path3, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3)); + _dbus_assert (find_subtree (tree, path4, NULL)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path4)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path2)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path1)); + + _dbus_object_tree_unregister_and_unlock (tree, path4); + _dbus_assert (!find_subtree (tree, path4, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path4)); + _dbus_assert (!find_subtree (tree, path3, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); + + /* Test subtree removal */ + if (!_dbus_object_tree_register (tree, TRUE, path12, + &test_vtable, + NULL, + NULL)) + goto out; + + _dbus_assert (find_subtree (tree, path12, NULL)); + + if (!_dbus_object_tree_register (tree, TRUE, path13, + &test_vtable, + NULL, + NULL)) + goto out; + + _dbus_assert (find_subtree (tree, path13, NULL)); + + if (!_dbus_object_tree_register (tree, TRUE, path14, + &test_vtable, + NULL, + NULL)) + goto out; + + _dbus_assert (find_subtree (tree, path14, NULL)); + + _dbus_object_tree_unregister_and_unlock (tree, path12); + + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path12)); + _dbus_assert (find_subtree (tree, path13, NULL)); + _dbus_assert (find_subtree (tree, path14, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path9)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path5)); + + if (!_dbus_object_tree_register (tree, TRUE, path12, + &test_vtable, + NULL, + NULL)) + goto out; + + _dbus_assert (find_subtree (tree, path12, NULL)); + + _dbus_object_tree_unregister_and_unlock (tree, path13); + + _dbus_assert (find_subtree (tree, path12, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path13)); + _dbus_assert (find_subtree (tree, path14, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path10)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path5)); + + if (!_dbus_object_tree_register (tree, TRUE, path13, + &test_vtable, + NULL, + NULL)) + goto out; + + _dbus_assert (find_subtree (tree, path13, NULL)); + + _dbus_object_tree_unregister_and_unlock (tree, path14); + + _dbus_assert (find_subtree (tree, path12, NULL)); + _dbus_assert (find_subtree (tree, path13, NULL)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path14)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path11)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path5)); + + _dbus_object_tree_unregister_and_unlock (tree, path12); + + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path12)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path9)); + _dbus_assert (find_subtree_registered_or_unregistered (tree, path5)); + + _dbus_object_tree_unregister_and_unlock (tree, path13); + + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path13)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path10)); + _dbus_assert (!find_subtree_registered_or_unregistered (tree, path5)); + +#if 0 + /* Test attempting to unregister non-existent paths. These trigger + "Attempted to unregister path ..." warning messages */ + _dbus_object_tree_unregister_and_unlock (tree, path0); + _dbus_object_tree_unregister_and_unlock (tree, path1); + _dbus_object_tree_unregister_and_unlock (tree, path2); + _dbus_object_tree_unregister_and_unlock (tree, path3); + _dbus_object_tree_unregister_and_unlock (tree, path4); +#endif + /* Register it all again, and test dispatch */ if (!do_register (tree, path0, TRUE, 0, tree_test_data)) @@ -1962,4 +2330,4 @@ _dbus_object_tree_test (void) #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c index 8a9d2f49..be534105 100644 --- a/dbus/dbus-pending-call.c +++ b/dbus/dbus-pending-call.c @@ -79,26 +79,19 @@ struct DBusPendingCall unsigned int timeout_added : 1; /**< Have added the timeout */ }; -#ifdef DBUS_ENABLE_VERBOSE_MODE static void _dbus_pending_call_trace_ref (DBusPendingCall *pending_call, int old_refcount, int new_refcount, const char *why) { +#ifdef DBUS_ENABLE_VERBOSE_MODE static int enabled = -1; _dbus_trace_ref ("DBusPendingCall", pending_call, old_refcount, new_refcount, why, "DBUS_PENDING_CALL_TRACE", &enabled); -} -#else -#define _dbus_pending_call_trace_ref(p, o, n, w) \ - do \ - {\ - (void) (o); \ - (void) (n); \ - } while (0) #endif +} static dbus_int32_t notify_user_data_slot = -1; @@ -489,8 +482,8 @@ _dbus_pending_call_get_completed_unlocked (DBusPendingCall *pending) return pending->completed; } -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (pending_call_slots)); /** * Stores a pointer on a #DBusPendingCall, along @@ -631,6 +624,8 @@ dbus_pending_call_set_notify (DBusPendingCall *pending, void *user_data, DBusFreeFunction free_user_data) { + dbus_bool_t ret = FALSE; + _dbus_return_val_if_fail (pending != NULL, FALSE); CONNECTION_LOCK (pending->connection); @@ -638,13 +633,15 @@ dbus_pending_call_set_notify (DBusPendingCall *pending, /* could invoke application code! */ if (!_dbus_pending_call_set_data_unlocked (pending, notify_user_data_slot, user_data, free_user_data)) - return FALSE; + goto out; pending->function = function; + ret = TRUE; +out: CONNECTION_UNLOCK (pending->connection); - return TRUE; + return ret; } /** @@ -764,7 +761,6 @@ dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p) _dbus_return_val_if_fail (slot_p != NULL, FALSE); return _dbus_data_slot_allocator_alloc (&slot_allocator, - &_DBUS_LOCK_NAME (pending_call_slots), slot_p); } diff --git a/dbus/dbus-server-debug-pipe.c b/dbus/dbus-server-debug-pipe.c index 419db5c5..8f5ff5fb 100644 --- a/dbus/dbus-server-debug-pipe.c +++ b/dbus/dbus-server-debug-pipe.c @@ -31,7 +31,7 @@ #include "dbus-string.h" #include "dbus-protocol.h" -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * @defgroup DBusServerDebugPipe DBusServerDebugPipe @@ -427,5 +427,5 @@ _dbus_transport_open_debug_pipe (DBusAddressEntry *entry, /** @} */ -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-server-launchd.c b/dbus/dbus-server-launchd.c index db4673c5..9832875e 100644 --- a/dbus/dbus-server-launchd.c +++ b/dbus/dbus-server-launchd.c @@ -40,6 +40,7 @@ #include <launch.h> #include <errno.h> +#include "dbus-misc.h" #include "dbus-server-socket.h" /* put other private launchd functions here */ @@ -176,7 +177,7 @@ _dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error) else { display = launch_data_get_string(environment_param); - _dbus_setenv ("DISPLAY", display); + dbus_setenv ("DISPLAY", display); } } } diff --git a/dbus/dbus-server-socket.c b/dbus/dbus-server-socket.c index ae4b602e..060a919e 100644 --- a/dbus/dbus-server-socket.c +++ b/dbus/dbus-server-socket.c @@ -101,7 +101,7 @@ handle_new_client_fd_and_unlock (DBusServer *server, return TRUE; } - transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, FALSE); + transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, NULL); if (transport == NULL) { _dbus_close_socket (client_fd, NULL); @@ -478,7 +478,10 @@ _dbus_server_new_for_tcp_socket (const char *host, if (server == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - goto failed_4; + if (noncefile != NULL) + goto failed_4; + else + goto failed_2; } _dbus_string_free (&port_str); diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 130f66ec..d9952404 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -149,7 +149,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry, } else if (strcmp (method, "systemd") == 0) { - int n, *fds; + int i, n, *fds; DBusString address; n = _dbus_listen_systemd_sockets (&fds, error); @@ -159,27 +159,39 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry, return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } - _dbus_string_init_const (&address, "systemd:"); + if (!_dbus_string_init (&address)) + goto systemd_oom; - *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL); - if (*server_p == NULL) + for (i = 0; i < n; i++) { - int i; - - for (i = 0; i < n; i++) + if (i > 0) { - _dbus_close_socket (fds[i], NULL); + if (!_dbus_string_append (&address, ";")) + goto systemd_oom; } - dbus_free (fds); - - dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; + if (!_dbus_append_address_from_socket (fds[i], &address, error)) + goto systemd_err; } + *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL); + if (*server_p == NULL) + goto systemd_oom; + dbus_free (fds); return DBUS_SERVER_LISTEN_OK; - } + systemd_oom: + _DBUS_SET_OOM (error); + systemd_err: + for (i = 0; i < n; i++) + { + _dbus_close_socket (fds[i], NULL); + } + dbus_free (fds); + _dbus_string_free (&address); + + return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; + } #ifdef DBUS_ENABLE_LAUNCHD else if (strcmp (method, "launchd") == 0) { diff --git a/dbus/dbus-server-win.c b/dbus/dbus-server-win.c index bf1c896c..bb6da483 100644 --- a/dbus/dbus-server-win.c +++ b/dbus/dbus-server-win.c @@ -57,33 +57,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry, method = dbus_address_entry_get_method (entry); - if (strcmp (method, "nonce-tcp") == 0) - { - const char *host; - const char *port; - const char *bind; - const char *family; - - host = dbus_address_entry_get_value (entry, "host"); - bind = dbus_address_entry_get_value (entry, "bind"); - port = dbus_address_entry_get_value (entry, "port"); - family = dbus_address_entry_get_value (entry, "family"); - - *server_p = _dbus_server_new_for_tcp_socket (host, bind, port, - family, error, TRUE); - - if (*server_p) - { - _DBUS_ASSERT_ERROR_IS_CLEAR(error); - return DBUS_SERVER_LISTEN_OK; - } - else - { - _DBUS_ASSERT_ERROR_IS_SET(error); - return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; - } - } - else if (strcmp (method, "autolaunch") == 0) + if (strcmp (method, "autolaunch") == 0) { const char *host = "localhost"; const char *bind = "localhost"; diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index b62c2b40..19d8590c 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -26,7 +26,7 @@ #include "dbus-server-unix.h" #include "dbus-server-socket.h" #include "dbus-string.h" -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-server-debug-pipe.h" #endif #include "dbus-address.h" @@ -529,7 +529,7 @@ static const struct { } listen_funcs[] = { { _dbus_server_listen_socket } , { _dbus_server_listen_platform_specific } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS , { _dbus_server_listen_debug_pipe } #endif }; @@ -699,13 +699,11 @@ dbus_server_ref (DBusServer *server) _dbus_return_val_if_fail (server != NULL, NULL); - /* can't get the refcount without a side-effect */ old_refcount = _dbus_atomic_inc (&server->refcount); #ifndef DBUS_DISABLE_CHECKS if (_DBUS_UNLIKELY (old_refcount <= 0)) { - /* undo side-effect first */ _dbus_atomic_dec (&server->refcount); _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, _DBUS_FUNCTION_NAME, "old_refcount > 0", @@ -736,13 +734,18 @@ dbus_server_unref (DBusServer *server) _dbus_return_if_fail (server != NULL); - /* can't get the refcount without a side-effect */ old_refcount = _dbus_atomic_dec (&server->refcount); #ifndef DBUS_DISABLE_CHECKS if (_DBUS_UNLIKELY (old_refcount <= 0)) { - /* undo side-effect first */ + /* undo side-effect first + * please do not try to simplify the code here by using + * _dbus_atomic_get(), why we don't use it is + * because it issues another atomic operation even though + * DBUS_DISABLE_CHECKS defined. + * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68303 + */ _dbus_atomic_inc (&server->refcount); _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, _DBUS_FUNCTION_NAME, "old_refcount > 0", @@ -777,16 +780,7 @@ dbus_server_disconnect (DBusServer *server) { _dbus_return_if_fail (server != NULL); -#ifdef DBUS_DISABLE_CHECKS - _dbus_atomic_inc (&server->refcount); -#else - { - dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); - - _dbus_return_if_fail (old_refcount > 0); - } -#endif - + dbus_server_ref (server); SERVER_LOCK (server); _dbus_assert (server->vtable->disconnect != NULL); @@ -1071,9 +1065,8 @@ dbus_server_set_auth_mechanisms (DBusServer *server, return TRUE; } - -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (server_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (server_slots)); /** * Allocates an integer ID to be used for storing application-specific @@ -1093,7 +1086,6 @@ dbus_bool_t dbus_server_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - (DBusRMutex **)&_DBUS_LOCK_NAME (server_slots), slot_p); } @@ -1190,7 +1182,7 @@ dbus_server_get_data (DBusServer *server, /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <string.h> @@ -1246,4 +1238,4 @@ _dbus_server_test (void) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-sha.c b/dbus/dbus-sha.c index d1827522..febfba20 100644 --- a/dbus/dbus-sha.c +++ b/dbus/dbus-sha.c @@ -511,7 +511,7 @@ _dbus_sha_compute (const DBusString *data, /** @} */ /* end of exported functions */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> @@ -966,4 +966,4 @@ _dbus_sha_test (const char *test_data_dir) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-shell.c b/dbus/dbus-shell.c index 111d39df..2384961c 100644 --- a/dbus/dbus-shell.c +++ b/dbus/dbus-shell.c @@ -150,7 +150,7 @@ unquote_string_inplace (char* str, char** end) * through literally instead of being expanded). This function is * guaranteed to succeed if applied to the result of * _dbus_shell_quote(). If it fails, it returns %NULL. - * The @quoted_string need not actually contain quoted or + * The @p quoted_string need not actually contain quoted or * escaped text; _dbus_shell_unquote() simply goes through the string and * unquotes/unescapes anything that the shell would. Both single and * double quotes are handled, as are escapes including escaped @@ -163,7 +163,7 @@ unquote_string_inplace (char* str, char** end) * be escaped with backslash. Otherwise double quotes preserve things * literally. * - * @quoted_string: shell-quoted string + * @param quoted_string shell-quoted string **/ char* _dbus_shell_unquote (const char *quoted_string) @@ -544,10 +544,10 @@ tokenize_command_line (const char *command_line, DBusError *error) * does contain such expansions, they are passed through * literally. Free the returned vector with dbus_free_string_array(). * - * @command_line: command line to parse - * @argcp: return location for number of args - * @argvp: return location for array of args - * @error: error information + * @param command_line command line to parse + * @param argcp return location for number of args + * @param argvp return location for array of args + * @param error error information **/ dbus_bool_t _dbus_shell_parse_argv (const char *command_line, diff --git a/dbus/dbus-signature.c b/dbus/dbus-signature.c index c130de5b..8a4701c9 100644 --- a/dbus/dbus-signature.c +++ b/dbus/dbus-signature.c @@ -410,7 +410,7 @@ dbus_type_is_valid (int typecode) /** @} */ /* end of DBusSignature group */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * @ingroup DBusSignatureInternals diff --git a/dbus/dbus-socket-set-poll.c b/dbus/dbus-socket-set-poll.c index 65a1fd23..e322a3b4 100644 --- a/dbus/dbus-socket-set-poll.c +++ b/dbus/dbus-socket-set-poll.c @@ -44,7 +44,7 @@ typedef struct { #define MINIMUM_SIZE 8 /* If we're in the regression tests, force reallocation to happen sooner */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #define DEFAULT_SIZE_HINT 1 #else #define DEFAULT_SIZE_HINT MINIMUM_SIZE diff --git a/dbus/dbus-spawn-win.c b/dbus/dbus-spawn-win.c index 3dae4f38..7da7a431 100644 --- a/dbus/dbus-spawn-win.c +++ b/dbus/dbus-spawn-win.c @@ -63,12 +63,12 @@ struct DBusBabysitter int refcount; HANDLE start_sync_event; -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS HANDLE end_sync_event; #endif - char *executable; + char *log_name; DBusSpawnChildSetupFunc child_setup; void *user_data; @@ -109,7 +109,7 @@ _dbus_babysitter_new (void) return NULL; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL); if (sitter->end_sync_event == NULL) { @@ -250,7 +250,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter) sitter->start_sync_event = NULL; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (sitter->end_sync_event != NULL) { CloseHandle (sitter->end_sync_event); @@ -258,7 +258,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter) } #endif - dbus_free (sitter->executable); + dbus_free (sitter->log_name); dbus_free (sitter); } @@ -337,7 +337,7 @@ _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter, char *emsg = _dbus_win_error_string (sitter->spawn_errno); dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, "Failed to execute program %s: %s", - sitter->executable, emsg); + sitter->log_name, emsg); _dbus_win_free_error_string (emsg); } else if (sitter->have_child_status) @@ -345,14 +345,14 @@ _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter, PING(); dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED, "Process %s exited with status %d", - sitter->executable, sitter->child_status); + sitter->log_name, sitter->child_status); } else { PING(); dbus_set_error (error, DBUS_ERROR_FAILED, "Process %s exited, status unknown", - sitter->executable); + sitter->log_name); } PING(); } @@ -593,10 +593,10 @@ babysitter (void *parameter) (*sitter->child_setup) (sitter->user_data); } - _dbus_verbose ("babysitter: spawning %s\n", sitter->executable); + _dbus_verbose ("babysitter: spawning %s\n", sitter->log_name); PING(); - sitter->child_handle = spawn_program (sitter->executable, + sitter->child_handle = spawn_program (sitter->log_name, sitter->argv, sitter->envp); PING(); @@ -628,7 +628,7 @@ babysitter (void *parameter) sitter->child_handle = NULL; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS SetEvent (sitter->end_sync_event); #endif @@ -642,6 +642,7 @@ babysitter (void *parameter) dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, + const char *log_name, char **argv, char **envp, DBusSpawnChildSetupFunc child_setup, @@ -653,6 +654,7 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, DWORD sitter_thread_id; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (argv[0] != NULL); *sitter_p = NULL; @@ -667,8 +669,17 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, sitter->child_setup = child_setup; sitter->user_data = user_data; - sitter->executable = _dbus_strdup (argv[0]); - if (sitter->executable == NULL) + sitter->log_name = _dbus_strdup (log_name); + if (sitter->log_name == NULL && log_name != NULL) + { + _DBUS_SET_OOM (error); + goto out0; + } + + if (sitter->log_name == NULL) + sitter->log_name = _dbus_strdup (argv[0]); + + if (sitter->log_name == NULL) { _DBUS_SET_OOM (error); goto out0; @@ -753,7 +764,7 @@ _dbus_babysitter_set_result_function (DBusBabysitter *sitter, sitter->finished_data = user_data; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS static char * get_test_exec (const char *exe, @@ -804,7 +815,7 @@ check_spawn_nonexistent (void *data) /*** Test launching nonexistent binary */ argv[0] = "/this/does/not/exist/32542sdgafgafdg"; - if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL, + if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv, NULL, NULL, NULL, &error)) { @@ -857,7 +868,7 @@ check_spawn_segfault (void *data) return TRUE; } - if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL, + if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv, NULL, NULL, NULL, &error)) { @@ -912,7 +923,7 @@ check_spawn_exit (void *data) return TRUE; } - if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL, + if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv, NULL, NULL, NULL, &error)) { @@ -967,7 +978,7 @@ check_spawn_and_kill (void *data) return TRUE; } - if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL, + if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv, NULL, NULL, NULL, &error)) { diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c index ef00801c..b95cad6e 100644 --- a/dbus/dbus-spawn.c +++ b/dbus/dbus-spawn.c @@ -38,6 +38,12 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_SYSTEMD +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#endif +#include <systemd/sd-journal.h> +#endif extern char **environ; @@ -174,6 +180,48 @@ read_pid (int fd, * and the grandchild. The grandchild is our spawned process. The intermediate * child is a babysitter process; it keeps track of when the grandchild * exits/crashes, and reaps the grandchild. + * + * We automatically reap the babysitter process, killing it if necessary, + * when the DBusBabysitter's refcount goes to zero. + * + * Processes: + * + * main process + * | fork() A + * \- babysitter + * | fork () B + * \- grandchild --> exec --> spawned process + * + * IPC: + * child_err_report_pipe + * /-----------<---------<--------------\ + * | ^ + * v | + * main process babysitter grandchild + * ^ ^ + * v v + * \-------<->-------/ + * babysitter_pipe + * + * child_err_report_pipe is genuinely a pipe. + * The READ_END (also called error_pipe_from_child) is used in the main + * process. The WRITE_END (also called child_err_report_fd) is used in + * the grandchild process. + * + * On failure, the grandchild process sends CHILD_EXEC_FAILED + errno. + * On success, the pipe just closes (because it's close-on-exec) without + * sending any bytes. + * + * babysitter_pipe is mis-named: it's really a bidirectional socketpair. + * The [0] end (also called socket_to_babysitter) is used in the main + * process, the [1] end (also called parent_pipe) is used in the babysitter. + * + * If the fork() labelled B in the diagram above fails, the babysitter sends + * CHILD_FORK_FAILED + errno. + * On success, the babysitter sends CHILD_PID + the grandchild's pid. + * On SIGCHLD, the babysitter sends CHILD_EXITED + the exit status. + * The main process doesn't explicitly send anything, but when it exits, + * the babysitter gets POLLHUP or POLLERR. */ /* Messages from children to parents */ @@ -192,7 +240,8 @@ struct DBusBabysitter { int refcount; /**< Reference count */ - char *executable; /**< executable name to use in error messages */ + char *log_name; /**< the name under which to log messages about this + process being spawned */ int socket_to_babysitter; /**< Connection to the babysitter process */ int error_pipe_from_child; /**< Connection to the process that does the exec() */ @@ -308,15 +357,18 @@ _dbus_babysitter_unref (DBusBabysitter *sitter) if (ret == 0) kill (sitter->sitter_pid, SIGKILL); - again: if (ret == 0) - ret = waitpid (sitter->sitter_pid, &status, 0); + { + do + { + ret = waitpid (sitter->sitter_pid, &status, 0); + } + while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR)); + } if (ret < 0) { - if (errno == EINTR) - goto again; - else if (errno == ECHILD) + if (errno == ECHILD) _dbus_warn ("Babysitter process not available to be reaped; should not happen\n"); else _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n", @@ -343,7 +395,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter) if (sitter->watches) _dbus_watch_list_free (sitter->watches); - dbus_free (sitter->executable); + dbus_free (sitter->log_name); dbus_free (sitter); } @@ -698,34 +750,34 @@ _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter, { dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, "Failed to execute program %s: %s", - sitter->executable, _dbus_strerror (sitter->errnum)); + sitter->log_name, _dbus_strerror (sitter->errnum)); } else if (sitter->have_fork_errnum) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, "Failed to fork a new process %s: %s", - sitter->executable, _dbus_strerror (sitter->errnum)); + sitter->log_name, _dbus_strerror (sitter->errnum)); } else if (sitter->have_child_status) { if (WIFEXITED (sitter->status)) dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED, "Process %s exited with status %d", - sitter->executable, WEXITSTATUS (sitter->status)); + sitter->log_name, WEXITSTATUS (sitter->status)); else if (WIFSIGNALED (sitter->status)) dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED, "Process %s received signal %d", - sitter->executable, WTERMSIG (sitter->status)); + sitter->log_name, WTERMSIG (sitter->status)); else dbus_set_error (error, DBUS_ERROR_FAILED, "Process %s exited abnormally", - sitter->executable); + sitter->log_name); } else { dbus_set_error (error, DBUS_ERROR_FAILED, "Process %s exited, reason unknown", - sitter->executable); + sitter->log_name); } } @@ -807,9 +859,14 @@ handle_watch (DBusWatch *watch, #define WRITE_END 1 -/* Avoids a danger in threaded situations (calling close() - * on a file descriptor twice, and another thread has - * re-opened it since the first close) +/* Avoids a danger in re-entrant situations (calling close() + * on a file descriptor twice, and another module has + * re-opened it since the first close). + * + * This previously claimed to be relevant for threaded situations, but by + * trivial inspection, it is not thread-safe. It doesn't actually + * matter, since this module is only used in the -util variant of the + * library, which is only used in single-threaded situations. */ static int close_and_invalidate (int *fd) @@ -936,7 +993,7 @@ do_exec (int child_err_report_fd, DBusSpawnChildSetupFunc child_setup, void *user_data) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS int i, max_open; #endif @@ -947,7 +1004,7 @@ do_exec (int child_err_report_fd, if (child_setup) (* child_setup) (user_data); -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS max_open = sysconf (_SC_OPEN_MAX); for (i = 3; i < max_open; i++) @@ -1115,8 +1172,7 @@ babysit (pid_t grandchild_pid, } /** - * Spawns a new process. The executable name and argv[0] - * are the same, both are provided in argv[0]. The child_setup + * Spawns a new process. The child_setup * function is passed the given user_data and is run in the child * just before calling exec(). * @@ -1126,8 +1182,9 @@ babysit (pid_t grandchild_pid, * If sitter_p is #NULL, no babysitter is kept. * * @param sitter_p return location for babysitter or #NULL + * @param log_name the name under which to log messages about this process being spawned * @param argv the executable and arguments - * @param env the environment (not used on unix yet) + * @param env the environment, or #NULL to copy the parent's * @param child_setup function to call in child pre-exec() * @param user_data user data for setup function * @param error error object to be filled in if function fails @@ -1135,6 +1192,7 @@ babysit (pid_t grandchild_pid, */ dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, + const char *log_name, char **argv, char **env, DBusSpawnChildSetupFunc child_setup, @@ -1145,8 +1203,13 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, int child_err_report_pipe[2] = { -1, -1 }; int babysitter_pipe[2] = { -1, -1 }; pid_t pid; +#ifdef HAVE_SYSTEMD + int fd_out = -1; + int fd_err = -1; +#endif _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (argv[0] != NULL); if (sitter_p != NULL) *sitter_p = NULL; @@ -1160,8 +1223,17 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, return FALSE; } - sitter->executable = _dbus_strdup (argv[0]); - if (sitter->executable == NULL) + sitter->log_name = _dbus_strdup (log_name); + if (sitter->log_name == NULL && log_name != NULL) + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto cleanup_and_fail; + } + + if (sitter->log_name == NULL) + sitter->log_name = _dbus_strdup (argv[0]); + + if (sitter->log_name == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; @@ -1221,7 +1293,16 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, } _DBUS_ASSERT_ERROR_IS_CLEAR (error); - + +#ifdef HAVE_SYSTEMD + /* This may fail, but it's not critical. + * In particular, if we were compiled with journald support but are now + * running on a non-systemd system, this is going to fail, so we + * have to cope gracefully. */ + fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE); + fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE); +#endif + pid = fork (); if (pid < 0) @@ -1256,7 +1337,21 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, _dbus_assert_not_reached ("Got to code after write_err_and_exit()"); } else if (grandchild_pid == 0) - { + { + /* Go back to ignoring SIGPIPE, since it's evil + */ + signal (SIGPIPE, SIG_IGN); + + close_and_invalidate (&babysitter_pipe[1]); +#ifdef HAVE_SYSTEMD + /* log to systemd journal if possible */ + if (fd_out >= 0) + dup2 (fd_out, STDOUT_FILENO); + if (fd_err >= 0) + dup2 (fd_err, STDERR_FILENO); + close_and_invalidate (&fd_out); + close_and_invalidate (&fd_err); +#endif do_exec (child_err_report_pipe[WRITE_END], argv, env, @@ -1265,6 +1360,11 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, } else { + close_and_invalidate (&child_err_report_pipe[WRITE_END]); +#ifdef HAVE_SYSTEMD + close_and_invalidate (&fd_out); + close_and_invalidate (&fd_err); +#endif babysit (grandchild_pid, babysitter_pipe[1]); _dbus_assert_not_reached ("Got to code after babysit()"); } @@ -1274,6 +1374,10 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, /* Close the uncared-about ends of the pipes */ close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[1]); +#ifdef HAVE_SYSTEMD + close_and_invalidate (&fd_out); + close_and_invalidate (&fd_err); +#endif sitter->socket_to_babysitter = babysitter_pipe[0]; babysitter_pipe[0] = -1; @@ -1303,6 +1407,10 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[0]); close_and_invalidate (&babysitter_pipe[1]); +#ifdef HAVE_SYSTEMD + close_and_invalidate (&fd_out); + close_and_invalidate (&fd_err); +#endif if (sitter != NULL) _dbus_babysitter_unref (sitter); @@ -1321,7 +1429,7 @@ _dbus_babysitter_set_result_function (DBusBabysitter *sitter, /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS static char * get_test_exec (const char *exe, @@ -1364,7 +1472,7 @@ check_spawn_nonexistent (void *data) /*** Test launching nonexistent binary */ argv[0] = "/this/does/not/exist/32542sdgafgafdg"; - if (_dbus_spawn_async_with_babysitter (&sitter, argv, + if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv, NULL, NULL, NULL, &error)) { @@ -1413,7 +1521,7 @@ check_spawn_segfault (void *data) return TRUE; } - if (_dbus_spawn_async_with_babysitter (&sitter, argv, + if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv, NULL, NULL, NULL, &error)) { @@ -1464,7 +1572,7 @@ check_spawn_exit (void *data) return TRUE; } - if (_dbus_spawn_async_with_babysitter (&sitter, argv, + if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv, NULL, NULL, NULL, &error)) { @@ -1515,7 +1623,7 @@ check_spawn_and_kill (void *data) return TRUE; } - if (_dbus_spawn_async_with_babysitter (&sitter, argv, + if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv, NULL, NULL, NULL, &error)) { diff --git a/dbus/dbus-spawn.h b/dbus/dbus-spawn.h index a8814fb9..e6baae97 100644 --- a/dbus/dbus-spawn.h +++ b/dbus/dbus-spawn.h @@ -39,6 +39,7 @@ typedef void (* DBusBabysitterFinishedFunc) (DBusBabysitter *sitter, void *user_data); dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, + const char *log_name, char **argv, char **env, DBusSpawnChildSetupFunc child_setup, diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c index 922580da..3babc053 100644 --- a/dbus/dbus-string-util.c +++ b/dbus/dbus-string-util.c @@ -115,7 +115,7 @@ _dbus_string_find_byte_backward (const DBusString *str, /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include <stdio.h> @@ -935,4 +935,4 @@ _dbus_string_test (void) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index f2726eee..006e4560 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -246,6 +246,14 @@ _dbus_string_free (DBusString *str) if (real->constant) return; + + /* so it's safe if @p str returned by a failed + * _dbus_string_init call + * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65959 + */ + if (real->str == NULL) + return; + dbus_free (real->str - real->align_offset); real->invalid = TRUE; @@ -277,9 +285,9 @@ compact (DBusRealString *real, return TRUE; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /* Not using this feature at the moment, - * so marked DBUS_BUILD_TESTS-only + * so marked DBUS_ENABLE_EMBEDDED_TESTS-only */ /** * Locks a string such that any attempts to change the string will @@ -303,7 +311,7 @@ _dbus_string_lock (DBusString *str) #define MAX_WASTE 48 compact (real, MAX_WASTE); } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ static dbus_bool_t reallocate_for_length (DBusRealString *real, @@ -327,14 +335,11 @@ reallocate_for_length (DBusRealString *real, * disable asserts to profile, you don't get this destroyer * of profiles. */ -#ifdef DBUS_DISABLE_ASSERT -#else -#ifdef DBUS_BUILD_TESTS +#if defined (DBUS_ENABLE_EMBEDDED_TESTS) && !defined (DBUS_DISABLE_ASSERT) new_allocated = 0; /* ensure a realloc every time so that we go * through all malloc failure codepaths */ -#endif /* DBUS_BUILD_TESTS */ -#endif /* !DBUS_DISABLE_ASSERT */ +#endif /* But be sure we always alloc at least space for the new length */ new_allocated = MAX (new_allocated, @@ -949,29 +954,9 @@ _dbus_string_append (DBusString *str, #define ASSIGN_4_OCTETS(p, octets) \ *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets)); -#ifdef DBUS_HAVE_INT64 /** assign 8 bytes from one string to another */ #define ASSIGN_8_OCTETS(p, octets) \ *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets)); -#else -/** assign 8 bytes from one string to another */ -#define ASSIGN_8_OCTETS(p, octets) \ -do { \ - unsigned char *b; \ - \ - b = p; \ - \ - *b++ = octets[0]; \ - *b++ = octets[1]; \ - *b++ = octets[2]; \ - *b++ = octets[3]; \ - *b++ = octets[4]; \ - *b++ = octets[5]; \ - *b++ = octets[6]; \ - *b++ = octets[7]; \ - _dbus_assert (b == p + 8); \ -} while (0) -#endif /* DBUS_HAVE_INT64 */ /** * Inserts 2 bytes aligned on a 2 byte boundary @@ -985,7 +970,7 @@ do { \ dbus_bool_t _dbus_string_insert_2_aligned (DBusString *str, int insert_at, - const unsigned char octets[4]) + const unsigned char octets[2]) { DBUS_STRING_PREAMBLE (str); @@ -1593,19 +1578,11 @@ _dbus_string_split_on_byte (DBusString *source, * * The second check covers surrogate pairs (category Cs). * - * The last two checks cover "Noncharacter": defined as: - * "A code point that is permanently reserved for - * internal use, and that should never be interchanged. In - * Unicode 3.1, these consist of the values U+nFFFE and U+nFFFF - * (where n is from 0 to 10_16) and the values U+FDD0..U+FDEF." - * * @param Char the character */ #define UNICODE_VALID(Char) \ ((Char) < 0x110000 && \ - (((Char) & 0xFFFFF800) != 0xD800) && \ - ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ - ((Char) & 0xFFFE) != 0xFFFE) + (((Char) & 0xFFFFF800) != 0xD800)) /** * Finds the given substring in the string, @@ -1920,7 +1897,7 @@ _dbus_string_skip_white_reverse (const DBusString *str, * @todo owen correctly notes that this is a stupid function (it was * written purely for test code, * e.g. dbus-message-builder.c). Probably should be enforced as test - * code only with ifdef DBUS_BUILD_TESTS + * code only with ifdef DBUS_ENABLE_EMBEDDED_TESTS * * @param source the source string * @param dest the destination string (contents are replaced) @@ -1964,7 +1941,7 @@ _dbus_string_pop_line (DBusString *source, return TRUE; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * Deletes up to and including the first blank space * in the string. @@ -1983,7 +1960,7 @@ _dbus_string_delete_first_word (DBusString *str) } #endif -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * Deletes any leading blanks in the string * @@ -2244,7 +2221,7 @@ _dbus_string_starts_with_c_str (const DBusString *a, */ dbus_bool_t _dbus_string_append_byte_as_hex (DBusString *str, - int byte) + unsigned char byte) { const char hexdigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h index ec52400a..2ebdf56f 100644 --- a/dbus/dbus-string.h +++ b/dbus/dbus-string.h @@ -263,7 +263,7 @@ void _dbus_string_delete_first_word (DBusString *str); void _dbus_string_delete_leading_blanks (DBusString *str); void _dbus_string_chop_white (DBusString *str); dbus_bool_t _dbus_string_append_byte_as_hex (DBusString *str, - int byte); + unsigned char byte); dbus_bool_t _dbus_string_hex_encode (const DBusString *source, int start, DBusString *dest, diff --git a/dbus/dbus-syntax.c b/dbus/dbus-syntax.c index 47922875..7ef659cb 100644 --- a/dbus/dbus-syntax.c +++ b/dbus/dbus-syntax.c @@ -93,7 +93,7 @@ dbus_validate_path (const char *path, * is also checked, since it assumes that the string ends at the first zero * byte according to normal C conventions. * - * @param path a potentially invalid interface name, which must not be #NULL + * @param name a potentially invalid interface name, which must not be #NULL * @param error error return * @returns #TRUE if name is valid */ @@ -140,7 +140,7 @@ dbus_validate_interface (const char *name, * is also checked, since it assumes that the string ends at the first zero * byte according to normal C conventions. * - * @param path a potentially invalid member name, which must not be #NULL + * @param name a potentially invalid member name, which must not be #NULL * @param error error return * @returns #TRUE if name is valid */ @@ -187,7 +187,7 @@ dbus_validate_member (const char *name, * is also checked, since it assumes that the string ends at the first zero * byte according to normal C conventions. * - * @param path a potentially invalid error name, which must not be #NULL + * @param name a potentially invalid error name, which must not be #NULL * @param error error return * @returns #TRUE if name is valid */ @@ -234,7 +234,7 @@ dbus_validate_error_name (const char *name, * is also checked, since it assumes that the string ends at the first zero * byte according to normal C conventions. * - * @param path a potentially invalid bus name, which must not be #NULL + * @param name a potentially invalid bus name, which must not be #NULL * @param error error return * @returns #TRUE if name is valid */ diff --git a/dbus/dbus-sysdeps-pthread.c b/dbus/dbus-sysdeps-pthread.c index c9ec9e5b..1300ec35 100644 --- a/dbus/dbus-sysdeps-pthread.c +++ b/dbus/dbus-sysdeps-pthread.c @@ -36,12 +36,14 @@ #include <config.h> +#ifdef HAVE_MONOTONIC_CLOCK /* Whether we have a "monotonic" clock; i.e. a clock not affected by * changes in system time. * This is initialized once in check_monotonic_clock below. * https://bugs.freedesktop.org/show_bug.cgi?id=18121 */ static dbus_bool_t have_monotonic_clock = 0; +#endif struct DBusRMutex { pthread_mutex_t lock; /**< the lock */ @@ -275,6 +277,26 @@ check_monotonic_clock (void) dbus_bool_t _dbus_threads_init_platform_specific (void) { + /* These have static variables, and we need to handle both the case + * where dbus_threads_init() has been called and when it hasn't; + * so initialize them before any threads are allowed to enter. + */ check_monotonic_clock (); - return dbus_threads_init (NULL); + (void) _dbus_check_setuid (); + + return TRUE; +} + +static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; + +void +_dbus_threads_lock_platform_specific (void) +{ + pthread_mutex_lock (&init_mutex); +} + +void +_dbus_threads_unlock_platform_specific (void) +{ + pthread_mutex_unlock (&init_mutex); } diff --git a/dbus/dbus-sysdeps-thread-win.c b/dbus/dbus-sysdeps-thread-win.c index e30e7b87..0887a549 100644 --- a/dbus/dbus-sysdeps-thread-win.c +++ b/dbus/dbus-sysdeps-thread-win.c @@ -30,6 +30,21 @@ #include <windows.h> +static dbus_bool_t global_init_done = FALSE; +static CRITICAL_SECTION init_lock; + +/* Called from C++ code in dbus-init-win.cpp. */ +void +_dbus_threads_windows_init_global (void) +{ + /* this ensures that the object that acts as our global constructor + * actually gets linked in when we're linked statically */ + _dbus_threads_windows_ensure_ctor_linked (); + + InitializeCriticalSection (&init_lock); + global_init_done = TRUE; +} + struct DBusCondVar { DBusList *list; /**< list thread-local-stored events waiting on the cond variable */ CRITICAL_SECTION lock; /**< lock protecting the list */ @@ -269,6 +284,19 @@ _dbus_threads_init_platform_specific (void) return FALSE; } - return dbus_threads_init (NULL); + return TRUE; +} + +void +_dbus_threads_lock_platform_specific (void) +{ + _dbus_assert (global_init_done); + EnterCriticalSection (&init_lock); } +void +_dbus_threads_unlock_platform_specific (void) +{ + _dbus_assert (global_init_done); + LeaveCriticalSection (&init_lock); +} diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index cef8bd31..ae42f56e 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -55,6 +55,7 @@ #include <netinet/in.h> #include <netdb.h> #include <grp.h> +#include <arpa/inet.h> #ifdef HAVE_ERRNO_H #include <errno.h> @@ -71,6 +72,9 @@ #ifdef HAVE_GETPEERUCRED #include <ucred.h> #endif +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif #ifdef HAVE_ADT #include <bsm/adt.h> @@ -78,6 +82,10 @@ #include "sd-daemon.h" +#if !DBUS_USE_SYNC +#include <pthread.h> +#endif + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -136,7 +144,7 @@ _dbus_open_socket (int *fd_p, cloexec_done = *fd_p >= 0; /* Check if kernel seems to be too old to know SOCK_CLOEXEC */ - if (*fd_p < 0 && errno == EINVAL) + if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE)) #endif { *fd_p = socket (domain, type, protocol); @@ -733,7 +741,7 @@ _dbus_write_two (int fd, } #else /* HAVE_WRITEV */ { - int ret1; + int ret1, ret2; ret1 = _dbus_write (fd, buffer1, start1, len1); if (ret1 == len1 && buffer2 != NULL) @@ -884,16 +892,24 @@ _dbus_connect_exec (const char *path, { int fds[2]; pid_t pid; + int retval; + dbus_bool_t cloexec_done = 0; _DBUS_ASSERT_ERROR_IS_CLEAR (error); _dbus_verbose ("connecting to process %s\n", path); - if (socketpair (AF_UNIX, SOCK_STREAM #ifdef SOCK_CLOEXEC - |SOCK_CLOEXEC + retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); + cloexec_done = (retval >= 0); + + if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE)) #endif - , 0, fds) < 0) + { + retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds); + } + + if (retval < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), @@ -902,8 +918,11 @@ _dbus_connect_exec (const char *path, return -1; } - _dbus_fd_set_close_on_exec (fds[0]); - _dbus_fd_set_close_on_exec (fds[1]); + if (!cloexec_done) + { + _dbus_fd_set_close_on_exec (fds[0]); + _dbus_fd_set_close_on_exec (fds[1]); + } pid = fork (); if (pid < 0) @@ -956,39 +975,6 @@ _dbus_connect_exec (const char *path, } /** - * Enables or disables the reception of credentials on the given socket during - * the next message transmission. This is only effective if the #LOCAL_CREDS - * system feature exists, in which case the other side of the connection does - * not have to do anything special to send the credentials. - * - * @param fd socket on which to change the #LOCAL_CREDS flag. - * @param on whether to enable or disable the #LOCAL_CREDS flag. - */ -static dbus_bool_t -_dbus_set_local_creds (int fd, dbus_bool_t on) -{ - dbus_bool_t retval = TRUE; - -#if defined(HAVE_CMSGCRED) - /* NOOP just to make sure only one codepath is used - * and to prefer CMSGCRED - */ -#elif defined(LOCAL_CREDS) - int val = on ? 1 : 0; - if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0) - { - _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd); - retval = FALSE; - } - else - _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n", - on ? "enabled" : "disabled", fd); -#endif - - return retval; -} - -/** * Creates a socket and binds it to the given path, * then listens on the socket. The socket is * set to be nonblocking. @@ -1013,7 +999,6 @@ _dbus_listen_unix_socket (const char *path, int listen_fd; struct sockaddr_un addr; size_t path_len; - unsigned int reuseaddr; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -1088,13 +1073,6 @@ _dbus_listen_unix_socket (const char *path, strncpy (addr.sun_path, path, path_len); } - reuseaddr = 1; - if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) - { - _dbus_warn ("Failed to set socket option\"%s\": %s", - path, _dbus_strerror (errno)); - } - if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), @@ -1113,15 +1091,6 @@ _dbus_listen_unix_socket (const char *path, return -1; } - if (!_dbus_set_local_creds (listen_fd, TRUE)) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to enable LOCAL_CREDS on socket \"%s\": %s", - path, _dbus_strerror (errno)); - close (listen_fd); - return -1; - } - if (!_dbus_set_fd_nonblocking (listen_fd, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); @@ -1145,7 +1114,7 @@ _dbus_listen_unix_socket (const char *path, * * This will set FD_CLOEXEC for the sockets returned. * - * @oaram fds the file descriptors + * @param fds the file descriptors * @param error return location for errors * @returns the number of file descriptors */ @@ -1207,14 +1176,6 @@ _dbus_listen_systemd_sockets (int **fds, for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { - if (!_dbus_set_local_creds (fd, TRUE)) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to enable LOCAL_CREDS on systemd socket: %s", - _dbus_strerror (errno)); - goto fail; - } - if (!_dbus_set_fd_nonblocking (fd, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); @@ -1603,13 +1564,19 @@ write_credentials_byte (int server_fd, |MSG_NOSIGNAL #endif ); -#else - bytes_written = send (server_fd, buf, 1, 0 -#if HAVE_DECL_MSG_NOSIGNAL - |MSG_NOSIGNAL + + /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg() + * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD + * only allows that on AF_UNIX. Try just doing a send() instead. */ + if (bytes_written < 0 && errno == EINVAL) #endif - ); + { + bytes_written = send (server_fd, buf, 1, 0 +#if HAVE_DECL_MSG_NOSIGNAL + |MSG_NOSIGNAL #endif + ); + } if (bytes_written < 0 && errno == EINTR) goto again; @@ -1673,12 +1640,6 @@ _dbus_read_credentials_socket (int client_fd, struct cmsghdr hdr; char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; } cmsg; - -#elif defined(LOCAL_CREDS) - struct { - struct cmsghdr hdr; - struct sockcred cred; - } cmsg; #endif uid_read = DBUS_UID_UNSET; @@ -1696,12 +1657,6 @@ _dbus_read_credentials_socket (int client_fd, _dbus_credentials_clear (credentials); - /* Systems supporting LOCAL_CREDS are configured to have this feature - * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting - * the connection. Therefore, the received message must carry the - * credentials information without doing anything special. - */ - iov.iov_base = &buf; iov.iov_len = 1; @@ -1709,7 +1664,7 @@ _dbus_read_credentials_socket (int client_fd, msg.msg_iov = &iov; msg.msg_iovlen = 1; -#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) +#if defined(HAVE_CMSGCRED) _DBUS_ZERO(cmsg); msg.msg_control = (caddr_t) &cmsg; msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); @@ -1749,20 +1704,18 @@ _dbus_read_credentials_socket (int client_fd, return FALSE; } -#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) - if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) - || cmsg.hdr.cmsg_type != SCM_CREDS) - { - dbus_set_error (error, DBUS_ERROR_FAILED, - "Message from recvmsg() was not SCM_CREDS"); - return FALSE; - } -#endif - _dbus_verbose ("read credentials byte\n"); { #ifdef SO_PEERCRED + /* Supported by at least Linux and OpenBSD, with minor differences. + * + * This mechanism passes the process ID through and does not require + * the peer's cooperation, so we prefer it over all others. Notably, + * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD + * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all, + * because this is much less fragile. + */ #ifdef __OpenBSD__ struct sockpeercred cr; #else @@ -1782,29 +1735,36 @@ _dbus_read_credentials_socket (int client_fd, cr_len, (int) sizeof (cr), _dbus_strerror (errno)); } #elif defined(HAVE_CMSGCRED) + /* We only check for HAVE_CMSGCRED, but we're really assuming that the + * presence of that struct implies SCM_CREDS. Supported by at least + * FreeBSD and DragonflyBSD. + * + * This mechanism requires the peer to help us (it has to send us a + * SCM_CREDS message) but it does pass the process ID through, + * which makes it better than getpeereid(). + */ struct cmsgcred *cred; + struct cmsghdr *cmsgp; - cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); - pid_read = cred->cmcred_pid; - uid_read = cred->cmcred_euid; -#elif defined(LOCAL_CREDS) - pid_read = DBUS_PID_UNSET; - uid_read = cmsg.cred.sc_uid; - /* Since we have already got the credentials from this socket, we can - * disable its LOCAL_CREDS flag if it was ever set. */ - _dbus_set_local_creds (client_fd, FALSE); -#elif defined(HAVE_GETPEEREID) - uid_t euid; - gid_t egid; - if (getpeereid (client_fd, &euid, &egid) == 0) + for (cmsgp = CMSG_FIRSTHDR (&msg); + cmsgp != NULL; + cmsgp = CMSG_NXTHDR (&msg, cmsgp)) { - uid_read = euid; - } - else - { - _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); + if (cmsgp->cmsg_type == SCM_CREDS && + cmsgp->cmsg_level == SOL_SOCKET && + cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred))) + { + cred = (struct cmsgcred *) CMSG_DATA (cmsgp); + pid_read = cred->cmcred_pid; + uid_read = cred->cmcred_euid; + break; + } } + #elif defined(HAVE_GETPEERUCRED) + /* Supported in at least Solaris >= 10. It should probably be higher + * up this list, because it carries the pid and we use this code path + * for audit data. */ ucred_t * ucred = NULL; if (getpeerucred (client_fd, &ucred) == 0) { @@ -1848,7 +1808,54 @@ _dbus_read_credentials_socket (int client_fd, } if (ucred != NULL) ucred_free (ucred); -#else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ + + /* ---------------------------------------------------------------- + * When adding new mechanisms, please add them above this point + * if they support passing the process ID through, or below if not. + * ---------------------------------------------------------------- */ + +#elif defined(HAVE_GETPEEREID) + /* getpeereid() originates from D.J. Bernstein and is fairly + * widely-supported. According to a web search, it might be present in + * any/all of: + * + * - AIX? + * - Blackberry? + * - Cygwin + * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid) + * - Mac OS X + * - Minix 3.1.8+ + * - MirBSD? + * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid) + * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid) + * - QNX? + */ + uid_t euid; + gid_t egid; + if (getpeereid (client_fd, &euid, &egid) == 0) + { + uid_read = euid; + } + else + { + _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); + } +#else /* no supported mechanism */ + +#warning Socket credentials not supported on this Unix OS +#warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus + + /* Please add other operating systems known to support at least one of + * the mechanisms above to this list, keeping alphabetical order. + * Everything not in this list is best-effort. + */ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ + defined(__linux__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) +# error Credentials passing not working on this OS is a regression! +#endif + _dbus_verbose ("Socket credentials not supported on this OS\n"); #endif } @@ -1862,7 +1869,7 @@ _dbus_read_credentials_socket (int client_fd, if (pid_read != DBUS_PID_UNSET) { - if (!_dbus_credentials_add_unix_pid (credentials, pid_read)) + if (!_dbus_credentials_add_pid (credentials, pid_read)) { _DBUS_SET_OOM (error); return FALSE; @@ -1934,11 +1941,15 @@ _dbus_accept (int listen_fd) retry: #ifdef HAVE_ACCEPT4 - /* We assume that if accept4 is available SOCK_CLOEXEC is too */ + /* + * At compile-time, we assume that if accept4() is available in + * libc headers, SOCK_CLOEXEC is too. At runtime, it is still + * not necessarily true that either is supported by the running kernel. + */ client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); cloexec_done = client_fd >= 0; - if (client_fd < 0 && errno == ENOSYS) + if (client_fd < 0 && (errno == ENOSYS || errno == EINVAL)) #endif { client_fd = accept (listen_fd, &addr, &addrlen); @@ -1988,6 +1999,16 @@ _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) return FALSE; } + if (sb.st_uid != geteuid ()) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "%s directory is owned by user %lu, not %lu", + directory, + (unsigned long) sb.st_uid, + (unsigned long) geteuid ()); + return FALSE; + } + if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) { @@ -2317,7 +2338,7 @@ _dbus_credentials_add_from_current_process (DBusCredentials *credentials) _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); - if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) + if (!_dbus_credentials_add_pid(credentials, _dbus_getpid())) return FALSE; if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) return FALSE; @@ -2424,7 +2445,12 @@ _dbus_parse_uid (const DBusString *uid_str, } #if !DBUS_USE_SYNC -_DBUS_DEFINE_GLOBAL_LOCK (atomic); +/* To be thread-safe by default on platforms that don't necessarily have + * atomic operations (notably Debian armel, which is armv4t), we must + * use a mutex that can be initialized statically, like this. + * GLib >= 2.32 uses a similar system. + */ +static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER; #endif /** @@ -2440,10 +2466,12 @@ _dbus_atomic_inc (DBusAtomic *atomic) return __sync_add_and_fetch(&atomic->value, 1)-1; #else dbus_int32_t res; - _DBUS_LOCK (atomic); + + pthread_mutex_lock (&atomic_mutex); res = atomic->value; atomic->value += 1; - _DBUS_UNLOCK (atomic); + pthread_mutex_unlock (&atomic_mutex); + return res; #endif } @@ -2462,10 +2490,11 @@ _dbus_atomic_dec (DBusAtomic *atomic) #else dbus_int32_t res; - _DBUS_LOCK (atomic); + pthread_mutex_lock (&atomic_mutex); res = atomic->value; atomic->value -= 1; - _DBUS_UNLOCK (atomic); + pthread_mutex_unlock (&atomic_mutex); + return res; #endif } @@ -2486,9 +2515,10 @@ _dbus_atomic_get (DBusAtomic *atomic) #else dbus_int32_t res; - _DBUS_LOCK (atomic); + pthread_mutex_lock (&atomic_mutex); res = atomic->value; - _DBUS_UNLOCK (atomic); + pthread_mutex_unlock (&atomic_mutex); + return res; #endif } @@ -2912,6 +2942,7 @@ _dbus_close (int fd, * (i.e. avoids stdin/stdout/stderr). Sets O_CLOEXEC. * * @param fd the file descriptor to duplicate + * @param error address of error location. * @returns duplicated file descriptor * */ int @@ -3052,7 +3083,7 @@ _dbus_full_duplex_pipe (int *fd1, retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); cloexec_done = retval >= 0; - if (retval < 0 && errno == EINVAL) + if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE)) #endif { retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); @@ -3118,8 +3149,11 @@ _dbus_printf_string_upper_bound (const char *format, char static_buf[1024]; int bufsize = sizeof (static_buf); int len; + va_list args_copy; - len = vsnprintf (static_buf, bufsize, format, args); + DBUS_VA_COPY (args_copy, args); + len = vsnprintf (static_buf, bufsize, format, args_copy); + va_end (args_copy); /* If vsnprintf() returned non-negative, then either the string fits in * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf @@ -3135,8 +3169,12 @@ _dbus_printf_string_upper_bound (const char *format, * or the real length could be coincidentally the same. Which is it? * If vsnprintf returns the truncated length, we'll go to the slow * path. */ - if (vsnprintf (static_buf, 1, format, args) == 1) + DBUS_VA_COPY (args_copy, args); + + if (vsnprintf (static_buf, 1, format, args_copy) == 1) len = -1; + + va_end (args_copy); } /* If vsnprintf() returned negative, we have to do more work. @@ -3152,7 +3190,10 @@ _dbus_printf_string_upper_bound (const char *format, if (buf == NULL) return -1; - len = vsnprintf (buf, bufsize, format, args); + DBUS_VA_COPY (args_copy, args); + len = vsnprintf (buf, bufsize, format, args_copy); + va_end (args_copy); + dbus_free (buf); /* If the reported length is exactly the buffer size, round up to the @@ -3169,13 +3210,17 @@ _dbus_printf_string_upper_bound (const char *format, * Gets the temporary files directory by inspecting the environment variables * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned * - * @returns location of temp directory + * @returns location of temp directory, or #NULL if no memory for locking */ const char* _dbus_get_tmpdir(void) { + /* Protected by _DBUS_LOCK_sysdeps */ static const char* tmpdir = NULL; + if (!_DBUS_LOCK (sysdeps)) + return NULL; + if (tmpdir == NULL) { /* TMPDIR is what glibc uses, then @@ -3198,11 +3243,14 @@ _dbus_get_tmpdir(void) tmpdir = "/tmp"; } + _DBUS_UNLOCK (sysdeps); + _dbus_assert(tmpdir != NULL); return tmpdir; } +#if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD) /** * Execute a subprocess, returning up to 1024 bytes of output * into @p result. @@ -3299,15 +3347,12 @@ _read_subprocess_line_argv (const char *progpath, /* set-up stdXXX */ close (result_pipe[READ_END]); close (errors_pipe[READ_END]); - close (0); /* close stdin */ - close (1); /* close stdout */ - close (2); /* close stderr */ - if (dup2 (fd, 0) == -1) + if (dup2 (fd, 0) == -1) /* setup stdin */ _exit (1); - if (dup2 (result_pipe[WRITE_END], 1) == -1) + if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */ _exit (1); - if (dup2 (errors_pipe[WRITE_END], 2) == -1) + if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */ _exit (1); _dbus_close_all (); @@ -3407,6 +3452,7 @@ _read_subprocess_line_argv (const char *progpath, return retval; } +#endif /** * Returns the address of a new session bus. @@ -3415,6 +3461,7 @@ _read_subprocess_line_argv (const char *progpath, * address. If a failure happens, returns #FALSE and * sets an error in @p error. * + * @param scope scope of autolaunch (Windows only) * @param address a DBusString where the address can be stored * @param error a DBusError to store the error in case of failure * @returns #TRUE on success, #FALSE if an error happened @@ -3429,11 +3476,18 @@ _dbus_get_autolaunch_address (const char *scope, * but that's done elsewhere, and if it worked, this function wouldn't * be called.) */ const char *display; - static char *argv[6]; + char *argv[6]; int i; DBusString uuid; dbus_bool_t retval; + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to autolaunch when setuid"); + return FALSE; + } + _DBUS_ASSERT_ERROR_IS_CLEAR (error); retval = FALSE; @@ -3462,7 +3516,12 @@ _dbus_get_autolaunch_address (const char *scope, } i = 0; - argv[i] = "dbus-launch"; +#ifdef DBUS_ENABLE_EMBEDDED_TESTS + if (_dbus_getenv ("DBUS_USE_TEST_BINARY") != NULL) + argv[i] = TEST_BUS_LAUNCH_BINARY; + else +#endif + argv[i] = DBUS_BINDIR "/dbus-launch"; ++i; argv[i] = "--autolaunch"; ++i; @@ -3477,7 +3536,7 @@ _dbus_get_autolaunch_address (const char *scope, _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); - retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", + retval = _read_subprocess_line_argv (argv[0], TRUE, argv, address, error); @@ -3531,11 +3590,9 @@ _dbus_read_local_machine_uuid (DBusGUID *machine_id, return _dbus_read_uuid_file (&filename, machine_id, FALSE, error); } -#define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" -#define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" - /** * quries launchd for a specific env var which holds the socket path. + * @param socket_path append the socket path to this DBusString * @param launchd_env_var the env var to look up * @param error a DBusError to store the error in case of failure * @return the value of the env var @@ -3551,6 +3608,13 @@ _dbus_lookup_launchd_socket (DBusString *socket_path, _DBUS_ASSERT_ERROR_IS_CLEAR (error); + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to find launchd socket when setuid"); + return FALSE; + } + i = 0; argv[i] = "launchctl"; ++i; @@ -3591,6 +3655,13 @@ _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) dbus_bool_t valid_socket; DBusString socket_path; + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to find launchd socket when setuid"); + return FALSE; + } + if (!_dbus_string_init (&socket_path)) { _DBUS_SET_OOM (error); @@ -3670,167 +3741,6 @@ _dbus_lookup_session_address (dbus_bool_t *supported, } /** - * Returns the standard directories for a session bus to look for service - * activation files - * - * On UNIX this should be the standard xdg freedesktop.org data directories: - * - * XDG_DATA_HOME=${XDG_DATA_HOME-$HOME/.local/share} - * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share} - * - * and - * - * DBUS_DATADIR - * - * @param dirs the directory list we are returning - * @returns #FALSE on OOM - */ - -dbus_bool_t -_dbus_get_standard_session_servicedirs (DBusList **dirs) -{ - const char *xdg_data_home; - const char *xdg_data_dirs; - DBusString servicedir_path; - - if (!_dbus_string_init (&servicedir_path)) - return FALSE; - - xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); - xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); - - if (xdg_data_home != NULL) - { - if (!_dbus_string_append (&servicedir_path, xdg_data_home)) - goto oom; - } - else - { - const DBusString *homedir; - DBusString local_share; - - if (!_dbus_homedir_from_current_process (&homedir)) - goto oom; - - if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) - goto oom; - - _dbus_string_init_const (&local_share, "/.local/share"); - if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) - goto oom; - } - - if (!_dbus_string_append (&servicedir_path, ":")) - goto oom; - - if (xdg_data_dirs != NULL) - { - if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) - goto oom; - - if (!_dbus_string_append (&servicedir_path, ":")) - goto oom; - } - else - { - if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) - goto oom; - } - - /* - * add configured datadir to defaults - * this may be the same as an xdg dir - * however the config parser should take - * care of duplicates - */ - if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) - goto oom; - - if (!_dbus_split_paths_and_append (&servicedir_path, - DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, - dirs)) - goto oom; - - _dbus_string_free (&servicedir_path); - return TRUE; - - oom: - _dbus_string_free (&servicedir_path); - return FALSE; -} - - -/** - * Returns the standard directories for a system bus to look for service - * activation files - * - * On UNIX this should be the standard xdg freedesktop.org data directories: - * - * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share} - * - * and - * - * DBUS_DATADIR - * - * On Windows there is no system bus and this function can return nothing. - * - * @param dirs the directory list we are returning - * @returns #FALSE on OOM - */ - -dbus_bool_t -_dbus_get_standard_system_servicedirs (DBusList **dirs) -{ - /* - * DBUS_DATADIR may be the same as one of the standard directories. However, - * the config parser should take care of the duplicates. - * - * Also, append /lib as counterpart of /usr/share on the root - * directory (the root directory does not know /share), in order to - * facilitate early boot system bus activation where /usr might not - * be available. - */ - static const char standard_search_path[] = - "/usr/local/share:" - "/usr/share:" - DBUS_DATADIR ":" - "/lib"; - DBusString servicedir_path; - - _dbus_string_init_const (&servicedir_path, standard_search_path); - - return _dbus_split_paths_and_append (&servicedir_path, - DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, - dirs); -} - -/** - * Append the absolute path of the system.conf file - * (there is no system bus on Windows so this can just - * return FALSE and print a warning or something) - * - * @param str the string to append to - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_append_system_config_file (DBusString *str) -{ - return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); -} - -/** - * Append the absolute path of the session.conf file. - * - * @param str the string to append to - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_append_session_config_file (DBusString *str) -{ - return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); -} - -/** * Called when the bus daemon is signaled to reload its configuration; any * caches should be nuked. Of course any caches that need explicit reload * are probably broken, but c'est la vie. @@ -3876,7 +3786,7 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory, if (!_dbus_homedir_from_uid (uid, &homedir)) goto failed; -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS { const char *override; @@ -3892,6 +3802,8 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory, } else { + /* Not strictly thread-safe, but if we fail at thread-safety here, + * the worst that will happen is some extra warnings. */ static dbus_bool_t already_warned = FALSE; if (!already_warned) { @@ -4007,20 +3919,6 @@ _dbus_socket_can_pass_unix_fd(int fd) { #endif } - -/* - * replaces the term DBUS_PREFIX in configure_time_path by the - * current dbus installation directory. On unix this function is a noop - * - * @param configure_time_path - * @return real path - */ -const char * -_dbus_replace_install_prefix (const char *configure_time_path) -{ - return configure_time_path; -} - /** * Closes all file descriptors except the first three (i.e. stdin, * stdout, stderr). @@ -4086,4 +3984,133 @@ _dbus_close_all (void) close (i); } +/** + * **NOTE**: If you modify this function, please also consider making + * the corresponding change in GLib. See + * glib/gutils.c:g_check_setuid(). + * + * Returns TRUE if the current process was executed as setuid (or an + * equivalent __libc_enable_secure is available). See: + * http://osdir.com/ml/linux.lfs.hardened/2007-04/msg00032.html + */ +dbus_bool_t +_dbus_check_setuid (void) +{ + /* TODO: get __libc_enable_secure exported from glibc. + * See http://www.openwall.com/lists/owl-dev/2012/08/14/1 + */ +#if 0 && defined(HAVE_LIBC_ENABLE_SECURE) + { + /* See glibc/include/unistd.h */ + extern int __libc_enable_secure; + return __libc_enable_secure; + } +#elif defined(HAVE_ISSETUGID) + /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */ + return issetugid (); +#else + uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ + gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ + + /* We call into this function from _dbus_threads_init_platform_specific() + * to make sure these are initialized before we start threading. */ + static dbus_bool_t check_setuid_initialised; + static dbus_bool_t is_setuid; + + if (_DBUS_UNLIKELY (!check_setuid_initialised)) + { +#ifdef HAVE_GETRESUID + if (getresuid (&ruid, &euid, &suid) != 0 || + getresgid (&rgid, &egid, &sgid) != 0) +#endif /* HAVE_GETRESUID */ + { + suid = ruid = getuid (); + sgid = rgid = getgid (); + euid = geteuid (); + egid = getegid (); + } + + check_setuid_initialised = TRUE; + is_setuid = (ruid != euid || ruid != suid || + rgid != egid || rgid != sgid); + + } + return is_setuid; +#endif +} + +/** + * Read the address from the socket and append it to the string + * + * @param fd the socket + * @param address + * @param error return location for error code + */ +dbus_bool_t +_dbus_append_address_from_socket (int fd, + DBusString *address, + DBusError *error) +{ + union { + struct sockaddr sa; + struct sockaddr_storage storage; + struct sockaddr_un un; + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } socket; + char hostip[INET6_ADDRSTRLEN]; + int size = sizeof (socket); + DBusString path_str; + + if (getsockname (fd, &socket.sa, &size)) + goto err; + + switch (socket.sa.sa_family) + { + case AF_UNIX: + if (socket.un.sun_path[0]=='\0') + { + _dbus_string_init_const (&path_str, &(socket.un.sun_path[1])); + if (_dbus_string_append (address, "unix:abstract=") && + _dbus_address_append_escaped (address, &path_str)) + return TRUE; + } + else + { + _dbus_string_init_const (&path_str, socket.un.sun_path); + if (_dbus_string_append (address, "unix:path=") && + _dbus_address_append_escaped (address, &path_str)) + return TRUE; + } + break; + case AF_INET: + if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip))) + if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u", + hostip, ntohs (socket.ipv4.sin_port))) + return TRUE; + break; +#ifdef AF_INET6 + case AF_INET6: + _dbus_string_init_const (&path_str, hostip); + if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip))) + if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=", + ntohs (socket.ipv6.sin6_port)) && + _dbus_address_append_escaped (address, &path_str)) + return TRUE; + break; +#endif + default: + dbus_set_error (error, + _dbus_error_from_errno (EINVAL), + "Failed to read address from socket: Unknown socket type."); + return FALSE; + } + err: + dbus_set_error (error, + _dbus_error_from_errno (errno), + "Failed to open socket: %s", + _dbus_strerror (errno)); + return FALSE; +} + /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h index 9b708967..a265b335 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -138,6 +138,10 @@ dbus_bool_t _dbus_parse_uid (const DBusString *uid_str, void _dbus_close_all (void); +dbus_bool_t _dbus_append_address_from_socket (int fd, + DBusString *address, + DBusError *error); + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index ef86d738..0d8a66c7 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -49,12 +49,17 @@ #include <sys/socket.h> #include <dirent.h> #include <sys/un.h> + +#ifdef HAVE_SYSLOG_H #include <syslog.h> +#endif #ifdef HAVE_SYS_SYSLIMITS_H #include <sys/syslimits.h> #endif +#include "sd-daemon.h" + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -123,6 +128,7 @@ _dbus_become_daemon (const DBusString *pidfile, dup2 (dev_null_fd, 2); else _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n"); + close (dev_null_fd); } if (!keep_umask) @@ -375,13 +381,13 @@ _dbus_change_to_daemon_user (const char *user, /** * Attempt to ensure that the current process can open - * at least @limit file descriptors. + * at least @p limit file descriptors. * - * If @limit is lower than the current, it will not be + * If @p limit is lower than the current, it will not be * lowered. No error is returned if the request can * not be satisfied. * - * @limit Number of file descriptors + * @param limit number of file descriptors */ void _dbus_request_file_descriptor_limit (unsigned int limit) @@ -422,12 +428,19 @@ _dbus_request_file_descriptor_limit (unsigned int limit) } void -_dbus_init_system_log (void) +_dbus_init_system_log (dbus_bool_t is_daemon) { -#ifdef HAVE_DECL_LOG_PERROR - openlog ("dbus", LOG_PID | LOG_PERROR, LOG_DAEMON); -#else - openlog ("dbus", LOG_PID, LOG_DAEMON); +#ifdef HAVE_SYSLOG_H + int logopts = LOG_PID; + +#if HAVE_DECL_LOG_PERROR +#ifdef HAVE_SYSTEMD + if (!is_daemon || sd_booted () <= 0) +#endif + logopts |= LOG_PERROR; +#endif + + openlog ("dbus", logopts, LOG_DAEMON); #endif } @@ -436,8 +449,6 @@ _dbus_init_system_log (void) * * @param severity a severity value * @param msg a printf-style format string - * @param args arguments for the format string - * */ void _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...) @@ -464,6 +475,8 @@ _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...) void _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args) { + va_list tmp; +#ifdef HAVE_SYSLOG_H int flags; switch (severity) { @@ -480,11 +493,14 @@ _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args return; } -#ifndef HAVE_DECL_LOG_PERROR + DBUS_VA_COPY (tmp, args); + vsyslog (flags, msg, tmp); + va_end (tmp); +#endif + +#if !defined(HAVE_SYSLOG_H) || !HAVE_DECL_LOG_PERROR { /* vsyslog() won't write to stderr, so we'd better do it */ - va_list tmp; - DBUS_VA_COPY (tmp, args); fprintf (stderr, "dbus[" DBUS_PID_FORMAT "]: ", _dbus_getpid ()); vfprintf (stderr, msg, tmp); @@ -493,8 +509,6 @@ _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args } #endif - vsyslog (flags, msg, args); - if (severity == DBUS_SYSTEM_LOG_FATAL) exit (1); } @@ -540,7 +554,7 @@ _dbus_user_at_console (const char *username, DBusError *error) { - DBusString f; + DBusString u, f; dbus_bool_t result; result = FALSE; @@ -556,8 +570,9 @@ _dbus_user_at_console (const char *username, goto out; } + _dbus_string_init_const (&u, username); - if (!_dbus_string_append (&f, username)) + if (!_dbus_concat_dir_and_file (&f, &u)) { _DBUS_SET_OOM (error); goto out; @@ -1142,6 +1157,7 @@ _dbus_command_for_pid (unsigned long pid, "Failed to read from \"%s\": %s", _dbus_string_get_const_data (&path), _dbus_strerror (errno)); + _dbus_close (fd, NULL); goto fail; } @@ -1163,3 +1179,180 @@ fail: _dbus_string_free (&path); return FALSE; } + +/* + * replaces the term DBUS_PREFIX in configure_time_path by the + * current dbus installation directory. On unix this function is a noop + * + * @param configure_time_path + * @return real path + */ +const char * +_dbus_replace_install_prefix (const char *configure_time_path) +{ + return configure_time_path; +} + +#define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" +#define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" + +/** + * Returns the standard directories for a session bus to look for service + * activation files + * + * On UNIX this should be the standard xdg freedesktop.org data directories: + * + * XDG_DATA_HOME=${XDG_DATA_HOME-$HOME/.local/share} + * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share} + * + * and + * + * DBUS_DATADIR + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ + +dbus_bool_t +_dbus_get_standard_session_servicedirs (DBusList **dirs) +{ + const char *xdg_data_home; + const char *xdg_data_dirs; + DBusString servicedir_path; + + if (!_dbus_string_init (&servicedir_path)) + return FALSE; + + xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); + xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); + + if (xdg_data_home != NULL) + { + if (!_dbus_string_append (&servicedir_path, xdg_data_home)) + goto oom; + } + else + { + const DBusString *homedir; + DBusString local_share; + + if (!_dbus_homedir_from_current_process (&homedir)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) + goto oom; + + _dbus_string_init_const (&local_share, "/.local/share"); + if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) + goto oom; + } + + if (!_dbus_string_append (&servicedir_path, ":")) + goto oom; + + if (xdg_data_dirs != NULL) + { + if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, ":")) + goto oom; + } + else + { + if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) + goto oom; + } + + /* + * add configured datadir to defaults + * this may be the same as an xdg dir + * however the config parser should take + * care of duplicates + */ + if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) + goto oom; + + if (!_dbus_split_paths_and_append (&servicedir_path, + DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, + dirs)) + goto oom; + + _dbus_string_free (&servicedir_path); + return TRUE; + + oom: + _dbus_string_free (&servicedir_path); + return FALSE; +} + + +/** + * Returns the standard directories for a system bus to look for service + * activation files + * + * On UNIX this should be the standard xdg freedesktop.org data directories: + * + * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share} + * + * and + * + * DBUS_DATADIR + * + * On Windows there is no system bus and this function can return nothing. + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ + +dbus_bool_t +_dbus_get_standard_system_servicedirs (DBusList **dirs) +{ + /* + * DBUS_DATADIR may be the same as one of the standard directories. However, + * the config parser should take care of the duplicates. + * + * Also, append /lib as counterpart of /usr/share on the root + * directory (the root directory does not know /share), in order to + * facilitate early boot system bus activation where /usr might not + * be available. + */ + static const char standard_search_path[] = + "/usr/local/share:" + "/usr/share:" + DBUS_DATADIR ":" + "/lib"; + DBusString servicedir_path; + + _dbus_string_init_const (&servicedir_path, standard_search_path); + + return _dbus_split_paths_and_append (&servicedir_path, + DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, + dirs); +} + +/** + * Append the absolute path of the system.conf file + * (there is no system bus on Windows so this can just + * return FALSE and print a warning or something) + * + * @param str the string to append to + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_append_system_config_file (DBusString *str) +{ + return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); +} + +/** + * Append the absolute path of the session.conf file. + * + * @param str the string to append to + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_append_session_config_file (DBusString *str) +{ + return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); +} diff --git a/dbus/dbus-sysdeps-util-win.c b/dbus/dbus-sysdeps-util-win.c index 111db9ea..4678b11e 100644 --- a/dbus/dbus-sysdeps-util-win.c +++ b/dbus/dbus-sysdeps-util-win.c @@ -54,7 +54,7 @@ * Does the chdir, fork, setsid, etc. to become a daemon process. * * @param pidfile #NULL, or pidfile to create - * @param print_pid_fd file descriptor to print daemon's pid to, or -1 for none + * @param print_pid_pipe file descriptor to print daemon's pid to, or -1 for none * @param error return location for errors * @param keep_umask #TRUE to keep the original umask * @returns #FALSE on failure @@ -65,7 +65,9 @@ _dbus_become_daemon (const DBusString *pidfile, DBusError *error, dbus_bool_t keep_umask) { - return TRUE; + dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, + "Cannot daemonize on Windows"); + return FALSE; } /** @@ -262,7 +264,7 @@ _dbus_request_file_descriptor_limit (unsigned int limit) } void -_dbus_init_system_log (void) +_dbus_init_system_log (dbus_bool_t is_daemon) { /* OutputDebugStringA doesn't need any special initialization, do nothing */ } @@ -272,8 +274,6 @@ _dbus_init_system_log (void) * * @param severity a severity value * @param msg a printf-style format string - * @param args arguments for the format string - * */ void _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...) @@ -1530,3 +1530,207 @@ _dbus_command_for_pid (unsigned long pid, // FIXME return FALSE; } + +/* + * replaces the term DBUS_PREFIX in configure_time_path by the + * current dbus installation directory. On unix this function is a noop + * + * @param configure_time_path + * @return real path + */ +const char * +_dbus_replace_install_prefix (const char *configure_time_path) +{ +#ifndef DBUS_PREFIX + return configure_time_path; +#else + static char retval[1000]; + static char runtime_prefix[1000]; + int len = 1000; + int i; + + if (!configure_time_path) + return NULL; + + if ((!_dbus_get_install_root(runtime_prefix, len) || + strncmp (configure_time_path, DBUS_PREFIX "/", + strlen (DBUS_PREFIX) + 1))) { + strcat (retval, configure_time_path); + return retval; + } + + strcpy (retval, runtime_prefix); + strcat (retval, configure_time_path + strlen (DBUS_PREFIX) + 1); + + /* Somehow, in some situations, backslashes get collapsed in the string. + * Since windows C library accepts both forward and backslashes as + * path separators, convert all backslashes to forward slashes. + */ + + for(i = 0; retval[i] != '\0'; i++) { + if(retval[i] == '\\') + retval[i] = '/'; + } + return retval; +#endif +} + +/** + * return the relocated DATADIR + * + * @returns relocated DATADIR static string + */ + +static const char * +_dbus_windows_get_datadir (void) +{ + return _dbus_replace_install_prefix(DBUS_DATADIR); +} + +#undef DBUS_DATADIR +#define DBUS_DATADIR _dbus_windows_get_datadir () + + +#define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" +#define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" + +/** + * Returns the standard directories for a session bus to look for service + * activation files + * + * On Windows this should be data directories: + * + * %CommonProgramFiles%/dbus + * + * and + * + * relocated DBUS_DATADIR + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ + +dbus_bool_t +_dbus_get_standard_session_servicedirs (DBusList **dirs) +{ + const char *common_progs; + DBusString servicedir_path; + + if (!_dbus_string_init (&servicedir_path)) + return FALSE; + +#ifdef DBUS_WINCE + { + /* On Windows CE, we adjust datadir dynamically to installation location. */ + const char *data_dir = _dbus_getenv ("DBUS_DATADIR"); + + if (data_dir != NULL) + { + if (!_dbus_string_append (&servicedir_path, data_dir)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) + goto oom; + } + } +#else +/* + the code for accessing services requires absolute base pathes + in case DBUS_DATADIR is relative make it absolute +*/ +#ifdef DBUS_WIN + { + DBusString p; + + _dbus_string_init_const (&p, DBUS_DATADIR); + + if (!_dbus_path_is_absolute (&p)) + { + char install_root[1000]; + if (_dbus_get_install_root (install_root, sizeof(install_root))) + if (!_dbus_string_append (&servicedir_path, install_root)) + goto oom; + } + } +#endif + if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) + goto oom; +#endif + + common_progs = _dbus_getenv ("CommonProgramFiles"); + + if (common_progs != NULL) + { + if (!_dbus_string_append (&servicedir_path, common_progs)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) + goto oom; + } + + if (!_dbus_split_paths_and_append (&servicedir_path, + DBUS_STANDARD_SESSION_SERVICEDIR, + dirs)) + goto oom; + + _dbus_string_free (&servicedir_path); + return TRUE; + + oom: + _dbus_string_free (&servicedir_path); + return FALSE; +} + +/** + * Returns the standard directories for a system bus to look for service + * activation files + * + * On UNIX this should be the standard xdg freedesktop.org data directories: + * + * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share} + * + * and + * + * DBUS_DATADIR + * + * On Windows there is no system bus and this function can return nothing. + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ + +dbus_bool_t +_dbus_get_standard_system_servicedirs (DBusList **dirs) +{ + *dirs = NULL; + return TRUE; +} + +/** + * Append the absolute path of the system.conf file + * (there is no system bus on Windows so this can just + * return FALSE and print a warning or something) + * + * @param str the string to append to + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_append_system_config_file (DBusString *str) +{ + return _dbus_get_config_file_name(str, "system.conf"); +} + +/** + * Append the absolute path of the session.conf file. + * + * @param str the string to append to + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_append_session_config_file (DBusString *str) +{ + return _dbus_get_config_file_name(str, "session.conf"); +} diff --git a/dbus/dbus-sysdeps-util.c b/dbus/dbus-sysdeps-util.c index 4b3d16f2..6b361ef0 100644 --- a/dbus/dbus-sysdeps-util.c +++ b/dbus/dbus-sysdeps-util.c @@ -80,7 +80,7 @@ _dbus_get_environment (void) return environment; } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS static void check_dirname (const char *filename, const char *dirname) @@ -196,4 +196,4 @@ _dbus_sysdeps_test (void) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index 397520af..1167e967 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -6,7 +6,7 @@ * Copyright (C) 2005 Novell, Inc. * Copyright (C) 2006 Peter Kümmel <syntheticpp@gmx.net> * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de> - * Copyright (C) 2006-2010 Ralf Habacker <ralf.habacker@freenet.de> + * Copyright (C) 2006-2013 Ralf Habacker <ralf.habacker@freenet.de> * * Licensed under the Academic Free License version 2.1 * @@ -54,12 +54,14 @@ #include <windows.h> #include <ws2tcpip.h> #include <wincrypt.h> +#include <iphlpapi.h> -/* Declarations missing in mingw's headers */ +/* Declarations missing in mingw's and windows sdk 7.0 headers */ extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid); extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); #include <stdio.h> +#include <stdlib.h> #include <string.h> #if HAVE_ERRNO_H @@ -76,20 +78,15 @@ extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); #include <ws2tcpip.h> #endif -#ifdef HAVE_WSPIAPI_H -// needed for w2k compatibility (getaddrinfo/freeaddrinfo/getnameinfo) -#ifdef __GNUC__ -#define _inline -#include "wspiapi.h" -#else -#include <wspiapi.h> -#endif -#endif // HAVE_WSPIAPI_H - #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef PROCESS_QUERY_LIMITED_INFORMATION +/* MinGW32 < 4 does not define this value in its headers */ +#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000) +#endif + typedef int socklen_t; @@ -103,6 +100,203 @@ _dbus_win_set_errno (int err) #endif } +static BOOL is_winxp_sp3_or_lower(); + +/* + * _MIB_TCPROW_EX and friends are not available in system headers + * and are mapped to attribute identical ...OWNER_PID typedefs. + */ +typedef MIB_TCPROW_OWNER_PID _MIB_TCPROW_EX; +typedef MIB_TCPTABLE_OWNER_PID MIB_TCPTABLE_EX; +typedef PMIB_TCPTABLE_OWNER_PID PMIB_TCPTABLE_EX; +typedef DWORD (WINAPI *ProcAllocateAndGetTcpExtTableFromStack)(PMIB_TCPTABLE_EX*,BOOL,HANDLE,DWORD,DWORD); +static ProcAllocateAndGetTcpExtTableFromStack lpfnAllocateAndGetTcpExTableFromStack = NULL; + +/** + * AllocateAndGetTcpExTableFromStack() is undocumented and not exported, + * but is the only way to do this in older XP versions. + * @return true if the procedures could be loaded + */ +static BOOL +load_ex_ip_helper_procedures(void) +{ + HMODULE hModule = LoadLibrary ("iphlpapi.dll"); + if (hModule == NULL) + { + _dbus_verbose ("could not load iphlpapi.dll\n"); + return FALSE; + } + + lpfnAllocateAndGetTcpExTableFromStack = (ProcAllocateAndGetTcpExtTableFromStack)GetProcAddress (hModule, "AllocateAndGetTcpExTableFromStack"); + if (lpfnAllocateAndGetTcpExTableFromStack == NULL) + { + _dbus_verbose ("could not find function AllocateAndGetTcpExTableFromStack in iphlpapi.dll\n"); + return FALSE; + } + return TRUE; +} + +/** + * get pid from localhost tcp connection using peer_port + * This function is available on WinXP >= SP3 + * @param peer_port peers tcp port + * @return process id or 0 if connection has not been found + */ +static dbus_pid_t +get_pid_from_extended_tcp_table(int peer_port) +{ + dbus_pid_t result; + DWORD errorCode, size, i; + MIB_TCPTABLE_OWNER_PID *tcp_table; + + if ((errorCode = + GetExtendedTcpTable (NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) == ERROR_INSUFFICIENT_BUFFER) + { + tcp_table = (MIB_TCPTABLE_OWNER_PID *) dbus_malloc (size); + if (tcp_table == NULL) + { + _dbus_verbose ("Error allocating memory\n"); + return 0; + } + } + else + { + _dbus_win_warn_win_error ("unexpected error returned from GetExtendedTcpTable", errorCode); + return 0; + } + + if ((errorCode = GetExtendedTcpTable (tcp_table, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) != NO_ERROR) + { + _dbus_verbose ("Error fetching tcp table %d\n", (int)errorCode); + dbus_free (tcp_table); + return 0; + } + + result = 0; + for (i = 0; i < tcp_table->dwNumEntries; i++) + { + MIB_TCPROW_OWNER_PID *p = &tcp_table->table[i]; + int local_address = ntohl (p->dwLocalAddr); + int local_port = ntohs (p->dwLocalPort); + if (p->dwState == MIB_TCP_STATE_ESTAB + && local_address == INADDR_LOOPBACK && local_port == peer_port) + result = p->dwOwningPid; + } + + dbus_free (tcp_table); + _dbus_verbose ("got pid %lu\n", result); + return result; +} + +/** + * get pid from localhost tcp connection using peer_port + * This function is available on all WinXP versions, but + * not in wine (at least version <= 1.6.0) + * @param peer_port peers tcp port + * @return process id or 0 if connection has not been found + */ +static dbus_pid_t +get_pid_from_tcp_ex_table(int peer_port) +{ + dbus_pid_t result; + DWORD errorCode, i; + PMIB_TCPTABLE_EX tcp_table = NULL; + + if (!load_ex_ip_helper_procedures ()) + { + _dbus_verbose + ("Error not been able to load iphelper procedures\n"); + return 0; + } + + errorCode = lpfnAllocateAndGetTcpExTableFromStack (&tcp_table, TRUE, GetProcessHeap(), 0, 2); + + if (errorCode != NO_ERROR) + { + _dbus_verbose + ("Error not been able to call AllocateAndGetTcpExTableFromStack()\n"); + return 0; + } + + result = 0; + for (i = 0; i < tcp_table->dwNumEntries; i++) + { + _MIB_TCPROW_EX *p = &tcp_table->table[i]; + int local_port = ntohs (p->dwLocalPort); + int local_address = ntohl (p->dwLocalAddr); + if (local_address == INADDR_LOOPBACK && local_port == peer_port) + { + result = p->dwOwningPid; + break; + } + } + + HeapFree (GetProcessHeap(), 0, tcp_table); + _dbus_verbose ("got pid %lu\n", result); + return result; +} + +/** + * @brief return peer process id from tcp handle for localhost connections + * @param handle tcp socket descriptor + * @return process id or 0 in case the process id could not be fetched + */ +static dbus_pid_t +_dbus_get_peer_pid_from_tcp_handle (int handle) +{ + struct sockaddr_storage addr; + socklen_t len = sizeof (addr); + int peer_port; + + dbus_pid_t result; + dbus_bool_t is_localhost = FALSE; + + getpeername (handle, (struct sockaddr *) &addr, &len); + + if (addr.ss_family == AF_INET) + { + struct sockaddr_in *s = (struct sockaddr_in *) &addr; + peer_port = ntohs (s->sin_port); + is_localhost = (ntohl (s->sin_addr.s_addr) == INADDR_LOOPBACK); + } + else if (addr.ss_family == AF_INET6) + { + _dbus_verbose ("FIXME [61922]: IPV6 support not working on windows\n"); + return 0; + /* + struct sockaddr_in6 *s = (struct sockaddr_in6 * )&addr; + peer_port = ntohs (s->sin6_port); + is_localhost = (memcmp(s->sin6_addr.s6_addr, in6addr_loopback.s6_addr, 16) == 0); + _dbus_verbose ("IPV6 %08x %08x\n", s->sin6_addr.s6_addr, in6addr_loopback.s6_addr); + */ + } + else + { + _dbus_verbose ("no idea what address family %d is\n", addr.ss_family); + return 0; + } + + if (!is_localhost) + { + _dbus_verbose ("could not fetch process id from remote process\n"); + return 0; + } + + if (peer_port == 0) + { + _dbus_verbose + ("Error not been able to fetch tcp peer port from connection\n"); + return 0; + } + + _dbus_verbose ("trying to get peers pid"); + + result = get_pid_from_extended_tcp_table (peer_port); + if (result > 0) + return result; + result = get_pid_from_tcp_ex_table (peer_port); + return result; +} /* Convert GetLastError() to a dbus error. */ const char* @@ -324,7 +518,7 @@ _dbus_close_socket (int fd, * on exec. Should be called for all file * descriptors in D-Bus code. * - * @param fd the file descriptor + * @param handle the Windows HANDLE */ void _dbus_fd_set_close_on_exec (intptr_t handle) @@ -340,7 +534,7 @@ _dbus_fd_set_close_on_exec (intptr_t handle) /** * Sets a file descriptor to be nonblocking. * - * @param fd the file descriptor. + * @param handle the file descriptor. * @param error address of error location. * @returns #TRUE on success. */ @@ -474,21 +668,26 @@ _dbus_connect_named_pipe (const char *path, #endif - - -void +/** + * @returns #FALSE if no memory + */ +dbus_bool_t _dbus_win_startup_winsock (void) { /* Straight from MSDN, deuglified */ + /* Protected by _DBUS_LOCK_sysdeps */ static dbus_bool_t beenhere = FALSE; WORD wVersionRequested; WSADATA wsaData; int err; + if (!_DBUS_LOCK (sysdeps)) + return FALSE; + if (beenhere) - return; + goto out; wVersionRequested = MAKEWORD (2, 0); @@ -512,6 +711,10 @@ _dbus_win_startup_winsock (void) } beenhere = TRUE; + +out: + _DBUS_UNLOCK (sysdeps); + return TRUE; } @@ -538,9 +741,12 @@ int _dbus_printf_string_upper_bound (const char *format, char buf[1024]; int bufsize; int len; + va_list args_copy; bufsize = sizeof (buf); - len = _vsnprintf (buf, bufsize - 1, format, args); + DBUS_VA_COPY (args_copy, args); + len = _vsnprintf (buf, bufsize - 1, format, args_copy); + va_end (args_copy); while (len == -1) /* try again */ { @@ -553,7 +759,9 @@ int _dbus_printf_string_upper_bound (const char *format, if (p == NULL) return -1; - len = _vsnprintf (p, bufsize - 1, format, args); + DBUS_VA_COPY (args_copy, args); + len = _vsnprintf (p, bufsize - 1, format, args_copy); + va_end (args_copy); free (p); } @@ -738,22 +946,56 @@ _dbus_pid_for_log (void) return _dbus_getpid (); } - #ifndef DBUS_WINCE + +static BOOL is_winxp_sp3_or_lower() +{ + OSVERSIONINFOEX osvi; + DWORDLONG dwlConditionMask = 0; + int op=VER_LESS_EQUAL; + + // Initialize the OSVERSIONINFOEX structure. + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.dwMajorVersion = 5; + osvi.dwMinorVersion = 1; + osvi.wServicePackMajor = 3; + osvi.wServicePackMinor = 0; + + // Initialize the condition mask. + + VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op ); + VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op ); + VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op ); + VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op ); + + // Perform the test. + + return VerifyVersionInfo( + &osvi, + VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, + dwlConditionMask); +} + /** Gets our SID - * @param points to sid buffer, need to be freed with LocalFree() + * @param sid points to sid buffer, need to be freed with LocalFree() + * @param process_id the process id for which the sid should be returned * @returns process sid */ static dbus_bool_t -_dbus_getsid(char **sid) +_dbus_getsid(char **sid, dbus_pid_t process_id) { HANDLE process_token = INVALID_HANDLE_VALUE; TOKEN_USER *token_user = NULL; DWORD n; PSID psid; int retval = FALSE; - - if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token)) + + HANDLE process_handle = OpenProcess(is_winxp_sp3_or_lower() ? PROCESS_QUERY_INFORMATION : PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id); + + if (!OpenProcessToken (process_handle, TOKEN_QUERY, &process_token)) { _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ()); goto failed; @@ -781,10 +1023,11 @@ _dbus_getsid(char **sid) retval = TRUE; failed: + CloseHandle (process_handle); if (process_token != INVALID_HANDLE_VALUE) CloseHandle (process_token); - _dbus_verbose("_dbus_getsid() returns %d\n",retval); + _dbus_verbose("_dbus_getsid() got '%s' and returns %d\n", *sid, retval); return retval; } #endif @@ -816,7 +1059,11 @@ _dbus_full_duplex_pipe (int *fd1, int len; u_long arg; - _dbus_win_startup_winsock (); + if (!_dbus_win_startup_winsock ()) + { + _DBUS_SET_OOM (error); + return FALSE; + } temp = socket (AF_INET, SOCK_STREAM, 0); if (temp == INVALID_SOCKET) @@ -1260,7 +1507,11 @@ _dbus_connect_tcp_socket_with_nonce (const char *host, _DBUS_ASSERT_ERROR_IS_CLEAR (error); - _dbus_win_startup_winsock (); + if (!_dbus_win_startup_winsock ()) + { + _DBUS_SET_OOM (error); + return -1; + } _DBUS_ZERO (hints); @@ -1405,7 +1656,11 @@ _dbus_listen_tcp_socket (const char *host, *fds_p = NULL; _DBUS_ASSERT_ERROR_IS_CLEAR (error); - _dbus_win_startup_winsock (); + if (!_dbus_win_startup_winsock ()) + { + _DBUS_SET_OOM (error); + return -1; + } _DBUS_ZERO (hints); @@ -1665,13 +1920,13 @@ again: * a byte was read, not whether we got valid credentials. On some * systems, such as Linux, reading/writing the byte isn't actually * required, but we do it anyway just to avoid multiple codepaths. - * + * * Fails if no byte is available, so you must select() first. * * The point of the byte is that on some systems we have to * use sendmsg()/recvmsg() to transmit credentials. * - * @param client_fd the client file descriptor + * @param handle the client file descriptor * @param credentials struct to fill with credentials of client * @param error location to store error code * @returns #TRUE on success @@ -1683,22 +1938,41 @@ _dbus_read_credentials_socket (int handle, { int bytes_read = 0; DBusString buf; - + + char *sid = NULL; + dbus_pid_t pid; + int retval = FALSE; + // could fail due too OOM - if (_dbus_string_init(&buf)) + if (_dbus_string_init (&buf)) { - bytes_read = _dbus_read_socket(handle, &buf, 1 ); + bytes_read = _dbus_read_socket (handle, &buf, 1 ); if (bytes_read > 0) - _dbus_verbose("got one zero byte from server"); + _dbus_verbose ("got one zero byte from server\n"); - _dbus_string_free(&buf); + _dbus_string_free (&buf); } - _dbus_credentials_add_from_current_process (credentials); - _dbus_verbose("FIXME: get faked credentials from current process"); + pid = _dbus_get_peer_pid_from_tcp_handle (handle); + if (pid == 0) + return TRUE; - return TRUE; + _dbus_credentials_add_pid (credentials, pid); + + if (_dbus_getsid (&sid, pid)) + { + if (!_dbus_credentials_add_windows_sid (credentials, sid)) + goto out; + } + + retval = TRUE; + +out: + if (sid) + LocalFree (sid); + + return retval; } /** @@ -1792,10 +2066,10 @@ _dbus_credentials_add_from_current_process (DBusCredentials *credentials) dbus_bool_t retval = FALSE; char *sid = NULL; - if (!_dbus_getsid(&sid)) + if (!_dbus_getsid(&sid, _dbus_getpid())) goto failed; - if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) + if (!_dbus_credentials_add_pid (credentials, _dbus_getpid())) goto failed; if (!_dbus_credentials_add_windows_sid (credentials,sid)) @@ -1830,7 +2104,7 @@ _dbus_append_user_from_current_process (DBusString *str) dbus_bool_t retval = FALSE; char *sid = NULL; - if (!_dbus_getsid(&sid)) + if (!_dbus_getsid(&sid, _dbus_getpid())) return FALSE; retval = _dbus_string_append (str,sid); @@ -1999,14 +2273,18 @@ _dbus_generate_random_bytes (DBusString *str, * Gets the temporary files directory by inspecting the environment variables * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned * - * @returns location of temp directory + * @returns location of temp directory, or #NULL if no memory for locking */ const char* _dbus_get_tmpdir(void) { + /* Protected by _DBUS_LOCK_sysdeps */ static const char* tmpdir = NULL; static char buf[1000]; + if (!_DBUS_LOCK (sysdeps)) + return NULL; + if (tmpdir == NULL) { char *last_slash; @@ -2028,6 +2306,8 @@ _dbus_get_tmpdir(void) tmpdir = buf; } + _DBUS_UNLOCK (sysdeps); + _dbus_assert(tmpdir != NULL); return tmpdir; @@ -2063,51 +2343,7 @@ _dbus_delete_file (const DBusString *filename, return TRUE; } -/* - * replaces the term DBUS_PREFIX in configure_time_path by the - * current dbus installation directory. On unix this function is a noop - * - * @param configure_time_path - * @return real path - */ -const char * -_dbus_replace_install_prefix (const char *configure_time_path) -{ -#ifndef DBUS_PREFIX - return configure_time_path; -#else - static char retval[1000]; - static char runtime_prefix[1000]; - int len = 1000; - int i; - - if (!configure_time_path) - return NULL; - - if ((!_dbus_get_install_root(runtime_prefix, len) || - strncmp (configure_time_path, DBUS_PREFIX "/", - strlen (DBUS_PREFIX) + 1))) { - strcat (retval, configure_time_path); - return retval; - } - - strcpy (retval, runtime_prefix); - strcat (retval, configure_time_path + strlen (DBUS_PREFIX) + 1); - - /* Somehow, in some situations, backslashes get collapsed in the string. - * Since windows C library accepts both forward and backslashes as - * path separators, convert all backslashes to forward slashes. - */ - - for(i = 0; retval[i] != '\0'; i++) { - if(retval[i] == '\\') - retval[i] = '/'; - } - return retval; -#endif -} - -#if !defined (DBUS_DISABLE_ASSERTS) || defined(DBUS_BUILD_TESTS) +#if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_ENABLE_EMBEDDED_TESTS) #if defined(_MSC_VER) || defined(DBUS_WINCE) # ifdef BACKTRACES @@ -2946,142 +3182,6 @@ _dbus_make_file_world_readable(const DBusString *filename, } /** - * return the relocated DATADIR - * - * @returns relocated DATADIR static string - */ - -static const char * -_dbus_windows_get_datadir (void) -{ - return _dbus_replace_install_prefix(DBUS_DATADIR); -} - -#undef DBUS_DATADIR -#define DBUS_DATADIR _dbus_windows_get_datadir () - - -#define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" -#define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" - -/** - * Returns the standard directories for a session bus to look for service - * activation files - * - * On Windows this should be data directories: - * - * %CommonProgramFiles%/dbus - * - * and - * - * relocated DBUS_DATADIR - * - * @param dirs the directory list we are returning - * @returns #FALSE on OOM - */ - -dbus_bool_t -_dbus_get_standard_session_servicedirs (DBusList **dirs) -{ - const char *common_progs; - DBusString servicedir_path; - - if (!_dbus_string_init (&servicedir_path)) - return FALSE; - -#ifdef DBUS_WINCE - { - /* On Windows CE, we adjust datadir dynamically to installation location. */ - const char *data_dir = _dbus_getenv ("DBUS_DATADIR"); - - if (data_dir != NULL) - { - if (!_dbus_string_append (&servicedir_path, data_dir)) - goto oom; - - if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) - goto oom; - } - } -#else -/* - the code for accessing services requires absolute base pathes - in case DBUS_DATADIR is relative make it absolute -*/ -#ifdef DBUS_WIN - { - DBusString p; - - _dbus_string_init_const (&p, DBUS_DATADIR); - - if (!_dbus_path_is_absolute (&p)) - { - char install_root[1000]; - if (_dbus_get_install_root (install_root, sizeof(install_root))) - if (!_dbus_string_append (&servicedir_path, install_root)) - goto oom; - } - } -#endif - if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) - goto oom; - - if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) - goto oom; -#endif - - common_progs = _dbus_getenv ("CommonProgramFiles"); - - if (common_progs != NULL) - { - if (!_dbus_string_append (&servicedir_path, common_progs)) - goto oom; - - if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) - goto oom; - } - - if (!_dbus_split_paths_and_append (&servicedir_path, - DBUS_STANDARD_SESSION_SERVICEDIR, - dirs)) - goto oom; - - _dbus_string_free (&servicedir_path); - return TRUE; - - oom: - _dbus_string_free (&servicedir_path); - return FALSE; -} - -/** - * Returns the standard directories for a system bus to look for service - * activation files - * - * On UNIX this should be the standard xdg freedesktop.org data directories: - * - * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share} - * - * and - * - * DBUS_DATADIR - * - * On Windows there is no system bus and this function can return nothing. - * - * @param dirs the directory list we are returning - * @returns #FALSE on OOM - */ - -dbus_bool_t -_dbus_get_standard_system_servicedirs (DBusList **dirs) -{ - *dirs = NULL; - return TRUE; -} - -_DBUS_DEFINE_GLOBAL_LOCK (atomic); - -/** * Atomically increments an integer * * @param atomic pointer to the integer to increment @@ -3121,8 +3221,18 @@ _dbus_atomic_dec (DBusAtomic *atomic) dbus_int32_t _dbus_atomic_get (DBusAtomic *atomic) { - /* this is what GLib does, hopefully it's right... */ - MemoryBarrier (); + /* In this situation, GLib issues a MemoryBarrier() and then returns + * atomic->value. However, mingw from mingw.org (not to be confused with + * mingw-w64 from mingw-w64.sf.net) does not have MemoryBarrier in its + * headers, so we have to get a memory barrier some other way. + * + * InterlockedIncrement is older, and is documented on MSDN to be a full + * memory barrier, so let's use that. + */ + long dummy = 0; + + InterlockedExchange (&dummy, 1); + return atomic->value; } @@ -3153,7 +3263,7 @@ _dbus_get_is_errno_eagain_or_ewouldblock (void) /** * return the absolute path of the dbus installation * - * @param s buffer for installation path + * @param prefix buffer for installation path * @param len length of buffer * @returns #FALSE on failure */ @@ -3258,32 +3368,6 @@ _dbus_get_config_file_name(DBusString *config_file, char *s) return TRUE; } -/** - * Append the absolute path of the system.conf file - * (there is no system bus on Windows so this can just - * return FALSE and print a warning or something) - * - * @param str the string to append to - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_append_system_config_file (DBusString *str) -{ - return _dbus_get_config_file_name(str, "system.conf"); -} - -/** - * Append the absolute path of the session.conf file. - * - * @param str the string to append to - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_append_session_config_file (DBusString *str) -{ - return _dbus_get_config_file_name(str, "session.conf"); -} - /* See comment in dbus-sysdeps-unix.c */ dbus_bool_t _dbus_lookup_session_address (dbus_bool_t *supported, @@ -3335,7 +3419,7 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory, _dbus_string_append(&homedir,homepath); } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS { const char *override; @@ -3351,6 +3435,8 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory, } else { + /* Not strictly thread-safe, but if we fail at thread-safety here, + * the worst that will happen is some extra warnings. */ static dbus_bool_t already_warned = FALSE; if (!already_warned) { @@ -3575,7 +3661,7 @@ _dbus_win_set_error_from_win_error (DBusError *error, void _dbus_win_warn_win_error (const char *message, - int code) + unsigned long code) { DBusError error; @@ -3632,6 +3718,12 @@ _dbus_path_is_absolute (const DBusString *filename) return FALSE; } +dbus_bool_t +_dbus_check_setuid (void) +{ + return FALSE; +} + /** @} end of sysdeps-win */ /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps-win.h b/dbus/dbus-sysdeps-win.h index 74624b75..02e7a83f 100644 --- a/dbus/dbus-sysdeps-win.h +++ b/dbus/dbus-sysdeps-win.h @@ -27,7 +27,7 @@ #define DBUS_SYSDEPS_WIN_H extern void *_dbus_win_get_dll_hmodule (void); -#define _WINSOCKAPI_ +#define WIN32_LEAN_AND_MEAN #include "dbus-hash.h" #include "dbus-string.h" @@ -42,9 +42,9 @@ extern void *_dbus_win_get_dll_hmodule (void); void _dbus_win_set_errno (int err); const char* _dbus_win_error_from_last_error (void); -void _dbus_win_startup_winsock (void); +dbus_bool_t _dbus_win_startup_winsock (void); void _dbus_win_warn_win_error (const char *message, - int code); + unsigned long code); char * _dbus_win_error_string (int error_number); void _dbus_win_free_error_string (char *string); @@ -85,6 +85,9 @@ dbus_bool_t _dbus_get_config_file_name(DBusString *config_file, dbus_bool_t _dbus_get_install_root(char *prefix, int len); +void _dbus_threads_windows_init_global (void); +void _dbus_threads_windows_ensure_ctor_linked (void); + #endif /** @} end of sysdeps-win.h */ diff --git a/dbus/dbus-sysdeps-wince-glue.c b/dbus/dbus-sysdeps-wince-glue.c index 74b1371f..e276f046 100644 --- a/dbus/dbus-sysdeps-wince-glue.c +++ b/dbus/dbus-sysdeps-wince-glue.c @@ -491,7 +491,7 @@ SearchPathA (LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension, /** Gets our SID - * @param points to sid buffer, need to be freed with LocalFree() + * @param sid points to sid buffer, need to be freed with LocalFree() * @returns process sid */ dbus_bool_t diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 861bfec9..de3a18cb 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -29,6 +29,7 @@ #include "dbus-protocol.h" #include "dbus-string.h" #include "dbus-list.h" +#include "dbus-misc.h" /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c. @@ -46,10 +47,6 @@ #include <errno.h> #endif -_DBUS_DEFINE_GLOBAL_LOCK (win_fds); -_DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache); -_DBUS_DEFINE_GLOBAL_LOCK (system_users); - #ifdef DBUS_WIN #include <stdlib.h> #elif (defined __APPLE__) @@ -96,6 +93,8 @@ _dbus_abort (void) } /** + * @ingroup DBusMisc + * * Wrapper for setenv(). If the value is #NULL, unsets * the environment variable. * @@ -104,13 +103,16 @@ _dbus_abort (void) * we can not rely on internal implementation details of * the underlying libc library. * + * This function is not thread-safe, because altering the environment + * in Unix is not thread-safe in general. + * * @param varname name of environment variable - * @param value value of environment variable - * @returns #TRUE on success. + * @param value value of environment variable, or #NULL to unset + * @returns #TRUE on success, #FALSE if not enough memory. */ dbus_bool_t -_dbus_setenv (const char *varname, - const char *value) +dbus_setenv (const char *varname, + const char *value) { _dbus_assert (varname != NULL); @@ -182,6 +184,11 @@ _dbus_setenv (const char *varname, const char* _dbus_getenv (const char *varname) { + /* Don't respect any environment variables if the current process is + * setuid. This is the equivalent of glibc's __secure_getenv(). + */ + if (_dbus_check_setuid ()) + return NULL; return getenv (varname); } diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index c03e2f54..e586946f 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -87,9 +87,8 @@ typedef struct DBusPipe DBusPipe; void _dbus_abort (void) _DBUS_GNUC_NORETURN; +dbus_bool_t _dbus_check_setuid (void); const char* _dbus_getenv (const char *varname); -dbus_bool_t _dbus_setenv (const char *varname, - const char *value); dbus_bool_t _dbus_clearenv (void); char ** _dbus_get_environment (void); @@ -277,6 +276,19 @@ dbus_int32_t _dbus_atomic_get (DBusAtomic *atomic); #define _DBUS_POLLHUP 0x0080 /** Invalid request: fd not open */ #define _DBUS_POLLNVAL 0x1000 +#elif defined(__QNX__) +/** Writing now will not block */ +#define _DBUS_POLLOUT 0x0002 +/** There is data to read */ +#define _DBUS_POLLIN 0x0005 +/** There is urgent data to read */ +#define _DBUS_POLLPRI 0x0008 +/** Error condition */ +#define _DBUS_POLLERR 0x0020 +/** Hung up */ +#define _DBUS_POLLHUP 0x0040 +/** Invalid request: fd not open */ +#define _DBUS_POLLNVAL 0x1000 #else /** There is data to read */ #define _DBUS_POLLIN 0x0001 @@ -308,12 +320,12 @@ int _dbus_poll (DBusPollFD *fds, void _dbus_sleep_milliseconds (int milliseconds); -void _dbus_get_real_time (long *tv_sec, - long *tv_usec); - void _dbus_get_monotonic_time (long *tv_sec, long *tv_usec); +void _dbus_get_real_time (long *tv_sec, + long *tv_usec); + /** * directory interface */ @@ -436,7 +448,7 @@ void _dbus_set_signal_handler (int sig, dbus_bool_t _dbus_user_at_console (const char *username, DBusError *error); -void _dbus_init_system_log (void); +void _dbus_init_system_log (dbus_bool_t is_daemon); typedef enum { DBUS_SYSTEM_LOG_INFO, @@ -506,6 +518,16 @@ dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id, */ dbus_bool_t _dbus_threads_init_platform_specific (void); +/** + * Lock a static mutex used to protect _dbus_threads_init_platform_specific(). + */ +void _dbus_threads_lock_platform_specific (void); + +/** + * Undo _dbus_threads_lock_platform_specific(). + */ +void _dbus_threads_unlock_platform_specific (void); + dbus_bool_t _dbus_split_paths_and_append (DBusString *dirs, const char *suffix, DBusList **dir_list); diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c index 224a6c8c..5990d6ec 100644 --- a/dbus/dbus-test.c +++ b/dbus/dbus-test.c @@ -28,7 +28,7 @@ #include <stdio.h> #include <stdlib.h> -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS static void die (const char *failure) { @@ -41,7 +41,7 @@ check_memleaks (void) { dbus_shutdown (); - printf ("%s: checking for memleaks\n", "dbus-test"); + printf ("%s: checking for memleaks\n", "test-dbus"); if (_dbus_get_malloc_blocks_outstanding () != 0) { _dbus_warn ("%d dbus_malloc blocks were not freed\n", @@ -60,7 +60,7 @@ run_test (const char *test_name, { if (!specific_test || strcmp (specific_test, test_name) == 0) { - printf ("%s: running %s tests\n", "dbus-test", test_name); + printf ("%s: running %s tests\n", "test-dbus", test_name); if (!test ()) die (test_name); @@ -76,7 +76,7 @@ run_data_test (const char *test_name, { if (!specific_test || strcmp (specific_test, test_name) == 0) { - printf ("%s: running %s tests\n", "dbus-test", test_name); + printf ("%s: running %s tests\n", "test-dbus", test_name); if (!test (test_data_dir)) die (test_name); @@ -84,7 +84,7 @@ run_data_test (const char *test_name, } } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ /** * An exported symbol to be run in order to execute @@ -94,11 +94,12 @@ run_data_test (const char *test_name, * (with --enable-tests=no) * * @param test_data_dir the directory with test data (test/data normally) + * @param specific_test run specific test or #NULL to run all tests */ void dbus_internal_do_not_use_run_tests (const char *test_data_dir, const char *specific_test) { -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS if (!_dbus_threads_init_debug ()) die ("debug threads init"); @@ -164,7 +165,7 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir, const char *speci run_data_test ("auth", specific_test, _dbus_auth_test, test_data_dir); - printf ("%s: completed successfully\n", "dbus-test"); + printf ("%s: completed successfully\n", "test-dbus"); #else printf ("Not compiled with unit tests, not running any\n"); #endif diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c index bb1169db..12d40493 100644 --- a/dbus/dbus-threads.c +++ b/dbus/dbus-threads.c @@ -27,18 +27,6 @@ #include "dbus-list.h" static int thread_init_generation = 0; - -static DBusList *uninitialized_rmutex_list = NULL; -static DBusList *uninitialized_cmutex_list = NULL; -static DBusList *uninitialized_condvar_list = NULL; - -/** This is used for the no-op default mutex pointer, just to be distinct from #NULL */ -#define _DBUS_DUMMY_MUTEX ((DBusMutex*)0xABCDEF) -#define _DBUS_DUMMY_RMUTEX ((DBusRMutex *) _DBUS_DUMMY_MUTEX) -#define _DBUS_DUMMY_CMUTEX ((DBusCMutex *) _DBUS_DUMMY_MUTEX) - -/** This is used for the no-op default mutex pointer, just to be distinct from #NULL */ -#define _DBUS_DUMMY_CONDVAR ((DBusCondVar*)0xABCDEF2) /** * @defgroup DBusThreadsInternals Thread functions @@ -59,11 +47,6 @@ static DBusList *uninitialized_condvar_list = NULL; * If possible, the mutex returned by this function is recursive, to * avoid deadlocks. However, that cannot be relied on. * - * The extra level of indirection given by allocating a pointer - * to point to the mutex location allows the threading - * module to swap out dummy mutexes for a real mutex so libraries - * can initialize threads even after the D-Bus API has been used. - * * @param location_p the location of the new mutex, can return #NULL on OOM */ void @@ -71,17 +54,13 @@ _dbus_rmutex_new_at_location (DBusRMutex **location_p) { _dbus_assert (location_p != NULL); - if (thread_init_generation == _dbus_current_generation) + if (!dbus_threads_init_default ()) { - *location_p = _dbus_platform_rmutex_new (); + *location_p = NULL; + return; } - else - { - *location_p = _DBUS_DUMMY_RMUTEX; - if (!_dbus_list_append (&uninitialized_rmutex_list, location_p)) - *location_p = NULL; - } + *location_p = _dbus_platform_rmutex_new (); } /** @@ -92,11 +71,6 @@ _dbus_rmutex_new_at_location (DBusRMutex **location_p) * * The returned mutex is suitable for use with condition variables. * - * The extra level of indirection given by allocating a pointer - * to point to the mutex location allows the threading - * module to swap out dummy mutexes for a real mutex so libraries - * can initialize threads even after the D-Bus API has been used. - * * @param location_p the location of the new mutex, can return #NULL on OOM */ void @@ -104,22 +78,17 @@ _dbus_cmutex_new_at_location (DBusCMutex **location_p) { _dbus_assert (location_p != NULL); - if (thread_init_generation == _dbus_current_generation) + if (!dbus_threads_init_default ()) { - *location_p = _dbus_platform_cmutex_new (); + *location_p = NULL; + return; } - else - { - *location_p = _DBUS_DUMMY_CMUTEX; - if (!_dbus_list_append (&uninitialized_cmutex_list, location_p)) - *location_p = NULL; - } + *location_p = _dbus_platform_cmutex_new (); } /** - * Frees a DBusRMutex or removes it from the uninitialized mutex list; - * does nothing if passed a #NULL pointer. + * Frees a DBusRMutex; does nothing if passed a #NULL pointer. */ void _dbus_rmutex_free_at_location (DBusRMutex **location_p) @@ -127,23 +96,12 @@ _dbus_rmutex_free_at_location (DBusRMutex **location_p) if (location_p == NULL) return; - if (thread_init_generation == _dbus_current_generation) - { - if (*location_p != NULL) - _dbus_platform_rmutex_free (*location_p); - } - else - { - _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_RMUTEX); - - _dbus_list_remove (&uninitialized_rmutex_list, location_p); - } + if (*location_p != NULL) + _dbus_platform_rmutex_free (*location_p); } /** - * Frees a DBusCMutex and removes it from the - * uninitialized mutex list; - * does nothing if passed a #NULL pointer. + * Frees a DBusCMutex; does nothing if passed a #NULL pointer. */ void _dbus_cmutex_free_at_location (DBusCMutex **location_p) @@ -151,17 +109,8 @@ _dbus_cmutex_free_at_location (DBusCMutex **location_p) if (location_p == NULL) return; - if (thread_init_generation == _dbus_current_generation) - { - if (*location_p != NULL) - _dbus_platform_cmutex_free (*location_p); - } - else - { - _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_CMUTEX); - - _dbus_list_remove (&uninitialized_cmutex_list, location_p); - } + if (*location_p != NULL) + _dbus_platform_cmutex_free (*location_p); } /** @@ -172,8 +121,10 @@ _dbus_cmutex_free_at_location (DBusCMutex **location_p) void _dbus_rmutex_lock (DBusRMutex *mutex) { - if (mutex && thread_init_generation == _dbus_current_generation) - _dbus_platform_rmutex_lock (mutex); + if (mutex == NULL) + return; + + _dbus_platform_rmutex_lock (mutex); } /** @@ -184,8 +135,10 @@ _dbus_rmutex_lock (DBusRMutex *mutex) void _dbus_cmutex_lock (DBusCMutex *mutex) { - if (mutex && thread_init_generation == _dbus_current_generation) - _dbus_platform_cmutex_lock (mutex); + if (mutex == NULL) + return; + + _dbus_platform_cmutex_lock (mutex); } /** @@ -196,8 +149,10 @@ _dbus_cmutex_lock (DBusCMutex *mutex) void _dbus_rmutex_unlock (DBusRMutex *mutex) { - if (mutex && thread_init_generation == _dbus_current_generation) - _dbus_platform_rmutex_unlock (mutex); + if (mutex == NULL) + return; + + _dbus_platform_rmutex_unlock (mutex); } /** @@ -208,8 +163,10 @@ _dbus_rmutex_unlock (DBusRMutex *mutex) void _dbus_cmutex_unlock (DBusCMutex *mutex) { - if (mutex && thread_init_generation == _dbus_current_generation) - _dbus_platform_cmutex_unlock (mutex); + if (mutex == NULL) + return; + + _dbus_platform_cmutex_unlock (mutex); } /** @@ -223,19 +180,17 @@ _dbus_cmutex_unlock (DBusCMutex *mutex) DBusCondVar * _dbus_condvar_new (void) { - if (thread_init_generation == _dbus_current_generation) - return _dbus_platform_condvar_new (); - else - return _DBUS_DUMMY_CONDVAR; + if (!dbus_threads_init_default ()) + return NULL; + + return _dbus_platform_condvar_new (); } /** * This does the same thing as _dbus_condvar_new. It however * gives another level of indirection by allocating a pointer - * to point to the condvar location. This allows the threading - * module to swap out dummy condvars for a real condvar so libraries - * can initialize threads even after the D-Bus API has been used. + * to point to the condvar location; this used to be useful. * * @returns the location of a new condvar or #NULL on OOM */ @@ -245,17 +200,7 @@ _dbus_condvar_new_at_location (DBusCondVar **location_p) { _dbus_assert (location_p != NULL); - if (thread_init_generation == _dbus_current_generation) - { - *location_p = _dbus_condvar_new(); - } - else - { - *location_p = _DBUS_DUMMY_CONDVAR; - - if (!_dbus_list_append (&uninitialized_condvar_list, location_p)) - *location_p = NULL; - } + *location_p = _dbus_condvar_new(); } @@ -266,14 +211,14 @@ _dbus_condvar_new_at_location (DBusCondVar **location_p) void _dbus_condvar_free (DBusCondVar *cond) { - if (cond && thread_init_generation == _dbus_current_generation) - _dbus_platform_condvar_free (cond); + if (cond == NULL) + return; + + _dbus_platform_condvar_free (cond); } /** - * Frees a conditional variable and removes it from the - * uninitialized_condvar_list; - * does nothing if passed a #NULL pointer. + * Frees a condition variable; does nothing if passed a #NULL pointer. */ void _dbus_condvar_free_at_location (DBusCondVar **location_p) @@ -281,17 +226,8 @@ _dbus_condvar_free_at_location (DBusCondVar **location_p) if (location_p == NULL) return; - if (thread_init_generation == _dbus_current_generation) - { - if (*location_p != NULL) - _dbus_platform_condvar_free (*location_p); - } - else - { - _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_CONDVAR); - - _dbus_list_remove (&uninitialized_condvar_list, location_p); - } + if (*location_p != NULL) + _dbus_platform_condvar_free (*location_p); } /** @@ -304,8 +240,10 @@ void _dbus_condvar_wait (DBusCondVar *cond, DBusCMutex *mutex) { - if (cond && mutex && thread_init_generation == _dbus_current_generation) - _dbus_platform_condvar_wait (cond, mutex); + if (cond == NULL || mutex == NULL) + return; + + _dbus_platform_condvar_wait (cond, mutex); } /** @@ -324,11 +262,11 @@ _dbus_condvar_wait_timeout (DBusCondVar *cond, DBusCMutex *mutex, int timeout_milliseconds) { - if (cond && mutex && thread_init_generation == _dbus_current_generation) - return _dbus_platform_condvar_wait_timeout (cond, mutex, - timeout_milliseconds); - else + if (cond == NULL || mutex == NULL) return TRUE; + + return _dbus_platform_condvar_wait_timeout (cond, mutex, + timeout_milliseconds); } /** @@ -339,215 +277,83 @@ _dbus_condvar_wait_timeout (DBusCondVar *cond, void _dbus_condvar_wake_one (DBusCondVar *cond) { - if (cond && thread_init_generation == _dbus_current_generation) - _dbus_platform_condvar_wake_one (cond); + if (cond == NULL) + return; + + _dbus_platform_condvar_wake_one (cond); } +static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL }; + static void -shutdown_global_locks (void *data) +shutdown_global_locks (void *nil) { - DBusRMutex ***locks = data; int i; - i = 0; - while (i < _DBUS_N_GLOBAL_LOCKS) + for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++) { - if (*(locks[i]) != NULL) - _dbus_platform_rmutex_free (*(locks[i])); - - *(locks[i]) = NULL; - ++i; + _dbus_assert (global_locks[i] != NULL); + _dbus_platform_rmutex_free (global_locks[i]); + global_locks[i] = NULL; } - - dbus_free (locks); -} - -static void -shutdown_uninitialized_locks (void *data) -{ - _dbus_list_clear (&uninitialized_rmutex_list); - _dbus_list_clear (&uninitialized_cmutex_list); - _dbus_list_clear (&uninitialized_condvar_list); } static dbus_bool_t -init_uninitialized_locks (void) +init_global_locks (void) { - DBusList *link; - - _dbus_assert (thread_init_generation != _dbus_current_generation); - - link = uninitialized_rmutex_list; - while (link != NULL) - { - DBusRMutex **mp; - - mp = link->data; - _dbus_assert (*mp == _DBUS_DUMMY_RMUTEX); - - *mp = _dbus_platform_rmutex_new (); - if (*mp == NULL) - goto fail_mutex; - - link = _dbus_list_get_next_link (&uninitialized_rmutex_list, link); - } - - link = uninitialized_cmutex_list; - while (link != NULL) - { - DBusCMutex **mp; - - mp = link->data; - _dbus_assert (*mp == _DBUS_DUMMY_CMUTEX); - - *mp = _dbus_platform_cmutex_new (); - if (*mp == NULL) - goto fail_mutex; - - link = _dbus_list_get_next_link (&uninitialized_cmutex_list, link); - } + int i; + dbus_bool_t ok; - link = uninitialized_condvar_list; - while (link != NULL) + for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++) { - DBusCondVar **cp; - - cp = (DBusCondVar **)link->data; - _dbus_assert (*cp == _DBUS_DUMMY_CONDVAR); + _dbus_assert (global_locks[i] == NULL); - *cp = _dbus_platform_condvar_new (); - if (*cp == NULL) - goto fail_condvar; + global_locks[i] = _dbus_platform_rmutex_new (); - link = _dbus_list_get_next_link (&uninitialized_condvar_list, link); + if (global_locks[i] == NULL) + goto failed; } - _dbus_list_clear (&uninitialized_rmutex_list); - _dbus_list_clear (&uninitialized_cmutex_list); - _dbus_list_clear (&uninitialized_condvar_list); + _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]); + ok = _dbus_register_shutdown_func_unlocked (shutdown_global_locks, NULL); + _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]); - if (!_dbus_register_shutdown_func (shutdown_uninitialized_locks, - NULL)) - goto fail_condvar; + if (!ok) + goto failed; return TRUE; - fail_condvar: - link = uninitialized_condvar_list; - while (link != NULL) - { - DBusCondVar **cp; - - cp = link->data; - - if (*cp != _DBUS_DUMMY_CONDVAR && *cp != NULL) - _dbus_platform_condvar_free (*cp); - - *cp = _DBUS_DUMMY_CONDVAR; - - link = _dbus_list_get_next_link (&uninitialized_condvar_list, link); - } - - fail_mutex: - link = uninitialized_rmutex_list; - while (link != NULL) - { - DBusRMutex **mp; - - mp = link->data; - - if (*mp != _DBUS_DUMMY_RMUTEX && *mp != NULL) - _dbus_platform_rmutex_free (*mp); - - *mp = _DBUS_DUMMY_RMUTEX; - - link = _dbus_list_get_next_link (&uninitialized_rmutex_list, link); - } - - link = uninitialized_cmutex_list; - while (link != NULL) + failed: + for (i = i - 1; i >= 0; i--) { - DBusCMutex **mp; - - mp = link->data; - - if (*mp != _DBUS_DUMMY_CMUTEX && *mp != NULL) - _dbus_platform_cmutex_free (*mp); - - *mp = _DBUS_DUMMY_CMUTEX; - - link = _dbus_list_get_next_link (&uninitialized_cmutex_list, link); + _dbus_platform_rmutex_free (global_locks[i]); + global_locks[i] = NULL; } return FALSE; } -static dbus_bool_t -init_locks (void) +dbus_bool_t +_dbus_lock (DBusGlobalLock lock) { - int i; - DBusRMutex ***dynamic_global_locks; - DBusRMutex **global_locks[] = { -#define LOCK_ADDR(name) (& _dbus_lock_##name) - LOCK_ADDR (win_fds), - LOCK_ADDR (sid_atom_cache), - LOCK_ADDR (list), - LOCK_ADDR (connection_slots), - LOCK_ADDR (pending_call_slots), - LOCK_ADDR (server_slots), - LOCK_ADDR (message_slots), -#if !DBUS_USE_SYNC - LOCK_ADDR (atomic), -#endif - LOCK_ADDR (bus), - LOCK_ADDR (bus_datas), - LOCK_ADDR (shutdown_funcs), - LOCK_ADDR (system_users), - LOCK_ADDR (message_cache), - LOCK_ADDR (shared_connections), - LOCK_ADDR (machine_uuid) -#undef LOCK_ADDR - }; - - _dbus_assert (_DBUS_N_ELEMENTS (global_locks) == - _DBUS_N_GLOBAL_LOCKS); - - i = 0; - - dynamic_global_locks = dbus_new (DBusRMutex**, _DBUS_N_GLOBAL_LOCKS); - if (dynamic_global_locks == NULL) - goto failed; - - while (i < _DBUS_N_ELEMENTS (global_locks)) - { - *global_locks[i] = _dbus_platform_rmutex_new (); - - if (*global_locks[i] == NULL) - goto failed; + _dbus_assert (lock >= 0); + _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS); - dynamic_global_locks[i] = global_locks[i]; - - ++i; - } - - if (!_dbus_register_shutdown_func (shutdown_global_locks, - dynamic_global_locks)) - goto failed; + if (thread_init_generation != _dbus_current_generation && + !dbus_threads_init_default ()) + return FALSE; - if (!init_uninitialized_locks ()) - goto failed; - + _dbus_platform_rmutex_lock (global_locks[lock]); return TRUE; +} - failed: - dbus_free (dynamic_global_locks); - - for (i = i - 1; i >= 0; i--) - { - _dbus_platform_rmutex_free (*global_locks[i]); - *global_locks[i] = NULL; - } - return FALSE; +void +_dbus_unlock (DBusGlobalLock lock) +{ + _dbus_assert (lock >= 0); + _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS); + + _dbus_platform_rmutex_unlock (global_locks[lock]); } /** @} */ /* end of internals */ @@ -584,14 +390,24 @@ init_locks (void) dbus_bool_t dbus_threads_init (const DBusThreadFunctions *functions) { + _dbus_threads_lock_platform_specific (); + if (thread_init_generation == _dbus_current_generation) - return TRUE; + { + _dbus_threads_unlock_platform_specific (); + return TRUE; + } - if (!init_locks ()) - return FALSE; + if (!_dbus_threads_init_platform_specific() || + !init_global_locks ()) + { + _dbus_threads_unlock_platform_specific (); + return FALSE; + } thread_init_generation = _dbus_current_generation; - + + _dbus_threads_unlock_platform_specific (); return TRUE; } @@ -602,11 +418,16 @@ dbus_threads_init (const DBusThreadFunctions *functions) /** * Initializes threads. If this function is not called, the D-Bus * library will not lock any data structures. If it is called, D-Bus - * will do locking, at some cost in efficiency. Note that this - * function must be called BEFORE the second thread is started. + * will do locking, at some cost in efficiency. + * + * Since D-Bus 1.7 it is safe to call this function from any thread, + * any number of times (but it must be called before any other + * libdbus API is used). * - * It's safe to call dbus_threads_init_default() as many times as you - * want, but only the first time will have an effect. + * In D-Bus 1.6 or older, this function must be called in the main thread + * before any other thread starts. As a result, it is not sufficient to + * call this function in a library or plugin, unless the library or plugin + * imposes a similar requirement on its callers. * * dbus_shutdown() reverses the effects of this function when it * resets all global state in libdbus. @@ -616,18 +437,18 @@ dbus_threads_init (const DBusThreadFunctions *functions) dbus_bool_t dbus_threads_init_default (void) { - return _dbus_threads_init_platform_specific (); + return dbus_threads_init (NULL); } /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS dbus_bool_t _dbus_threads_init_debug (void) { - return _dbus_threads_init_platform_specific(); + return dbus_threads_init (NULL); } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 44b9d785..396f0ffd 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -111,7 +111,7 @@ struct DBusTransport DBusFreeFunction free_windows_user_data; /**< Function to free windows_user_data */ unsigned int disconnected : 1; /**< #TRUE if we are disconnected. */ - unsigned int authenticated : 1; /**< Cache of auth state; use _dbus_transport_get_is_authenticated() to query value */ + unsigned int authenticated : 1; /**< Cache of auth state; use _dbus_transport_peek_is_authenticated() to query value */ unsigned int send_credentials_pending : 1; /**< #TRUE if we need to send credentials */ unsigned int receive_credentials_pending : 1; /**< #TRUE if we need to receive credentials */ unsigned int is_server : 1; /**< #TRUE if on the server side */ diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index 0673a8ce..774f4598 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -135,7 +135,7 @@ check_write_watch (DBusTransport *transport) _dbus_transport_ref (transport); - if (_dbus_transport_get_is_authenticated (transport)) + if (_dbus_transport_try_to_authenticate (transport)) needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection); else { @@ -190,7 +190,7 @@ check_read_watch (DBusTransport *transport) _dbus_transport_ref (transport); - if (_dbus_transport_get_is_authenticated (transport)) + if (_dbus_transport_try_to_authenticate (transport)) need_read_watch = (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) && (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds); @@ -255,8 +255,7 @@ read_data_into_auth (DBusTransport *transport, bytes_read = _dbus_read_socket (socket_transport->fd, buffer, socket_transport->max_bytes_read_per_iteration); - _dbus_auth_return_buffer (transport->auth, buffer, - bytes_read > 0 ? bytes_read : 0); + _dbus_auth_return_buffer (transport->auth, buffer); if (bytes_read > 0) { @@ -404,7 +403,7 @@ do_authentication (DBusTransport *transport, oom = FALSE; - orig_auth_state = _dbus_transport_get_is_authenticated (transport); + orig_auth_state = _dbus_transport_try_to_authenticate (transport); /* This is essential to avoid the check_write_watch() at the end, * we don't want to add a write watch in do_iteration before @@ -419,7 +418,7 @@ do_authentication (DBusTransport *transport, _dbus_transport_ref (transport); - while (!_dbus_transport_get_is_authenticated (transport) && + while (!_dbus_transport_try_to_authenticate (transport) && _dbus_transport_get_is_connected (transport)) { if (!exchange_credentials (transport, do_reading, do_writing)) @@ -477,7 +476,7 @@ do_authentication (DBusTransport *transport, out: if (auth_completed) - *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport)); + *auth_completed = (orig_auth_state != _dbus_transport_try_to_authenticate (transport)); check_read_watch (transport); check_write_watch (transport); @@ -498,7 +497,7 @@ do_writing (DBusTransport *transport) dbus_bool_t oom; /* No messages without authentication! */ - if (!_dbus_transport_get_is_authenticated (transport)) + if (!_dbus_transport_try_to_authenticate (transport)) { _dbus_verbose ("Not authenticated, not writing anything\n"); return TRUE; @@ -703,7 +702,7 @@ do_reading (DBusTransport *transport) _dbus_verbose ("fd = %d\n",socket_transport->fd); /* No messages without authentication! */ - if (!_dbus_transport_get_is_authenticated (transport)) + if (!_dbus_transport_try_to_authenticate (transport)) return TRUE; oom = FALSE; @@ -748,29 +747,23 @@ do_reading (DBusTransport *transport) if (bytes_read > 0) { - int orig_len; - _dbus_message_loader_get_buffer (transport->loader, &buffer); - orig_len = _dbus_string_get_length (buffer); - if (!_dbus_auth_decode_data (transport->auth, &socket_transport->encoded_incoming, buffer)) { _dbus_verbose ("Out of memory decoding incoming data\n"); _dbus_message_loader_return_buffer (transport->loader, - buffer, - _dbus_string_get_length (buffer) - orig_len); + buffer); oom = TRUE; goto out; } _dbus_message_loader_return_buffer (transport->loader, - buffer, - _dbus_string_get_length (buffer) - orig_len); + buffer); _dbus_string_set_length (&socket_transport->encoded_incoming, 0); _dbus_string_compact (&socket_transport->encoded_incoming, 2048); @@ -789,7 +782,7 @@ do_reading (DBusTransport *transport) if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds)) { _dbus_verbose ("Out of memory reading file descriptors\n"); - _dbus_message_loader_return_buffer (transport->loader, buffer, 0); + _dbus_message_loader_return_buffer (transport->loader, buffer); oom = TRUE; goto out; } @@ -812,8 +805,7 @@ do_reading (DBusTransport *transport) } _dbus_message_loader_return_buffer (transport->loader, - buffer, - bytes_read < 0 ? 0 : bytes_read); + buffer); } if (bytes_read < 0) @@ -1055,7 +1047,7 @@ socket_do_iteration (DBusTransport *transport, poll_fd.fd = socket_transport->fd; poll_fd.events = 0; - if (_dbus_transport_get_is_authenticated (transport)) + if (_dbus_transport_try_to_authenticate (transport)) { /* This is kind of a hack; if we have stuff to write, then try * to avoid the poll. This is probably about a 5% speedup on an @@ -1299,7 +1291,7 @@ _dbus_transport_new_for_socket (int fd, * @param host the host to connect to * @param port the port to connect to * @param family the address family to connect to - * @param path to nonce file + * @param noncefile path to nonce file * @param error location to store reason for failure. * @returns a new transport, or #NULL on failure. */ @@ -1337,12 +1329,12 @@ _dbus_transport_new_for_tcp_socket (const char *host, goto error; if (family != NULL && - (!_dbus_string_append (&address, "family=") || + (!_dbus_string_append (&address, ",family=") || !_dbus_string_append (&address, family))) goto error; if (noncefile != NULL && - (!_dbus_string_append (&address, "noncefile=") || + (!_dbus_string_append (&address, ",noncefile=") || !_dbus_string_append (&address, noncefile))) goto error; diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index 6ba5c0b5..9a9fea50 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -412,7 +412,7 @@ _dbus_transport_open_platform_specific (DBusAddressEntry *entry, /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS dbus_bool_t _dbus_transport_unix_test (void) diff --git a/dbus/dbus-transport-win.c b/dbus/dbus-transport-win.c index faaf1bd2..8fc15749 100644 --- a/dbus/dbus-transport-win.c +++ b/dbus/dbus-transport-win.c @@ -51,39 +51,8 @@ _dbus_transport_open_platform_specific (DBusAddressEntry *entry, DBusTransport **transport_p, DBusError *error) { - const char *method; - - const char *host = dbus_address_entry_get_value (entry, "host"); - const char *port = dbus_address_entry_get_value (entry, "port"); - const char *family = dbus_address_entry_get_value (entry, "family"); - const char *noncefile = dbus_address_entry_get_value (entry, "noncefile"); - - method = dbus_address_entry_get_method (entry); - _dbus_assert (method != NULL); - - if (strcmp (method, "nonce-tcp") != 0) - { - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - return DBUS_TRANSPORT_OPEN_NOT_HANDLED; - } - - if (port == NULL) - { - _dbus_set_bad_address (error, "nonce-tcp", "port", NULL); - return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; - } - - *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error); - if (*transport_p == NULL) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; - } - else - { - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - return DBUS_TRANSPORT_OPEN_OK; - } + /* currently no Windows-specific transports */ + return DBUS_TRANSPORT_OPEN_NOT_HANDLED; } /** @} */ diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index ba720f25..ecc31827 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -32,7 +32,7 @@ #include "dbus-credentials.h" #include "dbus-mainloop.h" #include "dbus-message.h" -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-server-debug-pipe.h" #endif @@ -242,6 +242,7 @@ _dbus_transport_finalize_base (DBusTransport *transport) * opened DBusTransport object. If it isn't, returns #NULL * and sets @p error. * + * @param address the address to be checked. * @param error address where an error can be returned. * @returns a new transport, or #NULL on failure. */ @@ -253,7 +254,6 @@ check_address (const char *address, DBusError *error) int len, i; _dbus_assert (address != NULL); - _dbus_assert (*address != '\0'); if (!dbus_parse_address (address, &entries, &len, error)) return NULL; /* not a valid address */ @@ -273,6 +273,7 @@ check_address (const char *address, DBusError *error) * Creates a new transport for the "autostart" method. * This creates a client-side of a transport. * + * @param scope scope of autolaunch (Windows only) * @param error address where an error can be returned. * @returns a new transport, or #NULL on failure. */ @@ -349,7 +350,7 @@ static const struct { { _dbus_transport_open_socket }, { _dbus_transport_open_platform_specific }, { _dbus_transport_open_autolaunch } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS , { _dbus_transport_open_debug_pipe } #endif }; @@ -685,10 +686,33 @@ auth_via_default_rules (DBusTransport *transport) return allow; } +/** + * Returns #TRUE if we have been authenticated. It will return #TRUE even if + * the transport is now disconnected, but was ever authenticated before + * disconnecting. + * + * This replaces the older _dbus_transport_get_is_authenticated() which + * had side-effects. + * + * @param transport the transport + * @returns whether we're authenticated + */ +dbus_bool_t +_dbus_transport_peek_is_authenticated (DBusTransport *transport) +{ + return transport->authenticated; +} /** - * Returns #TRUE if we have been authenticated. Will return #TRUE - * even if the transport is disconnected. + * Returns #TRUE if we have been authenticated. It will return #TRUE even if + * the transport is now disconnected, but was ever authenticated before + * disconnecting. + * + * If we have not finished authenticating, but we have enough buffered input + * to finish the job, then this function will do so before it returns. + * + * This used to be called _dbus_transport_get_is_authenticated(), but that + * name seems inappropriate for a function with side-effects. * * @todo we drop connection->mutex when calling the unix_user_function, * and windows_user_function, which may not be safe really. @@ -697,7 +721,7 @@ auth_via_default_rules (DBusTransport *transport) * @returns whether we're authenticated */ dbus_bool_t -_dbus_transport_get_is_authenticated (DBusTransport *transport) +_dbus_transport_try_to_authenticate (DBusTransport *transport) { if (transport->authenticated) return TRUE; @@ -1021,9 +1045,7 @@ recover_unused_bytes (DBusTransport *transport) orig_len); _dbus_message_loader_return_buffer (transport->loader, - buffer, - _dbus_string_get_length (buffer) - - orig_len); + buffer); _dbus_auth_delete_unused_bytes (transport->auth); @@ -1053,9 +1075,7 @@ recover_unused_bytes (DBusTransport *transport) orig_len); _dbus_message_loader_return_buffer (transport->loader, - buffer, - _dbus_string_get_length (buffer) - - orig_len); + buffer); if (succeeded) _dbus_auth_delete_unused_bytes (transport->auth); @@ -1084,12 +1104,12 @@ _dbus_transport_get_dispatch_status (DBusTransport *transport) _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) return DBUS_DISPATCH_COMPLETE; /* complete for now */ - if (!_dbus_transport_get_is_authenticated (transport)) + if (!_dbus_transport_try_to_authenticate (transport)) { if (_dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_WAITING_FOR_MEMORY) return DBUS_DISPATCH_NEED_MEMORY; - else if (!_dbus_transport_get_is_authenticated (transport)) + else if (!_dbus_transport_try_to_authenticate (transport)) return DBUS_DISPATCH_COMPLETE; } @@ -1338,7 +1358,7 @@ _dbus_transport_get_unix_process_id (DBusTransport *transport, if (_dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_PROCESS_ID)) { - *pid = _dbus_credentials_get_unix_pid (auth_identity); + *pid = _dbus_credentials_get_pid (auth_identity); return TRUE; } else diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 4b821517..80fa24ef 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -38,7 +38,8 @@ DBusTransport* _dbus_transport_ref (DBusTransport void _dbus_transport_unref (DBusTransport *transport); void _dbus_transport_disconnect (DBusTransport *transport); dbus_bool_t _dbus_transport_get_is_connected (DBusTransport *transport); -dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport); +dbus_bool_t _dbus_transport_peek_is_authenticated (DBusTransport *transport); +dbus_bool_t _dbus_transport_try_to_authenticate (DBusTransport *transport); dbus_bool_t _dbus_transport_get_is_anonymous (DBusTransport *transport); dbus_bool_t _dbus_transport_can_pass_unix_fd (DBusTransport *transport); diff --git a/dbus/dbus-types.h b/dbus/dbus-types.h index 57fc586a..021a55af 100644 --- a/dbus/dbus-types.h +++ b/dbus/dbus-types.h @@ -79,43 +79,23 @@ typedef dbus_uint32_t dbus_bool_t; /** * @typedef dbus_uint64_t * - * A 64-bit unsigned integer on all platforms that support it. - * If supported, #DBUS_HAVE_INT64 will be defined. - * - * C99 requires a 64-bit type and most likely all interesting - * compilers support one. GLib for example flat-out requires - * a 64-bit type. - * - * You probably want to just assume #DBUS_HAVE_INT64 is always defined. + * A 64-bit unsigned integer. */ /** * @typedef dbus_int64_t * - * A 64-bit signed integer on all platforms that support it. - * If supported, #DBUS_HAVE_INT64 will be defined. - * - * C99 requires a 64-bit type and most likely all interesting - * compilers support one. GLib for example flat-out requires - * a 64-bit type. - * - * You probably want to just assume #DBUS_HAVE_INT64 is always defined. + * A 64-bit signed integer. */ /** * @def DBUS_HAVE_INT64 * - * Defined if 64-bit integers are available. Will be defined - * on any platform you care about, unless you care about - * some truly ancient UNIX, or some bizarre embedded platform. + * Always defined. * - * C99 requires a 64-bit type and most likely all interesting - * compilers support one. GLib for example flat-out requires - * a 64-bit type. - * - * You should feel comfortable ignoring this macro and just using - * int64 unconditionally. - * + * In older libdbus versions, this would be undefined if there was no + * 64-bit integer type on that platform. libdbus no longer supports + * such platforms. */ /** @@ -136,7 +116,7 @@ typedef dbus_uint32_t dbus_bool_t; /** * An 8-byte struct you could use to access int64 without having - * int64 support + * int64 support. Use #dbus_int64_t or #dbus_uint64_t instead. */ typedef struct { @@ -162,10 +142,8 @@ typedef union dbus_int32_t i32; /**< as int32 */ dbus_uint32_t u32; /**< as int32 */ dbus_bool_t bool_val; /**< as boolean */ -#ifdef DBUS_HAVE_INT64 dbus_int64_t i64; /**< as int64 */ dbus_uint64_t u64; /**< as int64 */ -#endif DBus8ByteStruct eight; /**< as 8-byte struct */ double dbl; /**< as double */ unsigned char byt; /**< as byte */ diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c index 16bf2291..888a23e9 100644 --- a/dbus/dbus-userdb-util.c +++ b/dbus/dbus-userdb-util.c @@ -21,6 +21,7 @@ * */ #include <config.h> +#include <unistd.h> #define DBUS_USERDB_INCLUDES_PRIVATE 1 #include "dbus-userdb.h" #include "dbus-test.h" @@ -29,7 +30,6 @@ #include <string.h> #if HAVE_SYSTEMD -#include <systemd/sd-daemon.h> #include <systemd/sd-login.h> #endif @@ -55,7 +55,8 @@ _dbus_is_console_user (dbus_uid_t uid, dbus_bool_t result = FALSE; #ifdef HAVE_SYSTEMD - if (sd_booted () > 0) + /* check if we have logind */ + if (access ("/run/systemd/seats/", F_OK) >= 0) { int r; @@ -103,7 +104,11 @@ _dbus_is_console_user (dbus_uid_t uid, #endif /* HAVE_CONSOLE_OWNER_FILE */ - _dbus_user_database_lock_system (); + if (!_dbus_user_database_lock_system ()) + { + _DBUS_SET_OOM (error); + return FALSE; + } db = _dbus_user_database_get_system (); if (db == NULL) @@ -157,7 +162,10 @@ _dbus_get_group_id (const DBusString *groupname, { DBusUserDatabase *db; const DBusGroupInfo *info; - _dbus_user_database_lock_system (); + + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) @@ -194,7 +202,10 @@ _dbus_get_user_id_and_primary_group (const DBusString *username, { DBusUserDatabase *db; const DBusUserInfo *info; - _dbus_user_database_lock_system (); + + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) @@ -250,7 +261,6 @@ _dbus_user_database_lookup_group (DBusUserDatabase *db, gid = n; } -#ifdef DBUS_ENABLE_USERDB_CACHE if (gid != DBUS_GID_UNSET) info = _dbus_hash_table_lookup_uintptr (db->groups, gid); else @@ -263,9 +273,6 @@ _dbus_user_database_lookup_group (DBusUserDatabase *db, return info; } else -#else - if (1) -#endif { if (gid != DBUS_GID_UNSET) _dbus_verbose ("No cache for GID "DBUS_GID_FORMAT"\n", @@ -387,7 +394,9 @@ _dbus_groups_from_uid (dbus_uid_t uid, *group_ids = NULL; *n_group_ids = 0; - _dbus_user_database_lock_system (); + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) @@ -424,7 +433,7 @@ _dbus_groups_from_uid (dbus_uid_t uid, } /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include <stdio.h> /** @@ -477,4 +486,4 @@ _dbus_userdb_test (const char *test_data_dir) return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c index 4e8b39aa..52f927a3 100644 --- a/dbus/dbus-userdb.c +++ b/dbus/dbus-userdb.c @@ -144,7 +144,6 @@ _dbus_user_database_lookup (DBusUserDatabase *db, uid = n; } -#ifdef DBUS_ENABLE_USERDB_CACHE if (uid != DBUS_UID_UNSET) info = _dbus_hash_table_lookup_uintptr (db->users, uid); else @@ -157,9 +156,6 @@ _dbus_user_database_lookup (DBusUserDatabase *db, return info; } else -#else - if (1) -#endif { if (uid != DBUS_UID_UNSET) _dbus_verbose ("No cache for UID "DBUS_UID_FORMAT"\n", @@ -306,11 +302,18 @@ init_system_db (void) /** * Locks global system user database. */ -void +dbus_bool_t _dbus_user_database_lock_system (void) { - _DBUS_LOCK (system_users); - database_locked = TRUE; + if (_DBUS_LOCK (system_users)) + { + database_locked = TRUE; + return TRUE; + } + else + { + return FALSE; + } } /** @@ -345,8 +348,12 @@ _dbus_user_database_get_system (void) void _dbus_user_database_flush_system (void) { - _dbus_user_database_lock_system (); - + if (!_dbus_user_database_lock_system ()) + { + /* nothing to flush */ + return; + } + if (system_db != NULL) _dbus_user_database_flush (system_db); @@ -363,7 +370,9 @@ _dbus_user_database_flush_system (void) dbus_bool_t _dbus_username_from_current_process (const DBusString **username) { - _dbus_user_database_lock_system (); + if (!_dbus_user_database_lock_system ()) + return FALSE; + if (!init_system_db ()) { _dbus_user_database_unlock_system (); @@ -385,7 +394,9 @@ _dbus_username_from_current_process (const DBusString **username) dbus_bool_t _dbus_homedir_from_current_process (const DBusString **homedir) { - _dbus_user_database_lock_system (); + if (!_dbus_user_database_lock_system ()) + return FALSE; + if (!init_system_db ()) { _dbus_user_database_unlock_system (); @@ -410,7 +421,10 @@ _dbus_homedir_from_username (const DBusString *username, { DBusUserDatabase *db; const DBusUserInfo *info; - _dbus_user_database_lock_system (); + + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) @@ -449,7 +463,10 @@ _dbus_homedir_from_uid (dbus_uid_t uid, { DBusUserDatabase *db; const DBusUserInfo *info; - _dbus_user_database_lock_system (); + + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) @@ -496,7 +513,9 @@ _dbus_credentials_add_from_user (DBusCredentials *credentials, DBusUserDatabase *db; const DBusUserInfo *info; - _dbus_user_database_lock_system (); + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) @@ -579,7 +598,7 @@ _dbus_user_database_flush (DBusUserDatabase *db) _dbus_hash_table_remove_all(db->groups); } -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * Increments refcount of user database. * @param db the database @@ -594,7 +613,7 @@ _dbus_user_database_ref (DBusUserDatabase *db) return db; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ /** * Decrements refcount of user database. diff --git a/dbus/dbus-userdb.h b/dbus/dbus-userdb.h index cb49d9e7..d6b72d8c 100644 --- a/dbus/dbus-userdb.h +++ b/dbus/dbus-userdb.h @@ -86,7 +86,7 @@ void _dbus_group_info_free_allocated (DBusGroupInfo *info); #endif /* DBUS_USERDB_INCLUDES_PRIVATE */ DBusUserDatabase* _dbus_user_database_get_system (void); -void _dbus_user_database_lock_system (void); +dbus_bool_t _dbus_user_database_lock_system (void) _DBUS_GNUC_WARN_UNUSED_RESULT; void _dbus_user_database_unlock_system (void); void _dbus_user_database_flush_system (void); diff --git a/dbus/dbus-valgrind-internal.h b/dbus/dbus-valgrind-internal.h index 55566ec0..6760b40d 100644 --- a/dbus/dbus-valgrind-internal.h +++ b/dbus/dbus-valgrind-internal.h @@ -32,10 +32,10 @@ # include <memcheck.h> # include <valgrind.h> #else -# define VALGRIND_CREATE_MEMPOOL(_1, _2, _3) /* nothing */ -# define VALGRIND_DESTROY_MEMPOOL(_1) /* nothing */ -# define VALGRIND_MEMPOOL_ALLOC(_1, _2, _3) /* nothing */ -# define VALGRIND_MEMPOOL_FREE(_1, _2) /* nothing */ +# define VALGRIND_CREATE_MEMPOOL(_1, _2, _3) do { } while (0) +# define VALGRIND_DESTROY_MEMPOOL(_1) do { } while (0) +# define VALGRIND_MEMPOOL_ALLOC(_1, _2, _3) do { } while (0) +# define VALGRIND_MEMPOOL_FREE(_1, _2) do { } while (0) /* Recent gcc will warn if you have a statement that's just a macro * expanding to (0), but not if you have an inline stub function that diff --git a/dbus/dbus-watch.c b/dbus/dbus-watch.c index b9f4ac23..b82c57d4 100644 --- a/dbus/dbus-watch.c +++ b/dbus/dbus-watch.c @@ -259,6 +259,25 @@ _dbus_watch_list_free (DBusWatchList *watch_list) dbus_free (watch_list); } +#ifdef DBUS_ENABLE_VERBOSE_MODE +static const char* +watch_flags_to_string (int flags) +{ + const char *watch_type; + + if ((flags & DBUS_WATCH_READABLE) && + (flags & DBUS_WATCH_WRITABLE)) + watch_type = "readwrite"; + else if (flags & DBUS_WATCH_READABLE) + watch_type = "read"; + else if (flags & DBUS_WATCH_WRITABLE) + watch_type = "write"; + else + watch_type = "not read or write"; + return watch_type; +} +#endif /* DBUS_ENABLE_VERBOSE_MODE */ + /** * Sets the watch functions. This function is the "backend" * for dbus_connection_set_watch_functions() and @@ -292,27 +311,9 @@ _dbus_watch_list_set_functions (DBusWatchList *watch_list, DBusList *next = _dbus_list_get_next_link (&watch_list->watches, link); -#ifdef DBUS_ENABLE_VERBOSE_MODE - { - const char *watch_type; - int flags; - - flags = dbus_watch_get_flags (link->data); - if ((flags & DBUS_WATCH_READABLE) && - (flags & DBUS_WATCH_WRITABLE)) - watch_type = "readwrite"; - else if (flags & DBUS_WATCH_READABLE) - watch_type = "read"; - else if (flags & DBUS_WATCH_WRITABLE) - watch_type = "write"; - else - watch_type = "not read or write"; - - _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n", - watch_type, - dbus_watch_get_socket (link->data)); - } -#endif /* DBUS_ENABLE_VERBOSE_MODE */ + _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n", + watch_flags_to_string (dbus_watch_get_flags (link->data)), + dbus_watch_get_socket (link->data)); if (!(* add_function) (link->data, data)) { diff --git a/dbus/sd-daemon.c b/dbus/sd-daemon.c index 9c23b917..485b3010 100644 --- a/dbus/sd-daemon.c +++ b/dbus/sd-daemon.c @@ -25,14 +25,14 @@ ***/ #ifndef _GNU_SOURCE -#define _GNU_SOURCE +# define _GNU_SOURCE #endif #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/un.h> -#include <sys/fcntl.h> +#include <fcntl.h> #include <netinet/in.h> #include <stdlib.h> #include <errno.h> @@ -40,10 +40,28 @@ #include <string.h> #include <stdarg.h> #include <stdio.h> +#include <stddef.h> +#include <limits.h> + +#if defined(__linux__) && !defined(SD_DAEMON_DISABLE_MQ) +# include <mqueue.h> +#endif #include "sd-daemon.h" -int sd_listen_fds(int unset_environment) { +#if (__GNUC__ >= 4) +# ifdef SD_EXPORT_SYMBOLS +/* Export symbols */ +# define _sd_export_ __attribute__ ((visibility("default"))) +# else +/* Don't export the symbols */ +# define _sd_export_ __attribute__ ((visibility("hidden"))) +# endif +#else +# define _sd_export_ +#endif + +_sd_export_ int sd_listen_fds(int unset_environment) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; @@ -53,7 +71,8 @@ int sd_listen_fds(int unset_environment) { char *p = NULL; unsigned long l; - if (!(e = getenv("LISTEN_PID"))) { + e = getenv("LISTEN_PID"); + if (!e) { r = 0; goto finish; } @@ -61,12 +80,12 @@ int sd_listen_fds(int unset_environment) { errno = 0; l = strtoul(e, &p, 10); - if (errno != 0) { + if (errno > 0) { r = -errno; goto finish; } - if (!p || *p || l <= 0) { + if (!p || p == e || *p || l <= 0) { r = -EINVAL; goto finish; } @@ -77,7 +96,8 @@ int sd_listen_fds(int unset_environment) { goto finish; } - if (!(e = getenv("LISTEN_FDS"))) { + e = getenv("LISTEN_FDS"); + if (!e) { r = 0; goto finish; } @@ -85,12 +105,12 @@ int sd_listen_fds(int unset_environment) { errno = 0; l = strtoul(e, &p, 10); - if (errno != 0) { + if (errno > 0) { r = -errno; goto finish; } - if (!p || *p) { + if (!p || p == e || *p) { r = -EINVAL; goto finish; } @@ -98,7 +118,8 @@ int sd_listen_fds(int unset_environment) { for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { int flags; - if ((flags = fcntl(fd, F_GETFD)) < 0) { + flags = fcntl(fd, F_GETFD); + if (flags < 0) { r = -errno; goto finish; } @@ -124,13 +145,12 @@ finish: #endif } -int sd_is_fifo(int fd, const char *path) { +_sd_export_ int sd_is_fifo(int fd, const char *path) { struct stat st_fd; if (fd < 0) return -EINVAL; - memset(&st_fd, 0, sizeof(st_fd)); if (fstat(fd, &st_fd) < 0) return -errno; @@ -140,7 +160,6 @@ int sd_is_fifo(int fd, const char *path) { if (path) { struct stat st_path; - memset(&st_path, 0, sizeof(st_path)); if (stat(path, &st_path) < 0) { if (errno == ENOENT || errno == ENOTDIR) @@ -157,6 +176,42 @@ int sd_is_fifo(int fd, const char *path) { return 1; } +_sd_export_ int sd_is_special(int fd, const char *path) { + struct stat st_fd; + + if (fd < 0) + return -EINVAL; + + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) + return 0; + + if (path) { + struct stat st_path; + + if (stat(path, &st_path) < 0) { + + if (errno == ENOENT || errno == ENOTDIR) + return 0; + + return -errno; + } + + if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) + return + st_path.st_dev == st_fd.st_dev && + st_path.st_ino == st_fd.st_ino; + else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) + return st_path.st_rdev == st_fd.st_rdev; + else + return 0; + } + + return 1; +} + static int sd_is_socket_internal(int fd, int type, int listening) { struct stat st_fd; @@ -208,21 +263,19 @@ union sockaddr_union { struct sockaddr_storage storage; }; -int sd_is_socket(int fd, int family, int type, int listening) { +_sd_export_ int sd_is_socket(int fd, int family, int type, int listening) { int r; if (family < 0) return -EINVAL; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; if (family > 0) { - union sockaddr_union sockaddr; - socklen_t l; - - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; @@ -236,20 +289,18 @@ int sd_is_socket(int fd, int family, int type, int listening) { return 1; } -int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { - union sockaddr_union sockaddr; - socklen_t l; +_sd_export_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); int r; if (family != 0 && family != AF_INET && family != AF_INET6) return -EINVAL; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); - if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; @@ -281,17 +332,15 @@ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port return 1; } -int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { - union sockaddr_union sockaddr; - socklen_t l; +_sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); int r; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); - if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; @@ -302,29 +351,66 @@ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t return 0; if (path) { - if (length <= 0) + if (length == 0) length = strlen(path); - if (length <= 0) + if (length == 0) /* Unnamed socket */ - return l == sizeof(sa_family_t); + return l == offsetof(struct sockaddr_un, sun_path); if (path[0]) /* Normal path socket */ return - (l >= sizeof(sa_family_t) + length + 1) && + (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && memcmp(path, sockaddr.un.sun_path, length+1) == 0; else /* Abstract namespace socket */ return - (l == sizeof(sa_family_t) + length) && + (l == offsetof(struct sockaddr_un, sun_path) + length) && memcmp(path, sockaddr.un.sun_path, length) == 0; } return 1; } -int sd_notify(int unset_environment, const char *state) { +_sd_export_ int sd_is_mq(int fd, const char *path) { +#if !defined(__linux__) || defined(SD_DAEMON_DISABLE_MQ) + return 0; +#else + struct mq_attr attr; + + if (fd < 0) + return -EINVAL; + + if (mq_getattr(fd, &attr) < 0) + return -errno; + + if (path) { + char fpath[PATH_MAX]; + struct stat a, b; + + if (path[0] != '/') + return -EINVAL; + + if (fstat(fd, &a) < 0) + return -errno; + + strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); + fpath[sizeof(fpath)-1] = 0; + + if (stat(fpath, &b) < 0) + return -errno; + + if (a.st_dev != b.st_dev || + a.st_ino != b.st_ino) + return 0; + } + + return 1; +#endif +} + +_sd_export_ int sd_notify(int unset_environment, const char *state) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) return 0; #else @@ -339,7 +425,8 @@ int sd_notify(int unset_environment, const char *state) { goto finish; } - if (!(e = getenv("NOTIFY_SOCKET"))) + e = getenv("NOTIFY_SOCKET"); + if (!e) return 0; /* Must be an abstract socket, or an absolute path */ @@ -348,7 +435,8 @@ int sd_notify(int unset_environment, const char *state) { goto finish; } - if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) { r = -errno; goto finish; } @@ -366,7 +454,7 @@ int sd_notify(int unset_environment, const char *state) { memset(&msghdr, 0, sizeof(msghdr)); msghdr.msg_name = &sockaddr; - msghdr.msg_namelen = sizeof(sa_family_t) + strlen(e); + msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) msghdr.msg_namelen = sizeof(struct sockaddr_un); @@ -392,7 +480,7 @@ finish: #endif } -int sd_notifyf(int unset_environment, const char *format, ...) { +_sd_export_ int sd_notifyf(int unset_environment, const char *format, ...) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; #else @@ -414,22 +502,19 @@ int sd_notifyf(int unset_environment, const char *format, ...) { #endif } -int sd_booted(void) { +_sd_export_ int sd_booted(void) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; #else + struct stat st; - struct stat a, b; - - /* We simply test whether the systemd cgroup hierarchy is - * mounted */ - - if (lstat("/sys/fs/cgroup", &a) < 0) - return 0; + /* We test whether the runtime unit file directory has been + * created. This takes place in mount-setup.c, so is + * guaranteed to happen very early during boot. */ - if (lstat("/sys/fs/cgroup/systemd", &b) < 0) + if (lstat("/run/systemd/system/", &st) < 0) return 0; - return a.st_dev != b.st_dev; + return !!S_ISDIR(st.st_mode); #endif } diff --git a/dbus/sd-daemon.h b/dbus/sd-daemon.h index c68c96d2..fb7456d5 100644 --- a/dbus/sd-daemon.h +++ b/dbus/sd-daemon.h @@ -58,21 +58,21 @@ extern "C" { You may find an up-to-date version of these source files online: - http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h - http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c + http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h + http://cgit.freedesktop.org/systemd/systemd/plain/src/libsystemd-daemon/sd-daemon.c This should compile on non-Linux systems, too, but with the exception of the sd_is_xxx() calls all functions will become NOPs. - See sd-daemon(7) for more information. + See sd-daemon(3) for more information. */ +#ifndef _sd_printf_attr_ #if __GNUC__ >= 4 #define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) -#define _sd_hidden_ __attribute__ ((visibility("hidden"))) #else #define _sd_printf_attr_(a,b) -#define _sd_hidden_ +#endif #endif /* @@ -109,7 +109,7 @@ extern "C" { See sd_listen_fds(3) for more information. */ -int sd_listen_fds(int unset_environment) _sd_hidden_; +int sd_listen_fds(int unset_environment); /* Helper call for identifying a passed file descriptor. Returns 1 if @@ -121,7 +121,19 @@ int sd_listen_fds(int unset_environment) _sd_hidden_; See sd_is_fifo(3) for more information. */ -int sd_is_fifo(int fd, const char *path) _sd_hidden_; +int sd_is_fifo(int fd, const char *path); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a special character device on the file + system stored under the specified path, 0 otherwise. + If path is NULL a path name check will not be done and the call + only verifies if the file descriptor refers to a special character. + Returns a negative errno style error code on failure. + + See sd_is_special(3) for more information. +*/ +int sd_is_special(int fd, const char *path); /* Helper call for identifying a passed file descriptor. Returns 1 if @@ -137,7 +149,7 @@ int sd_is_fifo(int fd, const char *path) _sd_hidden_; See sd_is_socket(3) for more information. */ -int sd_is_socket(int fd, int family, int type, int listening) _sd_hidden_; +int sd_is_socket(int fd, int family, int type, int listening); /* Helper call for identifying a passed file descriptor. Returns 1 if @@ -151,7 +163,7 @@ int sd_is_socket(int fd, int family, int type, int listening) _sd_hidden_; See sd_is_socket_inet(3) for more information. */ -int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) _sd_hidden_; +int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); /* Helper call for identifying a passed file descriptor. Returns 1 if @@ -167,17 +179,25 @@ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port See sd_is_socket_unix(3) for more information. */ -int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) _sd_hidden_; +int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a POSIX Message Queue of the specified name, + 0 otherwise. If path is NULL a message queue name check is not + done. Returns a negative errno style error code on failure. +*/ +int sd_is_mq(int fd, const char *path); /* Informs systemd about changed daemon state. This takes a number of - newline seperated environment-style variable assignments in a + newline separated environment-style variable assignments in a string. The following variables are known: READY=1 Tells systemd that daemon startup is finished (only relevant for services of Type=notify). The passed argument is a boolean "1" or "0". Since there is - little value in signalling non-readiness the only + little value in signaling non-readiness the only value daemons should send is "READY=1". STATUS=... Passes a single-line status string back to systemd @@ -197,8 +217,13 @@ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t MAINPID=... The main pid of a daemon, in case systemd did not fork off the process itself. Example: "MAINPID=4711" + WATCHDOG=1 Tells systemd to update the watchdog timestamp. + Services using this feature should do this in + regular intervals. A watchdog framework can use the + timestamps to detect failed services. + Daemons can choose to send additional variables. However, it is - recommened to prefix variable names not listed above with X_. + recommended to prefix variable names not listed above with X_. Returns a negative errno-style error code on failure. Returns > 0 if systemd could be notified, 0 if it couldn't possibly because @@ -213,7 +238,7 @@ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t See sd_notify(3) for more information. */ -int sd_notify(int unset_environment, const char *state) _sd_hidden_; +int sd_notify(int unset_environment, const char *state); /* Similar to sd_notify() but takes a format string. @@ -235,7 +260,7 @@ int sd_notify(int unset_environment, const char *state) _sd_hidden_; See sd_notifyf(3) for more information. */ -int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3) _sd_hidden_; +int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); /* Returns > 0 if the system was booted with systemd. Returns < 0 on @@ -244,11 +269,11 @@ int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_( fine. You should NOT protect them with a call to this function. Also note that this function checks whether the system, not the user session is controlled by systemd. However the functions above work - for both session and system services. + for both user and system services. See sd_booted(3) for more information. */ -int sd_booted(void) _sd_hidden_; +int sd_booted(void); #ifdef __cplusplus } |