hal/hald hald_dbus.c,1.10,1.11 hald_dbus.h,1.3,1.4

Joe Shaw joe at freedesktop.org
Fri Sep 17 10:05:50 PDT 2004


Update of /cvs/hal/hal/hald
In directory gabe:/tmp/cvs-serv18110/hald

Modified Files:
	hald_dbus.c hald_dbus.h 
Log Message:
2004-09-17  Joe Shaw  <joeshaw at novell.com>

	* doc/spec/hal-spec.xml.in: Add the Lock and Unlock methods to the
	spec.

	* hald/hald_dbus.c (raise_device_not_locked,
	raise_device_already_locked): New errors for the locking methods.
	(device_query_capability): Change the parsing to split up caps on
	spaces rather than doing a substring match.
	(device_lock): Implements the Lock dbus method, which grabs an
	advisory lock on a device.
	(device_unlock): Implements the Unlock dbus method.
	(service_deleted): Callback which releases locks when the locking
	service quits.
	(filter_function): Add a ServiceDeleted handler, check for Lock
	and Unlock methods.
	(hald_dbus_init): Add a match for the ServiceDeleted signal so we
	can see when things disconnect from the bus.

	* libhal/libhal.c (hal_device_lock): Added.  Takes an advisory
	lock for a device.
	(hal_device_unlock): Releases the lock.

Index: hald_dbus.c
===================================================================
RCS file: /cvs/hal/hal/hald/hald_dbus.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- hald_dbus.c	15 Sep 2004 09:16:56 -0000	1.10
+++ hald_dbus.c	17 Sep 2004 17:05:48 -0000	1.11
@@ -186,6 +186,89 @@
 	dbus_message_unref (reply);
 }
 
