D-Bus: Make wpas_dbus_error_scan_error() static
[mech_eap.git] / wpa_supplicant / dbus / dbus_new_helpers.c
index 7f15f86..8df7ac1 100644 (file)
@@ -3,14 +3,8 @@
  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
  * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "utils/includes.h"
@@ -38,33 +32,31 @@ static dbus_bool_t fill_dict_with_properties(
                               WPAS_DBUS_INTERFACE_MAX) != 0)
                        continue;
 
-               /* Handle access permissions or missing getter */
-               if (dsc->getter == NULL || dsc->access == W)
+               /* Skip write-only properties */
+               if (dsc->getter == NULL)
                        continue;
 
                if (!dbus_message_iter_open_container(dict_iter,
                                                      DBUS_TYPE_DICT_ENTRY,
-                                                     NULL, &entry_iter)) {
-                       dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
-                                            "no memory");
-                       return FALSE;
-               }
-               if (!dbus_message_iter_append_basic(&entry_iter,
+                                                     NULL, &entry_iter) ||
+                   !dbus_message_iter_append_basic(&entry_iter,
                                                    DBUS_TYPE_STRING,
-                                                   &dsc->dbus_property)) {
-                       dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
-                                            "no memory");
-                       return FALSE;
-               }
+                                                   &dsc->dbus_property))
+                       goto error;
 
                /* An error getting a property fails the request entirely */
                if (!dsc->getter(&entry_iter, error, user_data))
                        return FALSE;
 
-               dbus_message_iter_close_container(dict_iter, &entry_iter);
+               if (!dbus_message_iter_close_container(dict_iter, &entry_iter))
+                       goto error;
        }
 
        return TRUE;
+
+error:
+       dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+       return FALSE;
 }
 
 
@@ -117,7 +109,12 @@ static DBusMessage * get_all_properties(DBusMessage *message, char *interface,
                return reply;
        }
 
-       wpa_dbus_dict_close_write(&iter, &dict_iter);
+       if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
+               dbus_message_unref(reply);
+               return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+                                             "out of memory");
+       }
+
        return reply;
 }
 
@@ -139,7 +136,7 @@ static int is_signature_correct(DBusMessage *message,
                if (arg->dir == ARG_IN) {
                        size_t blen = registered_sig + MAX_SIG_LEN - pos;
                        ret = os_snprintf(pos, blen, "%s", arg->type);
-                       if (ret < 0 || (size_t) ret >= blen)
+                       if (os_snprintf_error(blen, ret))
                                return 0;
                        pos += ret;
                }
@@ -173,7 +170,7 @@ static DBusMessage * properties_get(DBusMessage *message,
                                              NULL);
        }
 
-       if (dsc->access == W || dsc->getter == NULL) {
+       if (dsc->getter == NULL) {
                return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                              "Property is write-only");
        }
@@ -207,7 +204,7 @@ static DBusMessage * properties_set(DBusMessage *message,
                                              NULL);
        }
 
-       if (dsc->access == R || dsc->setter == NULL) {
+       if (dsc->setter == NULL) {
                return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                              "Property is read-only");
        }
@@ -596,11 +593,11 @@ int wpa_dbus_unregister_object_per_iface(
        if (!obj_desc) {
                wpa_printf(MSG_ERROR, "dbus: %s: Could not obtain object's "
                           "private data: %s", __func__, path);
-       } else {
-               eloop_cancel_timeout(flush_object_timeout_handler, con,
-                                    obj_desc);
+               return 0;
        }
 
+       eloop_cancel_timeout(flush_object_timeout_handler, con, obj_desc);
+
        if (!dbus_connection_unregister_object_path(con, path))
                return -1;
 
@@ -610,7 +607,7 @@ int wpa_dbus_unregister_object_per_iface(
 
 static dbus_bool_t put_changed_properties(
        const struct wpa_dbus_object_desc *obj_dsc, const char *interface,
-       DBusMessageIter *dict_iter)
+       DBusMessageIter *dict_iter, int clear_changed)
 {
        DBusMessageIter entry_iter;
        const struct wpa_dbus_property_desc *dsc;
@@ -624,7 +621,8 @@ static dbus_bool_t put_changed_properties(
                        continue;
                if (os_strcmp(dsc->dbus_interface, interface) != 0)
                        continue;
-               obj_dsc->prop_changed_flags[i] = 0;
+               if (clear_changed)
+                       obj_dsc->prop_changed_flags[i] = 0;
 
                if (!dbus_message_iter_open_container(dict_iter,
                                                      DBUS_TYPE_DICT_ENTRY,
@@ -660,7 +658,57 @@ static dbus_bool_t put_changed_properties(
 }
 
 
-static void send_prop_changed_signal(
+static void do_send_prop_changed_signal(
+       DBusConnection *con, const char *path, const char *interface,
+       const struct wpa_dbus_object_desc *obj_dsc)
+{
+       DBusMessage *msg;
+       DBusMessageIter signal_iter, dict_iter;
+
+       msg = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
+                                     "PropertiesChanged");
+       if (msg == NULL)
+               return;
+
+       dbus_message_iter_init_append(msg, &signal_iter);
+
+       if (!dbus_message_iter_append_basic(&signal_iter, DBUS_TYPE_STRING,
+                                           &interface))
+               goto err;
+
+       /* Changed properties dict */
+       if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
+                                             "{sv}", &dict_iter))
+               goto err;
+
+       if (!put_changed_properties(obj_dsc, interface, &dict_iter, 0))
+               goto err;
+
+       if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
+               goto err;
+
+       /* Invalidated properties array (empty) */
+       if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
+                                             "s", &dict_iter))
+               goto err;
+
+       if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
+               goto err;
+
+       dbus_connection_send(con, msg, NULL);
+
+out:
+       dbus_message_unref(msg);
+       return;
+
+err:
+       wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal",
+                  __func__);
+       goto out;
+}
+
+
+static void do_send_deprecated_prop_changed_signal(
        DBusConnection *con, const char *path, const char *interface,
        const struct wpa_dbus_object_desc *obj_dsc)
 {
@@ -677,7 +725,7 @@ static void send_prop_changed_signal(
                                              "{sv}", &dict_iter))
                goto err;
 
-       if (!put_changed_properties(obj_dsc, interface, &dict_iter))
+       if (!put_changed_properties(obj_dsc, interface, &dict_iter, 1))
                goto err;
 
        if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
@@ -696,6 +744,29 @@ err:
 }
 
 
+static void send_prop_changed_signal(
+       DBusConnection *con, const char *path, const char *interface,
+       const struct wpa_dbus_object_desc *obj_dsc)
+{
+       /*
+        * First, send property change notification on the standardized
+        * org.freedesktop.DBus.Properties interface. This call will not
+        * clear the property change bits, so that they are preserved for
+        * the call that follows.
+        */
+       do_send_prop_changed_signal(con, path, interface, obj_dsc);
+
+       /*
+        * Now send PropertiesChanged on our own interface for backwards
+        * compatibility. This is deprecated and will be removed in a future
+        * release.
+        */
+       do_send_deprecated_prop_changed_signal(con, path, interface, obj_dsc);
+
+       /* Property change bits have now been cleared. */
+}
+
+
 static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx)
 {
        DBusConnection *con = eloop_ctx;
@@ -772,7 +843,6 @@ void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
                return;
        eloop_cancel_timeout(flush_object_timeout_handler, con, obj_desc);
 
-       dsc = obj_desc->properties;
        for (dsc = obj_desc->properties, i = 0; dsc && dsc->dbus_property;
             dsc++, i++) {
                if (obj_desc->prop_changed_flags == NULL ||