diff options
-rw-r--r-- | HACKING | 8 | ||||
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | doc/man/Makefile.am | 2 | ||||
-rw-r--r-- | doc/man/hal-find-by-capability.1.in | 2 | ||||
-rw-r--r-- | doc/man/hal-find-by-property.1.in | 2 | ||||
-rw-r--r-- | doc/man/hal-get-property.1.in | 2 | ||||
-rw-r--r-- | doc/man/hal-is-caller-locked-out.1.in | 2 | ||||
-rw-r--r-- | doc/man/hal-lock.1.in | 7 | ||||
-rw-r--r-- | doc/man/hal-set-property.1.in | 2 | ||||
-rw-r--r-- | doc/spec/hal-spec-interfaces.xml | 64 | ||||
-rw-r--r-- | doc/spec/hal-spec-locking.xml | 27 | ||||
-rwxr-xr-x | examples/interface-locking-test.py | 10 | ||||
-rw-r--r-- | hald/access-check.c | 122 | ||||
-rw-r--r-- | hald/access-check.h | 5 | ||||
-rw-r--r-- | hald/ci-tracker.c | 26 | ||||
-rw-r--r-- | hald/ci-tracker.h | 1 | ||||
-rw-r--r-- | hald/device.c | 77 | ||||
-rw-r--r-- | hald/device.h | 10 | ||||
-rw-r--r-- | hald/device_store.c | 63 | ||||
-rw-r--r-- | hald/device_store.h | 10 | ||||
-rw-r--r-- | hald/hald.c | 35 | ||||
-rw-r--r-- | hald/hald_dbus.c | 305 | ||||
-rw-r--r-- | hald/hald_dbus.h | 6 | ||||
-rw-r--r-- | hald/hald_marshal.list | 2 | ||||
-rw-r--r-- | libhal/libhal.c | 281 | ||||
-rw-r--r-- | libhal/libhal.h | 79 | ||||
-rw-r--r-- | tools/hal-lock.c | 116 | ||||
-rw-r--r-- | tools/lshal.c | 75 |
28 files changed, 1272 insertions, 70 deletions
@@ -131,3 +131,11 @@ Coding Style heuristically parse a file and accept not-well-formed data). Avoiding heuristics is also important for security reasons; if it looks funny, ignore it (or exit, or disconnect). + +Configuring the sources +=== + +To configure the HAL sources for a generic Linux desktop distribution +using Linux 2.6.20, one should use + +--enable-console-kit --enable-acl-management --enable-docbook-docs --enable-acpi-ibm --enable-acpi-toshiba diff --git a/configure.in b/configure.in index 8e14728f..349102a3 100644 --- a/configure.in +++ b/configure.in @@ -140,6 +140,7 @@ AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug AC_ARG_ENABLE(docbook-docs, [ --enable-docbook-docs build documentation (requires xmlto)],enable_docbook_docs=$enableval,enable_docbook_docs=no) AC_ARG_ENABLE(man-pages, [ --enable-man-pages build manual pages],enable_man_pages=$enableval,enable_man_pages=yes) AM_CONDITIONAL(MAN_PAGES_ENABLED, test x$enable_man_pages = xyes) +AC_SUBST(MAN_PAGES_ENABLED) ## eject AC_ARG_WITH(eject, [ --with-eject=<path> Specify eject program. (default /usr/bin/eject)]) diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 295c6948..4f22641c 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -10,4 +10,4 @@ endif # MAN_PAGES_ENABLED EXTRA_DIST=$(man_MANS) $(MAN_IN_FILES) clean-local: - rm -f *~ + rm -f *~ *.1 diff --git a/doc/man/hal-find-by-capability.1.in b/doc/man/hal-find-by-capability.1.in index 5d7e1550..5c593ca3 100644 --- a/doc/man/hal-find-by-capability.1.in +++ b/doc/man/hal-find-by-capability.1.in @@ -19,7 +19,7 @@ device database by looking at device capabilities. For more information about both the big picture and specific .B HAL properties, refer to the \fIHAL spec\fP which can be found in -.I "/usr/share/doc/hal-0.5.9/spec/hal-spec.html" +.I "/usr/share/doc/hal-@VERSION@/spec/hal-spec.html" depending on the distribution. .SH OPTIONS diff --git a/doc/man/hal-find-by-property.1.in b/doc/man/hal-find-by-property.1.in index 0dd29c3c..73bc99b2 100644 --- a/doc/man/hal-find-by-property.1.in +++ b/doc/man/hal-find-by-property.1.in @@ -19,7 +19,7 @@ device database by looking at device properties. For more information about both the big picture and specific .B HAL properties, refer to the \fIHAL spec\fP which can be found in -.I "/usr/share/doc/hal-0.5.9/spec/hal-spec.html" +.I "/usr/share/doc/hal-@VERSION@/spec/hal-spec.html" depending on the distribution. .SH OPTIONS diff --git a/doc/man/hal-get-property.1.in b/doc/man/hal-get-property.1.in index d61e4594..87ab9d99 100644 --- a/doc/man/hal-get-property.1.in +++ b/doc/man/hal-get-property.1.in @@ -19,7 +19,7 @@ device database. For more information about both the big picture and specific .B HAL properties, refer to the \fIHAL spec\fP which can be found in -.I "/usr/share/doc/hal-0.5.9/spec/hal-spec.html" +.I "/usr/share/doc/hal-@VERSION@/spec/hal-spec.html" depending on the distribution. .SH OPTIONS diff --git a/doc/man/hal-is-caller-locked-out.1.in b/doc/man/hal-is-caller-locked-out.1.in index 3df1c1d5..d5de39a1 100644 --- a/doc/man/hal-is-caller-locked-out.1.in +++ b/doc/man/hal-is-caller-locked-out.1.in @@ -17,7 +17,7 @@ locked out of a specific D-Bus interface on a specific device. For more information about both the big picture and specific .B HAL properties, refer to the \fIHAL spec\fP which can be found in -.I "/usr/share/doc/hal-0.5.9/spec/hal-spec.html" +.I "/usr/share/doc/hal-@VERSION@/spec/hal-spec.html" depending on the distribution. .SH OPTIONS diff --git a/doc/man/hal-lock.1.in b/doc/man/hal-lock.1.in index abd6af37..a5c54924 100644 --- a/doc/man/hal-lock.1.in +++ b/doc/man/hal-lock.1.in @@ -17,7 +17,7 @@ either on a given device or globally. For more information about both the big picture and the semantics of .B HAL locks, refer to the \fIHAL spec\fP which can be found in -.I "/usr/share/doc/hal-0.5.9/spec/hal-spec.html" +.I "/usr/share/doc/hal-@VERSION@/spec/hal-spec.html" depending on the distribution. .SH OPTIONS @@ -36,6 +36,11 @@ is ommitted, the global lock will be tried. .I "--exclusive" Whether the lock can be held by others. .TP +.I "--exit-with-lock" +Kill the program if the acquired lock is lost. This only makes sense if you pass a specific +.I UDI +due to the semantics of HAL locks. +.TP .I "--help" Print out usage. .TP diff --git a/doc/man/hal-set-property.1.in b/doc/man/hal-set-property.1.in index 2c4294c3..d62bfcda 100644 --- a/doc/man/hal-set-property.1.in +++ b/doc/man/hal-set-property.1.in @@ -19,7 +19,7 @@ device database. For more information about both the big picture and specific .B HAL properties, refer to the \fIHAL spec\fP which can be found in -.I "/usr/share/doc/hal-0.5.9/spec/hal-spec.html" +.I "/usr/share/doc/hal-@VERSION@/spec/hal-spec.html" depending on the distribution. .SH OPTIONS diff --git a/doc/spec/hal-spec-interfaces.xml b/doc/spec/hal-spec-interfaces.xml index 9858c717..1ad525b0 100644 --- a/doc/spec/hal-spec-interfaces.xml +++ b/doc/spec/hal-spec-interfaces.xml @@ -112,6 +112,28 @@ $ dbus-send --system --print-reply --dest=org.freedesktop.Hal \ the global device list (GDL). Caller must be uid 0. </entry> </row> + + <row> + <entry>AcquireGlobalInterfaceLock</entry> + <entry></entry> + <entry>String interface_name, Bool exclusive</entry> + <entry>Device.InterfaceAlreadyLocked</entry> + <entry> + Acquires a global lock on an interface. See + <xref linkend="locking"/> for details. + </entry> + </row> + <row> + <entry>ReleaseGlobalInterfaceLock</entry> + <entry></entry> + <entry>String interface_name</entry> + <entry>Device.InterfaceNotLocked</entry> + <entry> + Releases a global lock on an interface. See + <xref linkend="locking"/> for details. + </entry> + </row> + </tbody> </tgroup> </informaltable> @@ -151,6 +173,20 @@ $ dbus-send --system --print-reply --dest=org.freedesktop.Hal \ A device gained a new capability. </entry> </row> + <row> + <entry>GlobalInterfaceLockAcquired</entry> + <entry>String lock_name, String lock_owner, Int num_holders</entry> + <entry> + Sent when a process acquires a global interface lock. + </entry> + </row> + <row> + <entry>GlobalInterfaceLockReleased</entry> + <entry>String lock_name, String lock_owner, Int num_holders</entry> + <entry> + Sent when a process releases a global interface lock. + </entry> + </row> </tbody> </tgroup> </informaltable> @@ -377,7 +413,6 @@ $ dbus-send --system --print-reply --dest=org.freedesktop.Hal \ Releases an advisory lock on the device. Returns TRUE if the lock was released. </entry> </row> - <row> <entry>AcquireInterfaceLock</entry> <entry></entry> @@ -388,7 +423,6 @@ $ dbus-send --system --print-reply --dest=org.freedesktop.Hal \ device. See <xref linkend="locking"/> for details. </entry> </row> - <row> <entry>ReleaseInterfaceLock</entry> <entry></entry> @@ -399,7 +433,6 @@ $ dbus-send --system --print-reply --dest=org.freedesktop.Hal \ <xref linkend="locking"/> for details. </entry> </row> - <row> <entry>IsCallerLockedOut</entry> <entry>Bool</entry> @@ -412,6 +445,17 @@ $ dbus-send --system --print-reply --dest=org.freedesktop.Hal \ method. See <xref linkend="locking"/> for details. </entry> </row> + <row> + <entry>IsLockedByOthers</entry> + <entry>Bool</entry> + <entry>String interface_name</entry> + <entry></entry> + <entry> + Determines whether a determines other processes than the + caller holds a lock on the given device. See + <xref linkend="locking"/> for details. + </entry> + </row> <row> <entry>StringListAppend</entry> @@ -539,6 +583,20 @@ $ dbus-send --system --print-reply --dest=org.freedesktop.Hal \ dedicated interface.). </entry> </row> + <row> + <entry>InterfaceLockAcquired</entry> + <entry>String lock_name, String lock_owner, Int num_holders</entry> + <entry> + Sent when a process acquires an interface lock on the device. + </entry> + </row> + <row> + <entry>InterfaceLockReleased</entry> + <entry>String lock_name, String lock_owner, Int num_holders</entry> + <entry> + Sent when a process releases an interface lock on the device. + </entry> + </row> </tbody> </tgroup> </informaltable> diff --git a/doc/spec/hal-spec-locking.xml b/doc/spec/hal-spec-locking.xml index df62f0ae..7306dbb5 100644 --- a/doc/spec/hal-spec-locking.xml +++ b/doc/spec/hal-spec-locking.xml @@ -52,11 +52,28 @@ interface on the given device. The locker can specify whether the lock is <emphasis>exclusive</emphasis> meaning if multiple clients clients can hold the lock or if only one client can hold - the lock at one time. If a client don't have access to a device, - attempts to lock will fail with + the lock at one time. If a client don't have access to the + interface of the device, attempts to lock will fail with a <literal>org.freedesktop.Hal.PermissionDenied</literal> - exception. If another client already holds the lock exclusively, - attempts from other clients to acquire the lock will fail with + exception. If a client loses access to a device (say, if his + session is switched away from using fast user switching) while + holding a lock, he will lose the lock; this can be tracked by + listening to the <literal>InterfaceLockReleased</literal> + signal. + </para> + + <para> + All local clients, whether they are active or not, can always + lock interfaces on the root computer device object (this doesn't + mean that they are privileged to use the interfaces though) - + the rationale is that this device object represents shared + infrastructure, e.g. power management, and even inactive + sessions needs to participate in managing this. + </para> + + <para> + If another client already holds a lock exclusively, attempts + from other clients to acquire the lock will fail with the <literal>org.freedesktop.Hal.Device.InterfaceAlreadyLocked</literal> exception even if they have access to the device. </para> @@ -218,7 +235,7 @@ <listitem> <para> - ... MUST check that no other process is holding the lock + ... MUST check that no other process is holding the lock (using the <literal>IsLockedByOthers</literal> method on the standard <literal>org.freedesktop.Hal.Device</literal> interface) before calling into the <literal>org.freedesktop.Hal.Device.SystemPowerManagement</literal> interface. If another process is holding the lock, it diff --git a/examples/interface-locking-test.py b/examples/interface-locking-test.py index ca60a910..51552b4c 100755 --- a/examples/interface-locking-test.py +++ b/examples/interface-locking-test.py @@ -22,11 +22,15 @@ device_volume = dbus.Interface(bus.get_object("org.freedesktop.Hal", "org.freedesktop.Hal.Device.Volume") #manager.AcquireGlobalInterfaceLock("org.freedesktop.Hal.Device.Storage", True) -#time.sleep(2) +#time.sleep(10) #manager.ReleaseGlobalInterfaceLock("org.freedesktop.Hal.Device.Storage") device.AcquireInterfaceLock("org.freedesktop.Hal.Device.Volume", False) -device_volume.Mount("", "", []) -time.sleep(2) +#device_volume.Mount("", "", []) +if device.IsLockedByOthers("org.freedesktop.Hal.Device.Volume"): + print "device is locked by another process too!" +else: + print "we are the only process locking the device" +time.sleep(10) device.ReleaseInterfaceLock("org.freedesktop.Hal.Device.Volume") diff --git a/hald/access-check.c b/hald/access-check.c index 6f0542b6..ab68ce4f 100644 --- a/hald/access-check.c +++ b/hald/access-check.c @@ -110,17 +110,30 @@ out: * access_check_caller_have_access_to_device: * @cit: the CITracker object * @device: The device to check for - * @caller_unique_sysbus_name: The unique system bus connection name (e.g. ":1.43") of the caller + * @privilege: the type of access; right now this can be #NULL or + * "lock"; will be replaced by PolicyKit privileges in the future + * @caller_unique_sysbus_name: The unique system bus connection + * name (e.g. ":1.43") of the caller * * Determine if a given caller should have access to a device. This * depends on how the security is set up and may change according to * how the system is configured. * - * If ConsoleKit is used this function currently will return TRUE if, - * and only if, the caller is in an active session. TODO: once - * multi-seat is properly supported it will also depend on what seat - * the device belongs to and what seat the caller's session belongs - * to. + * If the privilege parameter is #NULL, it means "check if the caller + * can access D-Bus interfaces". If it is "lock" it means "check if + * the caller can lock an interface on the device". + * + * If ConsoleKit is used this function currently will return TRUE when + * privilege is #NULL if, and only if, the caller is in an active + * local session. If privilege is "lock" the only difference is that + * the it will always return TRUE for the root computer device + * object. This is used to ensure that any caller can always lock the + * SystemPowerManagement interface cf. the "Locking Guidelines" + * section of the HAL spec. + * + * (TODO: once PolicyKit and multi-seat is properly supported, this + * result from this function will also depend on what seat the device + * belongs to and what seat the caller's session belongs to.) * * If ConsoleKit is not used, this function will just return TRUE; the * OS vendor is supposed to have locked down access to HAL through OS @@ -132,7 +145,7 @@ out: * Returns: TRUE iff the caller have access to the device. */ gboolean -access_check_caller_have_access_to_device (CITracker *cit, HalDevice *device, const char *caller_unique_sysbus_name) +access_check_caller_have_access_to_device (CITracker *cit, HalDevice *device, const char *privilege, const char *caller_unique_sysbus_name) #ifdef HAVE_CONKIT { gboolean ret; @@ -152,19 +165,30 @@ access_check_caller_have_access_to_device (CITracker *cit, HalDevice *device, co goto out; } + /* must be tracked by ConsoleKit */ if (ci_tracker_caller_get_ck_session_path (ci) == NULL) { goto out; } + /* require caller to be local */ + if (!ci_tracker_caller_is_local (ci)) + goto out; - if (!ci_tracker_caller_in_active_session (ci)) { + /* allow inactive sessions to lock interfaces on root computer device object */ + if (privilege != NULL && + strcmp (privilege, "lock") == 0 && + strcmp (hal_device_get_udi (device), "/org/freedesktop/Hal/devices/computer") == 0) { + ret = TRUE; goto out; } - + + /* require caller to be in active session */ + if (!ci_tracker_caller_in_active_session (ci)) + goto out; + ret = TRUE; out: return ret; - } #else /* HAVE_CONKIT */ { @@ -254,7 +278,7 @@ access_check_caller_locked_out (CITracker *cit, for (n = 0; global_holders[n] != NULL; n++) { if (strcmp (global_holders[n], caller_unique_sysbus_name) == 0) { /* we are holding the global lock... */ - if (access_check_caller_have_access_to_device (cit, device, global_holders[n])) { + if (access_check_caller_have_access_to_device (cit, device, NULL, global_holders[n])) { /* only applies if the caller can access the device... */ is_locked_by_self = TRUE; /* this is good enough; we are holding the lock ourselves */ @@ -265,7 +289,7 @@ access_check_caller_locked_out (CITracker *cit, /* Someone else is holding the global lock.. check if that someone * actually have access to the device... */ - if (access_check_caller_have_access_to_device (cit, device, global_holders[n])) { + if (access_check_caller_have_access_to_device (cit, device, NULL, global_holders[n])) { /* They certainly do. Mark as locked. */ is_locked = TRUE; } @@ -293,3 +317,77 @@ out: return ret; } + + +/** + * access_check_locked_by_others: + * @cit: the CITracker object + * @device: The device to check for + * @caller_unique_sysbus_name: The unique system bus connection name (e.g. ":1.43") of the caller + * @interface_name: the interface to check for + * + * This method determines other processes than the caller holds a lock + * on the given device. + * + * Returns: TRUE iff other processes is holding a lock on the device + */ +gboolean +access_check_locked_by_others (CITracker *cit, + HalDevice *device, + const char *caller_unique_sysbus_name, + const char *interface_name) +{ + int n; + gboolean ret; + char *global_lock_name; + char **holders; + char **global_holders; + HalDevice *computer; + + global_lock_name = NULL; + holders = NULL; + global_holders = NULL; + ret = TRUE; + + computer = hal_device_store_find (hald_get_gdl (), "/org/freedesktop/Hal/devices/computer"); + if (computer == NULL) + computer = hal_device_store_find (hald_get_tdl (), "/org/freedesktop/Hal/devices/computer"); + if (computer == NULL) + goto out; + + global_lock_name = g_strdup_printf ("Global.%s", interface_name); + + holders = hal_device_get_lock_holders (device, interface_name); + global_holders = hal_device_get_lock_holders (computer, global_lock_name); + + if (holders != NULL) { + for (n = 0; holders[n] != NULL; n++) { + if (strcmp (holders[n], caller_unique_sysbus_name) != 0) { + /* someone else is holding the lock */ + goto out; + } + } + } + + if (global_holders != NULL) { + for (n = 0; global_holders[n] != NULL; n++) { + if (strcmp (global_holders[n], caller_unique_sysbus_name) != 0) { + /* someone else is holding the global lock... */ + if (access_check_caller_have_access_to_device (cit, device, NULL, global_holders[n])) { + /* ... and they can can access the device */ + goto out; + } + } + } + } + + /* done all the checks so noone else is locking... */ + ret = FALSE; + +out: + g_strfreev (global_holders); + g_strfreev (holders); + g_free (global_lock_name); + return ret; +} + diff --git a/hald/access-check.h b/hald/access-check.h index ab05f074..3da49ed4 100644 --- a/hald/access-check.h +++ b/hald/access-check.h @@ -35,10 +35,15 @@ gboolean access_check_message_caller_is_root_or_hal (CITracker *cit, DBusMessage *message); gboolean access_check_caller_have_access_to_device (CITracker *cit, HalDevice *device, + const char *privilege, const char *caller_unique_sysbus_name); gboolean access_check_caller_locked_out (CITracker *cit, HalDevice *device, const char *caller_unique_sysbus_name, const char *interface_name); +gboolean access_check_locked_by_others (CITracker *cit, + HalDevice *device, + const char *caller_unique_sysbus_name, + const char *interface_name); #endif /* ACCESS_CHECK_H */ diff --git a/hald/ci-tracker.c b/hald/ci-tracker.c index 6a8bd816..af836547 100644 --- a/hald/ci-tracker.c +++ b/hald/ci-tracker.c @@ -52,6 +52,7 @@ struct CICallerInfo_s { #ifdef HAVE_CONKIT pid_t pid; /* process ID of caller */ gboolean in_active_session; /* caller is in an active session */ + gboolean is_local; /* session is on a local seat */ char *session_objpath; /* obj path of ConsoleKit session */ #endif char *system_bus_unique_name; /* unique name of caller on the system bus */ @@ -261,6 +262,25 @@ ci_tracker_get_info (CITracker *cit, const char *system_bus_unique_name) dbus_message_iter_get_basic (&iter, &ci->in_active_session); dbus_message_unref (message); dbus_message_unref (reply); + + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + ci->session_objpath, + "org.freedesktop.ConsoleKit.Session", + "IsLocal"); + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (cit->dbus_connection, message, -1, &error); + if (reply == NULL || dbus_error_is_set (&error)) { + HAL_WARNING (("Error doing IsLocal on ConsoleKit: %s: %s", error.name, error.message)); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto error; + } + dbus_message_iter_init (reply, &iter); + dbus_message_iter_get_basic (&iter, &ci->is_local); + dbus_message_unref (message); + dbus_message_unref (reply); store_caller_info: #endif /* HAVE_CONKIT */ @@ -311,6 +331,12 @@ ci_tracker_caller_get_pid (CICallerInfo *ci) } gboolean +ci_tracker_caller_is_local (CICallerInfo *ci) +{ + return ci->is_local; +} + +gboolean ci_tracker_caller_in_active_session (CICallerInfo *ci) { return ci->in_active_session; diff --git a/hald/ci-tracker.h b/hald/ci-tracker.h index 7d762e98..5b0794a7 100644 --- a/hald/ci-tracker.h +++ b/hald/ci-tracker.h @@ -63,6 +63,7 @@ uid_t ci_tracker_caller_get_uid (CICallerInfo *ci); const char *ci_tracker_caller_get_sysbus_unique_name (CICallerInfo *ci); #ifdef HAVE_CONKIT pid_t ci_tracker_caller_get_pid (CICallerInfo *ci); +gboolean ci_tracker_caller_is_local (CICallerInfo *ci); gboolean ci_tracker_caller_in_active_session (CICallerInfo *ci); const char *ci_tracker_caller_get_ck_session_path (CICallerInfo *ci); #endif diff --git a/hald/device.c b/hald/device.c index f1f58477..e95cc19f 100644 --- a/hald/device.c +++ b/hald/device.c @@ -376,6 +376,8 @@ struct _HalDevicePrivate enum { PROPERTY_CHANGED, CAPABILITY_ADDED, + LOCK_ACQUIRED, + LOCK_RELEASED, LAST_SIGNAL }; @@ -441,6 +443,30 @@ hal_device_class_init (HalDeviceClass *klass) hald_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + + signals[LOCK_ACQUIRED] = + g_signal_new ("lock_acquired", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalDeviceClass, + lock_acquired), + NULL, NULL, + hald_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); + + signals[LOCK_RELEASED] = + g_signal_new ("lock_released", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalDeviceClass, + lock_released), + NULL, NULL, + hald_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); } static void @@ -1654,6 +1680,8 @@ hal_device_acquire_lock (HalDevice *device, const char *lock_name, gboolean excl add_to_locked_set (device); + g_signal_emit (device, signals[LOCK_ACQUIRED], 0, lock_name, sender); + ret = TRUE; out: return ret; @@ -1711,6 +1739,8 @@ hal_device_release_lock (HalDevice *device, const char *lock_name, const char *s hal_device_property_strlist_remove (device, buf, sender); } + g_signal_emit (device, signals[LOCK_RELEASED], 0, lock_name, sender); + ret = TRUE; out: @@ -1740,6 +1770,32 @@ hal_device_get_lock_holders (HalDevice *device, const char *lock_name) } /** + * hal_device_get_lock_holders: + * @device: the device to check for + * @lock_name: the lock name + * + * Get the number of lock holders on a device. + * + * Returns: Number of callers holding the given lock. + */ +int +hal_device_get_num_lock_holders (HalDevice *device, const char *lock_name) +{ + int num; + char **holders; + + num = 0; + holders = hal_device_get_lock_holders (device, lock_name); + if (holders == NULL) + goto out; + + num = g_strv_length (holders); + g_strfreev (holders); +out: + return num; +} + +/** * hal_device_client_disconnected: * @sender: the client that disconnected from the bus * @@ -1756,20 +1812,19 @@ hal_device_client_disconnected (const char *sender) for (i = locked_devices; i != NULL; i = g_slist_next (i)) { HalDevice *device = i->data; - GSList *locks; - GSList *j; - GSList *k; + char **locks; + int n; HAL_INFO (("Looking at udi '%s'", device->private->udi)); - locks = hal_device_property_get_strlist (device, "info.named_locks"); - for (j = locks; j != NULL; j = k) { - char *lock_name = j->data; - k = g_slist_next (j); - - HAL_INFO (("Lock '%s'", lock_name)); - - hal_device_release_lock (device, lock_name, sender); + locks = hal_device_property_dup_strlist_as_strv (device, "info.named_locks"); + if (locks != NULL) { + for (n = 0; locks[n] != NULL; n++) { + char *lock_name = locks[n]; + HAL_INFO (("Lock '%s'", lock_name)); + hal_device_release_lock (device, lock_name, sender); + } + g_strfreev (locks); } } } diff --git a/hald/device.h b/hald/device.h index 5dd11f57..1942e2f2 100644 --- a/hald/device.h +++ b/hald/device.h @@ -53,6 +53,14 @@ struct _HalDeviceClass { void (*capability_added) (HalDevice *device, const char *capability); + + void (*lock_acquired) (HalDevice *device, + const char *lock_name, + const char *lock_owner); + + void (*lock_released) (HalDevice *device, + const char *lock_name, + const char *lock_owner); }; #define HAL_TYPE_DEVICE (hal_device_get_type ()) @@ -212,6 +220,8 @@ gboolean hal_device_release_lock (HalDevice *device, const char *lock_name, char **hal_device_get_lock_holders (HalDevice *device, const char *lock_name); +int hal_device_get_num_lock_holders (HalDevice *device, const char *lock_name); + /* static method */ void hal_device_client_disconnected (const char *sender); diff --git a/hald/device_store.c b/hald/device_store.c index 7c06aabe..23c054d3 100644 --- a/hald/device_store.c +++ b/hald/device_store.c @@ -41,6 +41,8 @@ enum { STORE_CHANGED, DEVICE_PROPERTY_CHANGED, DEVICE_CAPABILITY_ADDED, + DEVICE_LOCK_ACQUIRED, + DEVICE_LOCK_RELEASED, LAST_SIGNAL }; @@ -103,6 +105,33 @@ hal_device_store_class_init (HalDeviceStoreClass *klass) G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_STRING); + + signals[DEVICE_LOCK_ACQUIRED] = + g_signal_new ("device_lock_acquired", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalDeviceStoreClass, + device_lock_acquired), + NULL, NULL, + hald_marshal_VOID__OBJECT_STRING_STRING, + G_TYPE_NONE, 3, + G_TYPE_OBJECT, + G_TYPE_STRING, + G_TYPE_STRING); + + signals[DEVICE_LOCK_RELEASED] = + g_signal_new ("device_lock_released", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalDeviceStoreClass, + device_lock_released), + NULL, NULL, + hald_marshal_VOID__OBJECT_STRING_STRING, + G_TYPE_NONE, 3, + G_TYPE_OBJECT, + G_TYPE_STRING, + G_TYPE_STRING); + } static void @@ -169,6 +198,30 @@ emit_device_capability_added (HalDevice *device, device, capability); } +static void +emit_device_lock_acquired (HalDevice *device, + const char *lock_name, + const char *lock_owner, + gpointer data) +{ + HalDeviceStore *store = HAL_DEVICE_STORE (data); + + g_signal_emit (store, signals[DEVICE_LOCK_ACQUIRED], 0, + device, lock_name, lock_owner); +} + +static void +emit_device_lock_released (HalDevice *device, + const char *lock_name, + const char *lock_owner, + gpointer data) +{ + HalDeviceStore *store = HAL_DEVICE_STORE (data); + + g_signal_emit (store, signals[DEVICE_LOCK_RELEASED], 0, + device, lock_name, lock_owner); +} + void hal_device_store_add (HalDeviceStore *store, HalDevice *device) { @@ -187,6 +240,10 @@ hal_device_store_add (HalDeviceStore *store, HalDevice *device) G_CALLBACK (emit_device_property_changed), store); g_signal_connect (device, "capability_added", G_CALLBACK (emit_device_capability_added), store); + g_signal_connect (device, "lock_acquired", + G_CALLBACK (emit_device_lock_acquired), store); + g_signal_connect (device, "lock_released", + G_CALLBACK (emit_device_lock_released), store); g_signal_emit (store, signals[STORE_CHANGED], 0, device, TRUE); @@ -208,6 +265,12 @@ hal_device_store_remove (HalDeviceStore *store, HalDevice *device) g_signal_handlers_disconnect_by_func (device, (gpointer)emit_device_capability_added, store); + g_signal_handlers_disconnect_by_func (device, + (gpointer)emit_device_lock_acquired, + store); + g_signal_handlers_disconnect_by_func (device, + (gpointer)emit_device_lock_released, + store); g_signal_emit (store, signals[STORE_CHANGED], 0, device, FALSE); diff --git a/hald/device_store.h b/hald/device_store.h index 0e1578a4..300f4c70 100644 --- a/hald/device_store.h +++ b/hald/device_store.h @@ -58,6 +58,16 @@ struct _HalDeviceStoreClass { HalDevice *device, const char *capability); + + void (*device_lock_acquired) (HalDeviceStore *store, + HalDevice *device, + const char *lock_name, + const char *lock_owner); + + void (*device_lock_released) (HalDeviceStore *store, + HalDevice *device, + const char *lock_name, + const char *lock_owner); }; #define HAL_TYPE_DEVICE_STORE (hal_device_store_get_type ()) diff --git a/hald/hald.c b/hald/hald.c index c130ca80..1a13a316 100644 --- a/hald/hald.c +++ b/hald/hald.c @@ -161,6 +161,32 @@ gdl_capability_added (HalDeviceStore *store, HalDevice *device, /*hal_callout_capability (device, capability, TRUE)*/; } +static void +gdl_lock_acquired (HalDeviceStore *store, HalDevice *device, const char *lock_name, const char *lock_owner) +{ + if (hal_device_are_all_addons_ready (device)) { + if (strncmp (lock_name, "Global.", 7) == 0 && + strcmp (hal_device_get_udi (device), "/org/freedesktop/Hal/devices/computer") == 0) { + manager_send_signal_interface_lock_acquired (lock_name + 7, lock_owner); + } else { + device_send_signal_interface_lock_acquired (device, lock_name, lock_owner); + } + } +} + +static void +gdl_lock_released (HalDeviceStore *store, HalDevice *device, const char *lock_name, const char *lock_owner) +{ + if (hal_device_are_all_addons_ready (device)) { + if (strncmp (lock_name, "Global.", 7) == 0 && + strcmp (hal_device_get_udi (device), "/org/freedesktop/Hal/devices/computer") == 0) { + manager_send_signal_interface_lock_released (lock_name + 7, lock_owner); + } else { + device_send_signal_interface_lock_released (device, lock_name, lock_owner); + } + } +} + HalDeviceStore * hald_get_gdl (void) { @@ -176,6 +202,15 @@ hald_get_gdl (void) g_signal_connect (global_device_list, "device_capability_added", G_CALLBACK (gdl_capability_added), NULL); + g_signal_connect (global_device_list, + "device_property_changed", + G_CALLBACK (gdl_property_changed), NULL); + g_signal_connect (global_device_list, + "device_lock_acquired", + G_CALLBACK (gdl_lock_acquired), NULL); + g_signal_connect (global_device_list, + "device_lock_released", + G_CALLBACK (gdl_lock_released), NULL); } return global_device_list; diff --git a/hald/hald_dbus.c b/hald/hald_dbus.c index 28169475..90dc9f7c 100644 --- a/hald/hald_dbus.c +++ b/hald/hald_dbus.c @@ -761,6 +761,146 @@ out: ; } +void +manager_send_signal_interface_lock_acquired (const char *interface_name, const char *sender) +{ + const char *udi; + char *lock_name; + int num_locks; + HalDevice *d; + DBusMessage *message; + DBusMessageIter iter; + + if (dbus_connection == NULL || hald_is_initialising) + goto out; + + udi = "/org/freedesktop/Hal/devices/computer"; + d = hal_device_store_find (hald_get_gdl (), udi); + if (d == NULL) + d = hal_device_store_find (hald_get_tdl (), udi); + if (d == NULL) + goto out; + + lock_name = g_strdup_printf ("Global.%s", interface_name); + num_locks = hal_device_get_num_lock_holders (d, lock_name); + g_free (lock_name); + + message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager", + "org.freedesktop.Hal.Manager", + "GlobalInterfaceLockAcquired"); + + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &sender); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &num_locks); + + if (!dbus_connection_send (dbus_connection, message, NULL)) + DIE (("error broadcasting message")); + + dbus_message_unref (message); +out: + ; +} + +void +manager_send_signal_interface_lock_released (const char *interface_name, const char *sender) +{ + const char *udi; + char *lock_name; + int num_locks; + HalDevice *d; + DBusMessage *message; + DBusMessageIter iter; + + if (dbus_connection == NULL || hald_is_initialising) + goto out; + + udi = "/org/freedesktop/Hal/devices/computer"; + d = hal_device_store_find (hald_get_gdl (), udi); + if (d == NULL) + d = hal_device_store_find (hald_get_tdl (), udi); + if (d == NULL) + goto out; + + lock_name = g_strdup_printf ("Global.%s", interface_name); + num_locks = hal_device_get_num_lock_holders (d, lock_name); + g_free (lock_name); + + message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager", + "org.freedesktop.Hal.Manager", + "GlobalInterfaceLockReleased"); + + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &sender); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &num_locks); + + if (!dbus_connection_send (dbus_connection, message, NULL)) + DIE (("error broadcasting message")); + + dbus_message_unref (message); +out: + ; +} + +void +device_send_signal_interface_lock_acquired (HalDevice *device, const char *interface_name, const char *sender) +{ + int num_locks; + DBusMessage *message; + DBusMessageIter iter; + + if (dbus_connection == NULL || hald_is_initialising) + goto out; + + num_locks = hal_device_get_num_lock_holders (device, interface_name); + + message = dbus_message_new_signal (hal_device_get_udi (device), + "org.freedesktop.Hal.Device", + "InterfaceLockAcquired"); + + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &sender); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &num_locks); + + if (!dbus_connection_send (dbus_connection, message, NULL)) + DIE (("error broadcasting message")); + + dbus_message_unref (message); +out: + ; +} + +void +device_send_signal_interface_lock_released (HalDevice *device, const char *interface_name, const char *sender) +{ + int num_locks; + DBusMessage *message; + DBusMessageIter iter; + + if (dbus_connection == NULL || hald_is_initialising) + goto out; + + num_locks = hal_device_get_num_lock_holders (device, interface_name); + + message = dbus_message_new_signal (hal_device_get_udi (device), + "org.freedesktop.Hal.Device", + "InterfaceLockReleased"); + + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &sender); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &num_locks); + + if (!dbus_connection_send (dbus_connection, message, NULL)) + DIE (("error broadcasting message")); + + dbus_message_unref (message); +out: + ; +} + static void foreach_property_append (HalDevice *device, const char *key, @@ -1903,7 +2043,7 @@ device_acquire_interface_lock (DBusConnection *connection, DBusMessage *message, sender = dbus_message_get_sender (message); if (!local_interface) { - if (!access_check_caller_have_access_to_device (ci_tracker, d, sender)) { + if (!access_check_caller_have_access_to_device (ci_tracker, d, "lock", sender)) { raise_permission_denied (connection, message, "AcquireInterfaceLock: no access to device"); return DBUS_HANDLER_RESULT_HANDLED; } @@ -1960,7 +2100,7 @@ device_release_interface_lock (DBusConnection *connection, DBusMessage *message, sender = dbus_message_get_sender (message); if (!local_interface) { - if (!access_check_caller_have_access_to_device (ci_tracker, d, sender)) { + if (!access_check_caller_have_access_to_device (ci_tracker, d, "lock", sender)) { raise_permission_denied (connection, message, "ReleaseInterfaceLock: no access to device"); return DBUS_HANDLER_RESULT_HANDLED; } @@ -1990,7 +2130,6 @@ device_release_interface_lock (DBusConnection *connection, DBusMessage *message, return DBUS_HANDLER_RESULT_HANDLED; } - static DBusHandlerResult device_is_caller_locked_out (DBusConnection *connection, DBusMessage *message, dbus_bool_t local_interface) { @@ -2049,6 +2188,62 @@ device_is_caller_locked_out (DBusConnection *connection, DBusMessage *message, d return DBUS_HANDLER_RESULT_HANDLED; } + +/*------------------------------------------------------------------------*/ + +static DBusHandlerResult +device_is_locked_by_others (DBusConnection *connection, DBusMessage *message, dbus_bool_t local_interface) +{ + const char *udi; + HalDevice *d; + DBusMessage *reply; + DBusError error; + const char *sender; + char *interface_name; + dbus_bool_t result; + DBusMessageIter iter; + + 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; + } + + sender = dbus_message_get_sender (message); + + /* anyone can ask this question */ + + dbus_error_init (&error); + if (!dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &interface_name, + DBUS_TYPE_INVALID)) { + raise_syntax (connection, message, "IsLockedByOthers"); + return DBUS_HANDLER_RESULT_HANDLED; + } + + result = access_check_locked_by_others (ci_tracker, d, sender, interface_name); + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + DIE (("No memory")); + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &result); + + if (!dbus_connection_send (connection, reply, NULL)) + DIE (("No memory")); + + dbus_message_unref (reply); + return DBUS_HANDLER_RESULT_HANDLED; +} + /*------------------------------------------------------------------------*/ static DBusHandlerResult @@ -3707,6 +3902,16 @@ do_introspect (DBusConnection *connection, " <arg name=\"udi\" type=\"s\"/>\n" " <arg name=\"cap_name\" type=\"s\"/>\n" " </signal>\n" + " <signal name=\"GlobalInterfaceLockAcquired\">\n" + " <arg name=\"interface_name\" type=\"s\"/>\n" + " <arg name=\"lock_holder\" type=\"s\"/>\n" + " <arg name=\"num_locks\" type=\"i\"/>\n" + " </signal>\n" + " <signal name=\"GlobalInterfaceLockReleased\">\n" + " <arg name=\"interface_name\" type=\"s\"/>\n" + " <arg name=\"lock_holder\" type=\"s\"/>\n" + " <arg name=\"num_locks\" type=\"i\"/>\n" + " </signal>\n" " </interface>\n"); } else { @@ -3816,6 +4021,10 @@ do_introspect (DBusConnection *connection, " <arg name=\"caller_sysbus_name\" direction=\"in\" type=\"s\"/>\n" " <arg name=\"whether_caller_is_locked_out\" direction=\"out\" type=\"b\"/>\n" " </method>\n" + " <method name=\"IsLockedByOthers\">\n" + " <arg name=\"interface_name\" direction=\"in\" type=\"s\"/>\n" + " <arg name=\"whether_it_is_locked_by_others\" direction=\"out\" type=\"b\"/>\n" + " </method>\n" " <method name=\"StringListAppend\">\n" " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n" @@ -3860,6 +4069,17 @@ do_introspect (DBusConnection *connection, " <arg name=\"cond_details\" type=\"s\"/>\n" " </signal>\n" + " <signal name=\"InterfaceLockAcquired\">\n" + " <arg name=\"interface_name\" type=\"s\"/>\n" + " <arg name=\"lock_holder\" type=\"s\"/>\n" + " <arg name=\"num_locks\" type=\"i\"/>\n" + " </signal>\n" + " <signal name=\"InterfaceLockReleased\">\n" + " <arg name=\"interface_name\" type=\"s\"/>\n" + " <arg name=\"lock_holder\" type=\"s\"/>\n" + " <arg name=\"num_locks\" type=\"i\"/>\n" + " </signal>\n" + " </interface>\n"); HalDeviceStrListIter if_iter; @@ -4085,7 +4305,10 @@ hald_dbus_filter_handle_methods (DBusConnection *connection, DBusMessage *messag "org.freedesktop.Hal.Device", "IsCallerLockedOut")) { return device_is_caller_locked_out (connection, message, local_interface); - + } else if (dbus_message_is_method_call (message, + "org.freedesktop.Hal.Device", + "IsLockedByOthers")) { + return device_is_locked_by_others (connection, message, local_interface); } else if (dbus_message_is_method_call (message, "org.freedesktop.Hal.Device", "GetAllProperties")) { @@ -4249,7 +4472,7 @@ hald_dbus_filter_handle_methods (DBusConnection *connection, DBusMessage *messag /* bypass security checks on direct connections */ if (!local_interface) { - if (!access_check_caller_have_access_to_device (ci_tracker, d, caller)) { + if (!access_check_caller_have_access_to_device (ci_tracker, d, NULL, caller)) { HAL_INFO (("Caller '%s' does not have access to device '%s'", caller, udi)); /* TODO: need to fix up reason */ raise_permission_denied (connection, message, "Not in active session"); @@ -4366,13 +4589,6 @@ DBusHandlerResult hald_dbus_filter_function (DBusConnection * connection, DBusMessage * message, void *user_data) { -#ifdef HAVE_CONKIT - /* TODO: only push the appropriate messages to the tracker; see ck-tracker.h */ - if (ck_tracker != NULL) { - ck_tracker_process_system_bus_message (ck_tracker, message); - } -#endif - if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") && strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) { @@ -4439,10 +4655,26 @@ hald_dbus_filter_function (DBusConnection * connection, HAL_INFO (("active=%d for session %s", is_active, session_objpath)); ci_tracker_active_changed (ci_tracker, session_objpath, is_active); #endif /* HAVE_CONKIT */ - } else + } else { + +#ifdef HAVE_CONKIT + /* TODO: only push the appropriate messages to the tracker; see ck-tracker.h */ + if (ck_tracker != NULL) { + ck_tracker_process_system_bus_message (ck_tracker, message); + } +#endif return hald_dbus_filter_handle_methods (connection, message, user_data, FALSE); + } out: + +#ifdef HAVE_CONKIT + /* TODO: only push the appropriate messages to the tracker; see ck-tracker.h */ + if (ck_tracker != NULL) { + ck_tracker_process_system_bus_message (ck_tracker, message); + } +#endif + return DBUS_HANDLER_RESULT_HANDLED; } @@ -4698,6 +4930,50 @@ hald_dbus_seat_removed (CKTracker *tracker, CKSeat *seat, void *user_data) /* TODO: we could run callouts here... but they wouldn't do anything useful right now */ } +static gboolean +validate_lock_for_device (HalDeviceStore *store, + HalDevice *device, + gpointer user_data) +{ + int n, m; + char **holders; + char **locked_interfaces; + + locked_interfaces = hal_device_property_dup_strlist_as_strv (device, "info.named_locks"); + if (locked_interfaces == NULL) + goto out; + + for (n = 0; locked_interfaces[n] != NULL; n++) { + holders = hal_device_get_lock_holders (device, locked_interfaces[n]); + if (holders == NULL) + continue; + for (m = 0; holders[m] != NULL; m++) { + HAL_INFO (("Validating lock holder '%s' on interface '%s' on udi '%s'", + holders[m], locked_interfaces[n], hal_device_get_udi (device))); + + if (!access_check_caller_have_access_to_device (ci_tracker, device, "lock", holders[m])) { + HAL_INFO (("Kicking out lock holder '%s' on interface '%s' on udi '%s' " + "as he no longer has access to the device", + holders[m], locked_interfaces[n], hal_device_get_udi (device))); + hal_device_release_lock (device, locked_interfaces[n], holders[m]); + } + + } + g_strfreev (holders); + } + + g_strfreev (locked_interfaces); +out: + return TRUE; +} + +static void +validate_locks (void) +{ + hal_device_store_foreach (hald_get_tdl (), validate_lock_for_device, NULL); + hal_device_store_foreach (hald_get_gdl (), validate_lock_for_device, NULL); +} + static void hald_dbus_session_active_changed (CKTracker *tracker, CKSession *session, void *user_data) { @@ -4713,6 +4989,9 @@ hald_dbus_session_active_changed (CKTracker *tracker, CKSession *session, void * ck_session_get_id (session), ck_session_is_active (session) ? "ACTIVE" : "INACTIVE")); + /* revalidate all locks (to remove locks from callers in that session who no longer has access to devices */ + validate_locks (); + d = hal_device_store_find (hald_get_gdl (), "/org/freedesktop/Hal/devices/computer"); if (d == NULL) { d = hal_device_store_find (hald_get_tdl (), "/org/freedesktop/Hal/devices/computer"); diff --git a/hald/hald_dbus.h b/hald/hald_dbus.h index d7f9accd..4a5deb18 100644 --- a/hald/hald_dbus.h +++ b/hald/hald_dbus.h @@ -83,6 +83,12 @@ void manager_send_signal_device_removed (HalDevice *device); void manager_send_signal_new_capability (HalDevice *device, const char *capability); +void manager_send_signal_interface_lock_acquired (const char *interface_name, const char *sender); +void manager_send_signal_interface_lock_released (const char *interface_name, const char *sender); + +void device_send_signal_interface_lock_acquired (HalDevice *device, const char *interface_name, const char *sender); +void device_send_signal_interface_lock_released (HalDevice *device, const char *interface_name, const char *sender); + void device_send_signal_property_modified (HalDevice *device, const char *key, dbus_bool_t removed, diff --git a/hald/hald_marshal.list b/hald/hald_marshal.list index 8e3863a8..14dd6f82 100644 --- a/hald/hald_marshal.list +++ b/hald/hald_marshal.list @@ -1,3 +1,5 @@ +VOID:OBJECT,STRING,STRING +VOID:STRING,STRING VOID:STRING,BOOL,BOOL VOID:STRING VOID:OBJECT,BOOL diff --git a/libhal/libhal.c b/libhal/libhal.c index b5f3c1e7..8e760321 100644 --- a/libhal/libhal.c +++ b/libhal/libhal.c @@ -245,6 +245,18 @@ struct LibHalContext_s { /** A non-continous event on the device occured */ LibHalDeviceCondition device_condition; + + /** A global interface lock is acquired */ + LibHalGlobalInterfaceLockAcquired global_interface_lock_acquired; + + /** A global interface lock is released */ + LibHalGlobalInterfaceLockReleased global_interface_lock_released; + + /** An interface lock is acquired */ + LibHalInterfaceLockAcquired interface_lock_acquired; + + /** An interface lock is released */ + LibHalInterfaceLockReleased interface_lock_released; void *user_data; /**< User data */ }; @@ -512,10 +524,11 @@ oom: return NULL; } -/* libhal_property_set_sort: +/** + * libhal_property_set_sort: * @set: property-set to sort * - * sort all properties according to property name + * Sort all properties according to property name. */ void libhal_property_set_sort (LibHalPropertySet *set) @@ -824,6 +837,38 @@ filter_func (DBusConnection * connection, LIBHAL_FREE_DBUS_ERROR(&error); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","GlobalInterfaceLockAcquired")) { + char *lock_name; + char *lock_owner; + int num_locks; + if (dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &lock_name, + DBUS_TYPE_STRING, &lock_owner, + DBUS_TYPE_INT32, &num_locks, + DBUS_TYPE_INVALID)) { + if (ctx->global_interface_lock_acquired != NULL) { + ctx->global_interface_lock_acquired (ctx, lock_name, lock_owner, num_locks); + } + } else { + LIBHAL_FREE_DBUS_ERROR(&error); + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","GlobalInterfaceLockReleased")) { + char *lock_name; + char *lock_owner; + int num_locks; + if (dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &lock_name, + DBUS_TYPE_STRING, &lock_owner, + DBUS_TYPE_INT32, &num_locks, + DBUS_TYPE_INVALID)) { + if (ctx->global_interface_lock_released != NULL) { + ctx->global_interface_lock_released (ctx, lock_name, lock_owner, num_locks); + } + } else { + LIBHAL_FREE_DBUS_ERROR(&error); + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) { char *condition_name; char *condition_detail; @@ -838,6 +883,38 @@ filter_func (DBusConnection * connection, LIBHAL_FREE_DBUS_ERROR(&error); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device","InterfaceLockAcquired")) { + char *lock_name; + char *lock_owner; + int num_locks; + if (dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &lock_name, + DBUS_TYPE_STRING, &lock_owner, + DBUS_TYPE_INT32, &num_locks, + DBUS_TYPE_INVALID)) { + if (ctx->interface_lock_acquired != NULL) { + ctx->interface_lock_acquired (ctx, object_path, lock_name, lock_owner, num_locks); + } + } else { + LIBHAL_FREE_DBUS_ERROR(&error); + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device","InterfaceLockReleased")) { + char *lock_name; + char *lock_owner; + int num_locks; + if (dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &lock_name, + DBUS_TYPE_STRING, &lock_owner, + DBUS_TYPE_INT32, &num_locks, + DBUS_TYPE_INVALID)) { + if (ctx->interface_lock_released != NULL) { + ctx->interface_lock_released (ctx, object_path, lock_name, lock_owner, num_locks); + } + } else { + LIBHAL_FREE_DBUS_ERROR(&error); + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) { if (ctx->device_property_modified != NULL) { int i; @@ -3901,7 +3978,7 @@ out: } /** - * libhal_device_set_property_strlist: + * libhal_changeset_set_property_strlist: * @changeset: the changeset * @key: key of property * @value: the value to set - NULL terminated array of strings @@ -4130,6 +4207,18 @@ libhal_device_free_changeset (LibHalChangeSet *changeset) } +/** + * libhal_device_acquire_interface_lock: + * @ctx: the context for the connection to hald + * @udi: the Unique id of device + * @interface: the intername name to lock + * @exclusive: whether the lock should be exclusive + * @error: pointer to an initialized dbus error object for returning errors + * + * Releases a lock on an interface for a specific device. + * + * Returns: TRUE iff the lock was acquired + **/ dbus_bool_t libhal_device_acquire_interface_lock (LibHalContext *ctx, const char *udi, @@ -4179,6 +4268,17 @@ libhal_device_acquire_interface_lock (LibHalContext *ctx, return TRUE; } +/** + * libhal_device_release_interface_lock: + * @ctx: the context for the connection to hald + * @udi: the Unique id of device + * @interface: the intername name to unlock + * @error: pointer to an initialized dbus error object for returning errors + * + * Acquires a lock on an interface for a specific device. + * + * Returns: TRUE iff the lock was released. + **/ dbus_bool_t libhal_device_release_interface_lock (LibHalContext *ctx, const char *udi, const char *interface, @@ -4225,6 +4325,17 @@ dbus_bool_t libhal_device_release_interface_lock (LibHalContext *ctx, return TRUE; } +/** + * libhal_acquire_global_interface_lock: + * @ctx: the context for the connection to hald + * @interface: the intername name to lock + * @exclusive: whether the lock should be exclusive + * @error: pointer to an initialized dbus error object for returning errors + * + * Acquires a global lock on an interface. + * + * Returns: TRUE iff the lock was acquired + **/ dbus_bool_t libhal_acquire_global_interface_lock (LibHalContext *ctx, const char *interface, dbus_bool_t exclusive, @@ -4271,6 +4382,16 @@ dbus_bool_t libhal_acquire_global_interface_lock (LibHalContext *ctx, return TRUE; } +/** + * libhal_release_global_interface_lock: + * @ctx: the context for the connection to hald + * @interface: the intername name to unlock + * @error: pointer to an initialized dbus error object for returning errors + * + * Releases a global lock on an interface. + * + * Returns: TRUE iff the lock was released + **/ dbus_bool_t libhal_release_global_interface_lock (LibHalContext *ctx, const char *interface, DBusError *error) @@ -4315,6 +4436,20 @@ dbus_bool_t libhal_release_global_interface_lock (LibHalContext *ctx, return TRUE; } +/** + * libhal_device_is_caller_locked_out: + * @ctx: the context for the connection to hald + * @udi: the Unique id of device + * @interface: the intername name to check + * @caller: the caller to check for + * @error: pointer to an initialized dbus error object for returning errors + * + * Determines whether a given process on the system message bus is + * locked out from an interface on a specific device. Only HAL helpers + * are privileged to use this method. + * + * Returns: Whether the given caller is locked out + **/ dbus_bool_t libhal_device_is_caller_locked_out (LibHalContext *ctx, const char *udi, @@ -4375,3 +4510,143 @@ libhal_device_is_caller_locked_out (LibHalContext *ctx, return value; } + +/** + * libhal_ctx_set_global_interface_lock_acquired: + * @ctx: the context for the connection to hald + * @callback: the callback + * + * Set the callback for when a global interface lock is acquired. + * + * Returns: TRUE if callback was successfully set, FALSE otherwise + */ +dbus_bool_t +libhal_ctx_set_global_interface_lock_acquired (LibHalContext *ctx, LibHalGlobalInterfaceLockAcquired callback) +{ + LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE); + ctx->global_interface_lock_acquired = callback; + return TRUE; +} + +/** + * libhal_ctx_set_global_interface_lock_released: + * @ctx: the context for the connection to hald + * @callback: the callback + * + * Set the callback for when a global interface lock is released. + * + * Returns: TRUE if callback was successfully set, FALSE otherwise + */ +dbus_bool_t +libhal_ctx_set_global_interface_lock_released (LibHalContext *ctx, LibHalGlobalInterfaceLockReleased callback) +{ + LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE); + ctx->global_interface_lock_released = callback; + return TRUE; +} + + +/** + * libhal_ctx_set_interface_lock_acquired: + * @ctx: the context for the connection to hald + * @callback: the callback + * + * Set the callback for when an interface lock is acquired. + * + * Returns: TRUE if callback was successfully set, FALSE otherwise + */ +dbus_bool_t +libhal_ctx_set_interface_lock_acquired (LibHalContext *ctx, LibHalInterfaceLockAcquired callback) +{ + LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE); + ctx->interface_lock_acquired = callback; + return TRUE; +} + +/** + * libhal_ctx_set_interface_lock_released: + * @ctx: the context for the connection to hald + * @callback: the callback + * + * Set the callback for when an interface lock is released. + * + * Returns: TRUE if callback was successfully set, FALSE otherwise + */ +dbus_bool_t +libhal_ctx_set_interface_lock_released (LibHalContext *ctx, LibHalInterfaceLockReleased callback) +{ + LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE); + ctx->interface_lock_released = callback; + return TRUE; +} + + + +/** + * libhal_device_is_locked_by_others: + * @ctx: the context for the connection to hald + * @udi: the Unique id of device + * @interface: the intername name to check + * @error: pointer to an initialized dbus error object for returning errors or NULL + * + * Determines whether a determines other processes than the caller holds a lock on the given device. + * + * Returns: If another process is holding a lock on the device + **/ +dbus_bool_t +libhal_device_is_locked_by_others (LibHalContext *ctx, + const char *udi, + const char *interface, + DBusError *error) +{ + DBusMessage *message; + DBusMessageIter iter; + DBusMessage *reply; + DBusMessageIter reply_iter; + dbus_bool_t value; + + LIBHAL_CHECK_LIBHALCONTEXT(ctx, TRUE); + LIBHAL_CHECK_PARAM_VALID(udi, "*udi", TRUE); + LIBHAL_CHECK_PARAM_VALID(interface, "*interface", TRUE); + + message = dbus_message_new_method_call ("org.freedesktop.Hal", + udi, + "org.freedesktop.Hal.Device", + "IsLockedByOthers"); + + if (message == NULL) { + fprintf (stderr, + "%s %d : Couldn't allocate D-BUS message\n", + __FILE__, __LINE__); + return TRUE; + } + + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface); + + reply = dbus_connection_send_with_reply_and_block (ctx->connection, + message, -1, + error); + + if (error != NULL && dbus_error_is_set (error)) { + dbus_message_unref (message); + return TRUE; + } + + dbus_message_unref (message); + + if (reply == NULL) + return TRUE; + + /* now analyze reply */ + dbus_message_iter_init (reply, &reply_iter); + if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) { + dbus_message_unref (message); + dbus_message_unref (reply); + return TRUE; + } + dbus_message_iter_get_basic (&reply_iter, &value); + dbus_message_unref (reply); + return value; +} + diff --git a/libhal/libhal.h b/libhal/libhal.h index 897787a0..015406c3 100644 --- a/libhal/libhal.h +++ b/libhal/libhal.h @@ -191,6 +191,67 @@ typedef void (*LibHalDeviceCondition) (LibHalContext *ctx, const char *condition_name, const char *condition_detail); +/** + * LibHalGlobalInterfaceLockAcquired: + * @ctx: context for connection to hald + * @interface_name: the name of the interface + * @lock_owner: what service acquired the lock + * @num_locks: number of locks on the interface + * + * Type for callback when someone acquires a global lock. + */ +typedef void (*LibHalGlobalInterfaceLockAcquired) (LibHalContext *ctx, + const char *interface_name, + const char *lock_owner, + int num_locks); + +/** + * LibHalGlobalInterfaceLockReleased: + * @ctx: context for connection to hald + * @interface_name: the name of the interface + * @lock_owner: what service released the lock + * @num_locks: number of locks on the interface + * + * Type for callback when someone releases a global lock. + */ +typedef void (*LibHalGlobalInterfaceLockReleased) (LibHalContext *ctx, + const char *interface_name, + const char *lock_owner, + int num_locks); + +/** + * LibHalInterfaceLockAcquired: + * @ctx: context for connection to hald + * @udi: the Unique Device Id + * @interface_name: the name of the interface + * @lock_owner: what service acquired the lock + * @num_locks: number of locks on the interface + * + * Type for callback when someone acquires a lock on a device. + */ +typedef void (*LibHalInterfaceLockAcquired) (LibHalContext *ctx, + const char *udi, + const char *interface_name, + const char *lock_owner, + int num_locks); + +/** + * LibHalInterfaceLockReleased: + * @ctx: context for connection to hald + * @udi: the Unique Device Id + * @interface_name: the name of the interface + * @lock_owner: what service released the lock + * @num_locks: number of locks on the interface + * + * Type for callback when someone acquires a lock on a device. + */ +typedef void (*LibHalInterfaceLockReleased) (LibHalContext *ctx, + const char *udi, + const char *interface_name, + const char *lock_owner, + int num_locks); + + /* Create a new context for a connection with hald */ LibHalContext *libhal_ctx_new (void); @@ -228,6 +289,18 @@ dbus_bool_t libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibH /* Set the callback for when a device emits a condition */ dbus_bool_t libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback); +/* Set the callback for when a global interface lock is acquired */ +dbus_bool_t libhal_ctx_set_global_interface_lock_acquired (LibHalContext *ctx, LibHalGlobalInterfaceLockAcquired callback); + +/* Set the callback for when a global interface lock is released */ +dbus_bool_t libhal_ctx_set_global_interface_lock_released (LibHalContext *ctx, LibHalGlobalInterfaceLockReleased callback); + +/* Set the callback for when an interface lock is acquired */ +dbus_bool_t libhal_ctx_set_interface_lock_acquired (LibHalContext *ctx, LibHalInterfaceLockAcquired callback); + +/* Set the callback for when an interface lock is released */ +dbus_bool_t libhal_ctx_set_interface_lock_released (LibHalContext *ctx, LibHalInterfaceLockReleased callback); + /* Initialize the connection to hald */ dbus_bool_t libhal_ctx_init (LibHalContext *ctx, DBusError *error); @@ -634,6 +707,12 @@ dbus_bool_t libhal_device_is_caller_locked_out (LibHalContext *ctx, const char *caller, DBusError *error); +/* Determines whether a determines other processes than the caller holds a lock on the given device. */ +dbus_bool_t libhal_device_is_locked_by_others (LibHalContext *ctx, + const char *udi, + const char *interface, + DBusError *error); + #if defined(__cplusplus) } diff --git a/tools/hal-lock.c b/tools/hal-lock.c index cd54f26d..f58431e4 100644 --- a/tools/hal-lock.c +++ b/tools/hal-lock.c @@ -37,6 +37,7 @@ #include <sys/wait.h> #include <signal.h> #include <glib.h> +#include <dbus/dbus-glib-lowlevel.h> #include "libhal.h" @@ -56,6 +57,7 @@ usage (int argc, char *argv[]) " --run <program-and-args>\n" " [--udi <udi>]\n" " [--exclusive]\n" + " [--exit-with-lock]" " [--help] [--version]\n"); fprintf (stderr, "\n" @@ -64,6 +66,7 @@ usage (int argc, char *argv[]) " --udi Unique Device Id of device to lock. If\n" " ommitted the global lock will be tried\n" " --exclusive Whether the lock can be held by others\n" + " --exit-with-lock Kill the program if the acquired lock is lost\n" " --version Show version and exit\n" " --help Show this information and exit\n" "\n" @@ -77,6 +80,35 @@ usage (int argc, char *argv[]) "\n"); } +static char *udi = NULL; +static char *interface = NULL; +static const char *unique_name; +static GPid child_pid; + +static void +guardian (GPid pid, int status, gpointer data) +{ + /* exit along with the child */ + exit (0); +} + +static void +interface_lock_released (LibHalContext *ctx, + const char *_udi, + const char *_interface, + const char *lock_owner, + int num_locks) +{ + + + if (strcmp (udi, _udi) == 0 && + strcmp (interface, _interface) == 0 && + strcmp (lock_owner, unique_name) == 0) { + fprintf (stderr, "Lost the lock; killing child...\n"); + kill (child_pid, SIGTERM); + } +} + /** * main: * @argc: Number of arguments given to program @@ -89,16 +121,17 @@ usage (int argc, char *argv[]) int main (int argc, char *argv[]) { - char *udi = NULL; - char *interface = NULL; char *run = NULL; dbus_bool_t is_version = FALSE; dbus_bool_t exclusive = FALSE; dbus_bool_t got_lock = FALSE; + dbus_bool_t exit_with_lock = FALSE; + DBusConnection *con; DBusError error; LibHalContext *hal_ctx; int ret; GError *g_error = NULL; + GMainLoop *loop; ret = 1; @@ -116,6 +149,7 @@ main (int argc, char *argv[]) {"interface", 1, NULL, 0}, {"run", 1, NULL, 0}, {"exclusive", 0, NULL, 0}, + {"exit-with-lock", 0, NULL, 0}, {"version", 0, NULL, 0}, {"help", 0, NULL, 0}, {NULL, 0, NULL, 0} @@ -143,6 +177,8 @@ main (int argc, char *argv[]) exclusive = TRUE; } else if (strcmp (opt, "interface") == 0) { interface = strdup (optarg); + } else if (strcmp (opt, "exit-with-lock") == 0) { + exit_with_lock = TRUE; } break; @@ -164,17 +200,41 @@ main (int argc, char *argv[]) goto out; } + if (exit_with_lock && udi == NULL) { + fprintf (stderr, "--exit-with-lock requires UDI to be given.\n"); + usage (argc, argv); + goto out; + } + + if (exit_with_lock) + loop = g_main_loop_new (NULL, FALSE); + else + loop = NULL; + dbus_error_init (&error); if ((hal_ctx = libhal_ctx_new ()) == NULL) { fprintf (stderr, "error: libhal_ctx_new\n"); goto out; } - if (!libhal_ctx_set_dbus_connection (hal_ctx, dbus_bus_get (DBUS_BUS_SYSTEM, &error))) { - fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n", error.name, error.message); + con = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (con == NULL) { + fprintf (stderr, "error: dbus_bus_get: %s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); goto out; } + if (!libhal_ctx_set_dbus_connection (hal_ctx, con)) { + fprintf (stderr, "error: libhal_ctx_set_dbus_connection\n"); + goto out; + } + + if (exit_with_lock) { + unique_name = dbus_bus_get_unique_name (con); + fprintf (stderr, "unique name is '%s'\n", unique_name); + libhal_ctx_set_interface_lock_released (hal_ctx, interface_lock_released); + dbus_connection_setup_with_g_main (con, NULL); + } + if (!libhal_ctx_init (hal_ctx, &error)) { if (dbus_error_is_set(&error)) { fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message); @@ -184,6 +244,9 @@ main (int argc, char *argv[]) "Normally this means the HAL daemon (hald) is not running or not ready.\n"); goto out; } + + if (exit_with_lock) + libhal_device_add_property_watch (hal_ctx, udi, &error); if (udi != NULL) { got_lock = libhal_device_acquire_interface_lock (hal_ctx, @@ -213,16 +276,43 @@ main (int argc, char *argv[]) goto out; } - /* now run the program while holding the lock */ - if (!g_spawn_command_line_sync (run, - NULL, - NULL, - NULL, - &g_error)) { + if (exit_with_lock) { + int _argc; + char **_argv; + + if (!g_shell_parse_argv (run, &_argc, &_argv, &g_error)) { + fprintf (stderr, "error: g_shell_parse_argv: %s\n", g_error->message); + g_error_free (g_error); + goto out; + } - fprintf (stderr, "error: g_spawn_command_line_sync: %s\n", g_error->message); - g_error_free (g_error); - goto out; + if (!g_spawn_async (NULL, + _argv, + NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, + NULL, + NULL, + &child_pid, + &g_error)) { + fprintf (stderr, "error: g_spawn_command_line_async: %s\n", g_error->message); + g_error_free (g_error); + goto out; + } + g_child_watch_add (child_pid, guardian, NULL); + g_main_loop_run (loop); + + } else { + /* now run the program while holding the lock */ + if (!g_spawn_command_line_sync (run, + NULL, + NULL, + NULL, + &g_error)) { + + fprintf (stderr, "error: g_spawn_command_line_sync: %s\n", g_error->message); + g_error_free (g_error); + goto out; + } } ret = 0; diff --git a/tools/lshal.c b/tools/lshal.c index 09516574..7e2bf824 100644 --- a/tools/lshal.c +++ b/tools/lshal.c @@ -581,6 +581,77 @@ device_condition (LibHalContext *ctx, } } +static void +do_interface_lock (LibHalContext *ctx, + dbus_bool_t acquired, + dbus_bool_t global, + const char *udi, + const char *interface_name, + const char *lock_owner, + int num_locks) +{ + if (show_device && strcmp(show_device, udi)) + return; + + if (long_list) { + if (global) + printf ("*** %s: lshal: global_interface_lock_%s\n", get_time (), acquired ? "acquired" : "released"); + else + printf ("*** %s: lshal: interface_lock_%s, udi=%s\n", get_time (), acquired ? "acquired" : "released", udi); + printf (" interface_name=%s\n", interface_name); + printf (" lock_owner=%s\n", lock_owner); + printf (" num_locks=%d\n", num_locks); + printf ("\n"); + } else { + if (global) + printf ("%s: global_interface_lock_%s %s by %s (%d lockers)\n", get_time (), + acquired ? "acquired" : "released", + interface_name, lock_owner, num_locks); + else + printf ("%s: %s interface_lock_%s %s by %s (%d lockers)\n", get_time (), short_name (udi), + acquired ? "acquired" : "released", + interface_name, lock_owner, num_locks); + } +} + +static void +global_interface_lock_acquired (LibHalContext *ctx, + const char *interface_name, + const char *lock_owner, + int num_locks) +{ + do_interface_lock (ctx, TRUE, TRUE, NULL, interface_name, lock_owner, num_locks); +} + +static void +global_interface_lock_released (LibHalContext *ctx, + const char *interface_name, + const char *lock_owner, + int num_locks) +{ + do_interface_lock (ctx, FALSE, TRUE, NULL, interface_name, lock_owner, num_locks); +} + +static void +interface_lock_acquired (LibHalContext *ctx, + const char *udi, + const char *interface_name, + const char *lock_owner, + int num_locks) +{ + do_interface_lock (ctx, TRUE, FALSE, udi, interface_name, lock_owner, num_locks); +} + +static void +interface_lock_released (LibHalContext *ctx, + const char *udi, + const char *interface_name, + const char *lock_owner, + int num_locks) +{ + do_interface_lock (ctx, FALSE, FALSE, udi, interface_name, lock_owner, num_locks); +} + /** * usage: @@ -750,6 +821,10 @@ main (int argc, char *argv[]) libhal_ctx_set_device_lost_capability (hal_ctx, device_lost_capability); libhal_ctx_set_device_property_modified (hal_ctx, property_modified); libhal_ctx_set_device_condition (hal_ctx, device_condition); + libhal_ctx_set_global_interface_lock_acquired (hal_ctx, global_interface_lock_acquired); + libhal_ctx_set_global_interface_lock_released (hal_ctx, global_interface_lock_released); + libhal_ctx_set_interface_lock_acquired (hal_ctx, interface_lock_acquired); + libhal_ctx_set_interface_lock_released (hal_ctx, interface_lock_released); if (show_device) dump_device (show_device); |