+/** Raise the org.freedesktop.Hal.DeviceNotLocked error
+ *
+ *  @param  connection          D-Bus connection
+ *  @param  in_reply_to         message to report error on
+ *  @param  device              device which isn't locked
+ */
+static void
+raise_device_not_locked (DBusConnection *connection,
+			 DBusMessage    *in_reply_to,
+			 HalDevice      *device)
+{
+	char buf[512];
+	DBusMessage *reply;
+
+	snprintf (buf, 511, "The device %s is not locked",
+		  hal_device_get_udi (device));
+	HAL_WARNING ((buf));
+	reply = dbus_message_new_error (in_reply_to,
+					"org.freedesktop.Hal.DeviceNotLocked",
+					buf);
+
+	if (reply == NULL || !dbus_connection_send (connection, reply, NULL))
+		DIE (("No memory"));
+
+	dbus_message_unref (reply);
+}
+
+/** Raise the org.freedesktop.Hal.DeviceAlreadyLocked error
+ *
+ *  @param  connection          D-Bus connection
+ *  @param  in_reply_to         message to report error on
+ *  @param  device              device which isn't locked
+ */
+static void
+raise_device_already_locked (DBusConnection *connection,
+			     DBusMessage    *in_reply_to,
+			     HalDevice      *device)
+{
+	DBusMessage *reply;
+	const char *reason;
+
+	reason = hal_device_property_get_string (device, "info.locked.reason");
+	HAL_WARNING (("Device %s is already locked: %s",
+		      hal_device_get_udi (device), reason));
+
+
+	reply = dbus_message_new_error (in_reply_to,
+					"org.freedesktop.Hal.DeviceAlreadyLocked",
+					
+					reason);
+
+	if (reply == NULL || !dbus_connection_send (connection, reply, NULL))
+		DIE (("No memory"));
+
+	dbus_message_unref (reply);
+}
+
+/** Raise the org.freedesktop.Hal.PermissionDenied error
+ *
+ *  @param  connection          D-Bus connection
+ *  @param  in_reply_to         message to report error on
+ *  @param  message             what you're not allowed to do
+ */
+static void
+raise_permission_denied (DBusConnection *connection,
+			 DBusMessage    *in_reply_to,
+			 const char     *reason)
+{
+	char buf[512];
+	DBusMessage *reply;
+
+	snprintf (buf, 511, "Permission denied: %s", reason);
+	HAL_WARNING ((buf));
+	reply = dbus_message_new_error (in_reply_to,
+					"org.freedesktop.Hal.PermissionDenied",
+					buf);
+
+	if (reply == NULL || !dbus_connection_send (connection, reply, NULL))
+		DIE (("No memory"));
+
+	dbus_message_unref (reply);
+}
+
 /** @} */
 
 /**
@@ -1176,7 +1259,7 @@
 }
 
 
-/** Determine if a device got a capability
+/** Determine if a device has a capability
  *
  *  <pre>
  *  bool Device.QueryCapability(string capability_name)
@@ -1229,10 +1312,21 @@
 	rc = FALSE;
 	caps = hal_device_property_get_string (d, "info.capabilities");
 	if (caps != NULL) {
-		if (strstr (caps, capability) != NULL)
-			rc = TRUE;
+		char **capsv, **iter;
+
+		capsv = g_strsplit (caps, " ", 0);
+		for (iter = capsv; iter != NULL; iter++) {
+			if (strcmp (*iter, capability) == 0) {
+				rc = TRUE;
+				break;
+			}
+		}
+
+		g_strfreev (capsv);
 	}
 
+	dbus_free (capability);
+
 	dbus_message_iter_init (reply, &iter);
 	dbus_message_iter_append_boolean (&iter, rc);
 
@@ -1243,6 +1337,184 @@
 	return DBUS_HANDLER_RESULT_HANDLED;
 }
 
+static GHashTable *services_with_locks = NULL;
+
+/** Grab an advisory lock on a device.
+ *
+ *  <pre>
+ *  bool Device.Lock(string reason)
+ *
+ *    raises org.freedesktop.Hal.NoSuchDevice, 
+ *           org.freedesktop.Hal.DeviceAlreadyLocked
+ *  </pre>
+ *
+ *  @param  connection          D-BUS connection
+ *  @param  message             Message
+ *  @return                     What to do with the message
+ */
+DBusHandlerResult
+device_lock (DBusConnection * connection,
+	     DBusMessage * message)
+{
+	const char *udi;
+	HalDevice *d;
+	DBusMessage *reply;
+	dbus_bool_t already_locked;
+	DBusError error;
+	char *reason;
+	const char *sender;
+
+	HAL_TRACE (("entering"));
+
+	udi = dbus_message_get_path (message);
+
+	d = hal_device_store_find (hald_get_gdl (), udi);
+	if (d == NULL)
+		d = hal_device_store_find (hald_get_tdl (), udi);
+
+	if (d == NULL) {
+		raise_no_such_device (connection, message, udi);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	already_locked = hal_device_property_get_bool (d, "info.locked");
+
+	if (already_locked) {
+		raise_device_already_locked (connection, message, d);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	dbus_error_init (&error);
+	if (!dbus_message_get_args (message, &error,
+				    DBUS_TYPE_STRING, &reason,
+				    DBUS_TYPE_INVALID)) {
+		raise_syntax (connection, message, "Lock");
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	reply = dbus_message_new_method_return (message);
+	if (reply == NULL)
+		DIE (("No memory"));
+
+	sender = dbus_message_get_sender (message);
+
+	hal_device_property_set_bool (d, "info.locked", TRUE);
+	hal_device_property_set_string (d, "info.locked.reason", reason);
+	hal_device_property_set_string (d, "info.locked.dbus_service",
+					sender);
+
+	if (services_with_locks == NULL) {
+		services_with_locks =
+			g_hash_table_new_full (g_str_hash,
+					       g_str_equal,
+					       g_free,
+					       g_object_unref);
+	}
+
+	g_hash_table_insert (services_with_locks, g_strdup (sender),
+			     g_object_ref (d));
+
+	dbus_free (reason);
+
+	if (!dbus_connection_send (connection, reply, NULL))
+		DIE (("No memory"));
+
+	dbus_message_unref (reply);
+	return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/** Release an advisory lock on a device.
+ *
+ *  <pre>
+ *  bool Device.Unlock()
+ *
+ *    raises org.freedesktop.Hal.NoSuchDevice, 
+ *           org.freedesktop.Hal.DeviceNotLocked,
+ *           org.freedesktop.Hal.PermissionDenied
+ *  </pre>
+ *
+ *  @param  connection          D-BUS connection
+ *  @param  message             Message
+ *  @return                     What to do with the message
+ */
+DBusHandlerResult
+device_unlock (DBusConnection * connection,
+	       DBusMessage * message)
+{
+	dbus_bool_t rc;
+	const char *udi;
+	HalDevice *d;
+	DBusMessage *reply;
+	DBusError error;
+	const char *sender;
+
+	HAL_TRACE (("entering"));
+
+	udi = dbus_message_get_path (message);
+
+	d = hal_device_store_find (hald_get_gdl (), udi);
+	if (d == NULL)
+		d = hal_device_store_find (hald_get_tdl (), udi);
+
+	if (d == NULL) {
+		raise_no_such_device (connection, message, udi);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	dbus_error_init (&error);
+	if (!dbus_message_get_args (message, &error,
+				    DBUS_TYPE_INVALID)) {
+		raise_syntax (connection, message, "Unlock");
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	reply = dbus_message_new_method_return (message);
+	if (reply == NULL)
+		DIE (("No memory"));
+
+	rc = hal_device_property_get_bool (d, "info.locked");
+
+	if (!rc) {
+		raise_device_not_locked (connection, message, d);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	sender = dbus_message_get_sender (message);
+
+	if (strcmp (sender, hal_device_property_get_string (
+			    d, "info.locked.dbus_service")) != 0) {
+		char *reason;
+
+		reason = g_strdup_printf ("Service '%s' does not own the "
+					  "lock on %s", sender,
+					  hal_device_get_udi (d));
+
+		raise_permission_denied (connection, message, reason);
+
+		g_free (reason);
+
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+	if (g_hash_table_lookup (services_with_locks, sender))
+		g_hash_table_remove (services_with_locks, sender);
+	else {
+		HAL_WARNING (("Service '%s' was not in the list of services "
+			      "with locks!", sender));
+	}
+
+	hal_device_property_remove (d, "info.locked");
+	hal_device_property_remove (d, "info.locked.reason");
+	hal_device_property_remove (d, "info.locked.dbus_service");
+
+	/* FIXME?  Pointless? */
+	if (!dbus_connection_send (connection, reply, NULL))
+		DIE (("No memory"));
+
+	dbus_message_unref (reply);
+	return DBUS_HANDLER_RESULT_HANDLED;
+}
+
 /** Counter for atomic updating */
 static int atomic_count = 0;
 
@@ -1795,6 +2067,32 @@
 		return TRUE;
 }
 
+static void
+service_deleted (DBusMessage *message)
+{
+	char *service_name;
+	HalDevice *d;
+
+	if (!dbus_message_get_args (message, NULL,
+				    DBUS_TYPE_STRING, &service_name,
+				    DBUS_TYPE_INVALID)) {
+		HAL_ERROR (("Invalid ServiceDeleted signal from bus!"));
+		return;
+	}
+
+	d = g_hash_table_lookup (services_with_locks, service_name);
+
+	if (d != NULL) {
+		hal_device_property_remove (d, "info.locked");
+		hal_device_property_remove (d, "info.locked.reason");
+		hal_device_property_remove (d, "info.locked.dbus_service");
+
+		g_hash_table_remove (services_with_locks, service_name);
+	}
+
+	dbus_free (service_name);
+}
+
 /** Message handler for method invocations. All invocations on any object
  *  or interface is routed through this function.
  *
@@ -1807,20 +2105,28 @@
 filter_function (DBusConnection * connection,
 		 DBusMessage * message, void *user_data)
 {
-/*
+
     HAL_INFO (("obj_path=%s interface=%s method=%s", 
     dbus_message_get_path(message), 
     dbus_message_get_interface(message),
     dbus_message_get_member(message)));
-*/
+
 
 	if (dbus_message_is_signal (message,
 				    DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
 				    "Disconnected") &&
 	    strcmp (dbus_message_get_path (message),
 		    DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0) {
+
 		dbus_connection_unref (dbus_connection);
 		g_timeout_add (3000, reinit_dbus, NULL);
+
+	} else if (dbus_message_is_signal (message,
+					   DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+					   "ServiceDeleted")) {
+
+		if (services_with_locks != NULL)
+			service_deleted (message);
 	} else if (dbus_message_is_method_call (message,
 					 "org.freedesktop.Hal.Manager",
 					 "GetAllDevices") &&
@@ -1947,6 +2253,14 @@
 						"org.freedesktop.Hal.Device",
 						"QueryCapability")) {
 		return device_query_capability (connection, message);
+	} else if (dbus_message_is_method_call (message,
+						"org.freedesktop.Hal.Device",
+						"Lock")) {
+		return device_lock (connection, message);
+	} else if (dbus_message_is_method_call (message,
+						"org.freedesktop.Hal.Device",
+						"Unlock")) {
+		return device_unlock (connection, message);
 	} else
 		osspec_filter_function (connection, message, user_data);
 
@@ -1981,6 +2295,13 @@
 	dbus_connection_add_filter (dbus_connection, filter_function, NULL,
 				    NULL);
 
+	dbus_bus_add_match (dbus_connection,
+			    "type='signal',"
+			    "interface='"DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS"',"
+			    "sender='"DBUS_SERVICE_ORG_FREEDESKTOP_DBUS"',"
+			    "member='ServiceDeleted'",
+			    NULL);
+
 	return TRUE;
 }
 

Index: hald_dbus.h
===================================================================
RCS file: /cvs/hal/hal/hald/hald_dbus.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- hald_dbus.h	30 Jul 2004 17:00:42 -0000	1.3
+++ hald_dbus.h	17 Sep 2004 17:05:48 -0000	1.4
@@ -56,6 +56,10 @@
 						     DBusMessage    *msg);
 DBusHandlerResult device_query_capability           (DBusConnection *conn,
 						     DBusMessage    *msg);
+DBusHandlerResult device_lock                       (DBusConnection *conn,
+						     DBusMessage    *msg);
+DBusHandlerResult device_unlock                     (DBusConnection *conn,
+						     DBusMessage    *msg);
 DBusHandlerResult agent_manager_new_device          (DBusConnection *conn,
 						     DBusMessage    *msg);
 DBusHandlerResult agent_manager_commit_to_gdl       (DBusConnection *conn,




More information about the hal-commit mailing list