</defaults>
</action>
+ <action id="org.freedesktop.devicekit.disks.inhibit-polling">
+ <_description>Inhibit media detection</_description>
+ <_message>Authentication is required to inhibit media detection</_message>
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>
devkit-disks-device-private.h \
mounts-file.h mounts-file.c \
devkit-disks-mount-monitor.h devkit-disks-mount-monitor.c \
+ devkit-disks-inhibitor.h devkit-disks-inhibitor.c \
+ poller.h poller.c \
main.c \
$(BUILT_SOURCES)
#include "devkit-disks-device-private.h"
#include "mounts-file.h"
#include "devkit-disks-mount-monitor.h"
+#include "poller.h"
+#include "devkit-disks-inhibitor.h"
#include "devkit-disks-daemon-glue.h"
#include "devkit-disks-marshal.h"
guint smart_refresh_timer_id;
DevkitDisksLogger *logger;
+
+ GList *polling_inhibitors;
};
static void devkit_disks_daemon_class_init (DevkitDisksDaemonClass *klass);
static void devkit_disks_daemon_init (DevkitDisksDaemon *seat);
static void devkit_disks_daemon_finalize (GObject *object);
+static void daemon_polling_inhibitor_disconnected_cb (DevkitDisksInhibitor *inhibitor,
+ DevkitDisksDaemon *daemon);
+
G_DEFINE_TYPE (DevkitDisksDaemon, devkit_disks_daemon, G_TYPE_OBJECT)
#define DEVKIT_DISKS_DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEVKIT_TYPE_DISKS_DAEMON, DevkitDisksDaemonPrivate))
devkit_disks_daemon_finalize (GObject *object)
{
DevkitDisksDaemon *daemon;
+ GList *l;
g_return_if_fail (object != NULL);
g_return_if_fail (DEVKIT_IS_DISKS_DAEMON (object));
g_object_unref (daemon->priv->logger);
}
+ for (l = daemon->priv->polling_inhibitors; l != NULL; l = l->next) {
+ DevkitDisksInhibitor *inhibitor = DEVKIT_DISKS_INHIBITOR (l->data);
+ g_signal_handlers_disconnect_by_func (inhibitor, daemon_polling_inhibitor_disconnected_cb, daemon);
+ g_object_unref (inhibitor);
+ }
+ g_list_free (daemon->priv->polling_inhibitors);
+
G_OBJECT_CLASS (devkit_disks_daemon_parent_class)->finalize (object);
}
g_source_remove (watch_id);
}
+void devkit_disks_inhibitor_name_owner_changed (DBusMessage *message);
+
static DBusHandlerResult
_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
{
if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
/* pass NameOwnerChanged signals from the bus to PolKitTracker */
polkit_tracker_dbus_func (daemon->priv->pk_tracker, message);
+
+ /* for now, pass NameOwnerChanged to DevkitDisksInhibitor */
+ devkit_disks_inhibitor_name_owner_changed (message);
}
if (interface != NULL && g_str_has_prefix (interface, "org.freedesktop.ConsoleKit")) {
device_remove (daemon, d);
} else {
g_print ("changed %s\n", native_path);
+ devkit_disks_daemon_local_update_poller (daemon);
}
} else {
g_print ("treating change event as add on %s\n", native_path);
object_path = devkit_disks_device_local_get_object_path (device);
g_signal_emit (daemon, signals[DEVICE_ADDED_SIGNAL], 0, object_path);
}
+ devkit_disks_daemon_local_update_poller (daemon);
} else {
g_print ("ignoring add event on %s\n", native_path);
}
g_signal_emit (daemon, signals[DEVICE_REMOVED_SIGNAL], 0,
devkit_disks_device_local_get_object_path (device));
g_object_unref (device);
+ devkit_disks_daemon_local_update_poller (daemon);
}
}
return ret;
}
+/*--------------------------------------------------------------------------------------------------------------*/
+
+void
+devkit_disks_daemon_local_update_poller (DevkitDisksDaemon *daemon)
+{
+ GHashTableIter hash_iter;
+ DevkitDisksDevice *device;
+ GList *devices_to_poll;
+
+ devices_to_poll = NULL;
+
+ g_hash_table_iter_init (&hash_iter, daemon->priv->map_object_path_to_device);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &device)) {
+ if (device->priv->info.device_is_media_change_detected)
+ devices_to_poll = g_list_prepend (devices_to_poll, device);
+ }
+
+ poller_set_devices (devices_to_poll);
+
+ g_list_free (devices_to_poll);
+}
/*--------------------------------------------------------------------------------------------------------------*/
}
/*--------------------------------------------------------------------------------------------------------------*/
+
+static void
+polling_update_devices (DevkitDisksDaemon *daemon)
+{
+ GHashTableIter hash_iter;
+ DevkitDisksDevice *device;
+
+ g_hash_table_iter_init (&hash_iter, daemon->priv->map_object_path_to_device);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &device)) {
+
+ if (devkit_disks_device_local_update_media_detection (device)) {
+ DevkitDevice *d;
+
+ d = g_object_ref (device->priv->d);
+ device_changed (daemon, d, TRUE);
+ g_object_unref (d);
+ }
+ }
+
+ devkit_disks_daemon_local_update_poller (daemon);
+}
+
+static void
+daemon_polling_inhibitor_disconnected_cb (DevkitDisksInhibitor *inhibitor,
+ DevkitDisksDaemon *daemon)
+{
+ daemon->priv->polling_inhibitors = g_list_remove (daemon->priv->polling_inhibitors, inhibitor);
+ g_signal_handlers_disconnect_by_func (inhibitor, daemon_polling_inhibitor_disconnected_cb, daemon);
+ g_object_unref (inhibitor);
+
+ polling_update_devices (daemon);
+}
+
+gboolean
+devkit_disks_daemon_local_has_polling_inhibitors (DevkitDisksDaemon *daemon)
+{
+ return daemon->priv->polling_inhibitors != NULL;
+}
+
+gboolean
+devkit_disks_daemon_drive_inhibit_all_polling (DevkitDisksDaemon *daemon,
+ char **options,
+ DBusGMethodInvocation *context)
+{
+ DevkitDisksInhibitor *inhibitor;
+ PolKitCaller *pk_caller;
+ guint n;
+
+ if ((pk_caller = devkit_disks_damon_local_get_caller_for_context (daemon, context)) == NULL)
+ goto out;
+
+
+ if (!devkit_disks_damon_local_check_auth (daemon,
+ pk_caller,
+ "org.freedesktop.devicekit.disks.inhibit-polling",
+ context))
+ goto out;
+
+ for (n = 0; options[n] != NULL; n++) {
+ const char *option = options[n];
+ throw_error (context,
+ DEVKIT_DISKS_ERROR_INVALID_OPTION,
+ "Unknown option %s", option);
+ goto out;
+ }
+
+ inhibitor = devkit_disks_inhibitor_new (context);
+
+ daemon->priv->polling_inhibitors = g_list_prepend (daemon->priv->polling_inhibitors, inhibitor);
+ g_signal_connect (inhibitor, "disconnected", G_CALLBACK (daemon_polling_inhibitor_disconnected_cb), daemon);
+
+ polling_update_devices (daemon);
+
+ dbus_g_method_return (context, devkit_disks_inhibitor_get_cookie (inhibitor));
+
+out:
+ if (pk_caller != NULL)
+ polkit_caller_unref (pk_caller);
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+gboolean
+devkit_disks_daemon_drive_uninhibit_all_polling (DevkitDisksDaemon *daemon,
+ char *cookie,
+ DBusGMethodInvocation *context)
+{
+ const gchar *sender;
+ DevkitDisksInhibitor *inhibitor;
+ GList *l;
+
+ sender = dbus_g_method_get_sender (context);
+
+ inhibitor = NULL;
+ for (l = daemon->priv->polling_inhibitors; l != NULL; l = l->next) {
+ DevkitDisksInhibitor *i = DEVKIT_DISKS_INHIBITOR (l->data);
+
+ if (g_strcmp0 (devkit_disks_inhibitor_get_unique_dbus_name (i), sender) == 0 &&
+ g_strcmp0 (devkit_disks_inhibitor_get_cookie (i), cookie) == 0) {
+ inhibitor = i;
+ break;
+ }
+ }
+
+ if (inhibitor == NULL) {
+ throw_error (context,
+ DEVKIT_DISKS_ERROR_FAILED,
+ "No such inhibitor");
+ goto out;
+ }
+
+ daemon->priv->polling_inhibitors = g_list_remove (daemon->priv->polling_inhibitors, inhibitor);
+ g_object_unref (inhibitor);
+
+ polling_update_devices (daemon);
+
+ dbus_g_method_return (context);
+
+ out:
+ return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
void devkit_disks_daemon_local_synthesize_changed (DevkitDisksDaemon *daemon,
DevkitDevice *d);
+void devkit_disks_daemon_local_update_poller (DevkitDisksDaemon *daemon);
+
+gboolean devkit_disks_daemon_local_has_polling_inhibitors (DevkitDisksDaemon *daemon);
+
DevkitDisksLogger *devkit_disks_daemon_local_get_logger (DevkitDisksDaemon *daemon);
/* exported methods */
char **options,
DBusGMethodInvocation *context);
+gboolean devkit_disks_daemon_drive_inhibit_all_polling (DevkitDisksDaemon *daemon,
+ char **options,
+ DBusGMethodInvocation *context);
+
+gboolean devkit_disks_daemon_drive_uninhibit_all_polling (DevkitDisksDaemon *daemon,
+ char *cookie,
+ DBusGMethodInvocation *context);
+
G_END_DECLS
#endif /* __DEVKIT_DISKS_DAEMON_H__ */
gboolean device_is_partition_table;
gboolean device_is_removable;
gboolean device_is_media_available;
+ gboolean device_is_media_change_detected;
+ gboolean device_is_media_change_detection_inhibitable;
+ gboolean device_is_media_change_detection_inhibited;
gboolean device_is_read_only;
gboolean device_is_drive;
gboolean device_is_optical_disc;
GPtrArray *holders_objpath;
} info;
+ /* A list of current polling inhibitors (DevkitDisksInhibitor objects) */
+ GList *polling_inhibitors;
+
/* We want S.M.A.R.T. to persist over change events */
gboolean drive_smart_is_capable;
gboolean drive_smart_is_enabled;
#include "devkit-disks-device-private.h"
#include "devkit-disks-marshal.h"
#include "mounts-file.h"
+#include "devkit-disks-inhibitor.h"
+#include "poller.h"
/*--------------------------------------------------------------------------------------------------------------*/
#include "devkit-disks-device-glue.h"
static void devkit_disks_device_init (DevkitDisksDevice *seat);
static void devkit_disks_device_finalize (GObject *object);
+static void polling_inhibitor_disconnected_cb (DevkitDisksInhibitor *inhibitor,
+ DevkitDisksDevice *device);
+
static void init_info (DevkitDisksDevice *device);
static void free_info (DevkitDisksDevice *device);
static gboolean update_info (DevkitDisksDevice *device);
PROP_DEVICE_IS_PARTITION_TABLE,
PROP_DEVICE_IS_REMOVABLE,
PROP_DEVICE_IS_MEDIA_AVAILABLE,
+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTED,
+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITABLE,
+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITED,
PROP_DEVICE_IS_READ_ONLY,
PROP_DEVICE_IS_DRIVE,
PROP_DEVICE_IS_OPTICAL_DISC,
case PROP_DEVICE_IS_MEDIA_AVAILABLE:
g_value_set_boolean (value, device->priv->info.device_is_media_available);
break;
+ case PROP_DEVICE_IS_MEDIA_CHANGE_DETECTED:
+ g_value_set_boolean (value, device->priv->info.device_is_media_change_detected);
+ break;
+ case PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITABLE:
+ g_value_set_boolean (value, device->priv->info.device_is_media_change_detection_inhibitable);
+ break;
+ case PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITED:
+ g_value_set_boolean (value, device->priv->info.device_is_media_change_detection_inhibited);
+ break;
case PROP_DEVICE_IS_READ_ONLY:
g_value_set_boolean (value, device->priv->info.device_is_read_only);
break;
g_param_spec_boolean ("device-is-media-available", NULL, NULL, FALSE, G_PARAM_READABLE));
g_object_class_install_property (
object_class,
+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTED,
+ g_param_spec_boolean ("device-is-media-change-detected", NULL, NULL, FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITABLE,
+ g_param_spec_boolean ("device-is-media-change-detection-inhibitable", NULL, NULL, FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITED,
+ g_param_spec_boolean ("device-is-media-change-detection-inhibited", NULL, NULL, FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
PROP_DEVICE_IS_READ_ONLY,
g_param_spec_boolean ("device-is-read-only", NULL, NULL, FALSE, G_PARAM_READABLE));
g_object_class_install_property (
devkit_disks_device_finalize (GObject *object)
{
DevkitDisksDevice *device;
+ GList *l;
g_return_if_fail (object != NULL);
g_return_if_fail (DEVKIT_IS_DISKS_DEVICE (object));
g_ptr_array_foreach (device->priv->drive_smart_attributes, (GFunc) g_value_array_free, NULL);
g_ptr_array_free (device->priv->drive_smart_attributes, TRUE);
+ for (l = device->priv->polling_inhibitors; l != NULL; l = l->next) {
+ DevkitDisksInhibitor *inhibitor = DEVKIT_DISKS_INHIBITOR (l->data);
+ g_signal_handlers_disconnect_by_func (inhibitor, polling_inhibitor_disconnected_cb, device);
+ g_object_unref (inhibitor);
+ }
+ g_list_free (device->priv->polling_inhibitors);
+
if (device->priv->linux_md_poll_timeout_id > 0)
g_source_remove (device->priv->linux_md_poll_timeout_id);
}
}
+ /* figure out if we need to poll the device */
+ devkit_disks_device_local_update_media_detection (device);
+
ret = TRUE;
out:
return ret;
}
+/* returns TRUE if something changed */
+gboolean
+devkit_disks_device_local_update_media_detection (DevkitDisksDevice *device)
+{
+ gboolean ret;
+ gboolean old_media_change_detected;
+ gboolean old_media_change_detection_inhibitable;
+ gboolean old_media_change_detection_inhibited;
+
+ old_media_change_detected = device->priv->info.device_is_media_change_detected;
+ old_media_change_detection_inhibitable = device->priv->info.device_is_media_change_detected;
+ old_media_change_detection_inhibited = device->priv->info.device_is_media_change_detected;
+
+ if (device->priv->info.device_is_removable) {
+ /* TODO: figure out if the device supports SATA AN */
+ device->priv->info.device_is_media_change_detection_inhibitable = TRUE;
+
+ if (device->priv->polling_inhibitors != NULL ||
+ devkit_disks_daemon_local_has_polling_inhibitors (device->priv->daemon)) {
+ device->priv->info.device_is_media_change_detected = FALSE;
+ device->priv->info.device_is_media_change_detection_inhibited = TRUE;
+ } else {
+ device->priv->info.device_is_media_change_detected = TRUE;
+ device->priv->info.device_is_media_change_detection_inhibited = FALSE;
+ }
+ }
+
+ ret = (old_media_change_detected != device->priv->info.device_is_media_change_detected) ||
+ (old_media_change_detection_inhibitable != device->priv->info.device_is_media_change_detected) ||
+ (old_media_change_detection_inhibited != device->priv->info.device_is_media_change_detected);
+
+ return ret;
+}
+
+
gboolean
devkit_disks_device_local_is_busy (DevkitDisksDevice *device)
{
/*--------------------------------------------------------------------------------------------------------------*/
+
+static void
+polling_inhibitor_disconnected_cb (DevkitDisksInhibitor *inhibitor,
+ DevkitDisksDevice *device)
+{
+ device->priv->polling_inhibitors = g_list_remove (device->priv->polling_inhibitors, inhibitor);
+ g_signal_handlers_disconnect_by_func (inhibitor, polling_inhibitor_disconnected_cb, device);
+ g_object_unref (inhibitor);
+
+ update_info (device);
+ devkit_disks_daemon_local_update_poller (device->priv->daemon);
+}
+
+gboolean
+devkit_disks_device_drive_inhibit_polling (DevkitDisksDevice *device,
+ char **options,
+ DBusGMethodInvocation *context)
+{
+ DevkitDisksInhibitor *inhibitor;
+ PolKitCaller *pk_caller;
+ guint n;
+
+ if ((pk_caller = devkit_disks_damon_local_get_caller_for_context (device->priv->daemon, context)) == NULL)
+ goto out;
+
+ if (!device->priv->info.device_is_drive) {
+ throw_error (context, DEVKIT_DISKS_ERROR_NOT_DRIVE,
+ "Device is not a drive");
+ goto out;
+ }
+
+ if (!device->priv->info.device_is_media_change_detection_inhibitable) {
+ throw_error (context, DEVKIT_DISKS_ERROR_FAILED,
+ "Media detection cannot be inhibited");
+ goto out;
+ }
+
+ if (!devkit_disks_damon_local_check_auth (device->priv->daemon,
+ pk_caller,
+ "org.freedesktop.devicekit.disks.inhibit-polling",
+ context))
+ goto out;
+
+ for (n = 0; options[n] != NULL; n++) {
+ const char *option = options[n];
+ throw_error (context,
+ DEVKIT_DISKS_ERROR_INVALID_OPTION,
+ "Unknown option %s", option);
+ goto out;
+ }
+
+ inhibitor = devkit_disks_inhibitor_new (context);
+
+ device->priv->polling_inhibitors = g_list_prepend (device->priv->polling_inhibitors, inhibitor);
+ g_signal_connect (inhibitor, "disconnected", G_CALLBACK (polling_inhibitor_disconnected_cb), device);
+
+ update_info (device);
+ devkit_disks_daemon_local_update_poller (device->priv->daemon);
+
+ dbus_g_method_return (context, devkit_disks_inhibitor_get_cookie (inhibitor));
+
+out:
+ if (pk_caller != NULL)
+ polkit_caller_unref (pk_caller);
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+gboolean
+devkit_disks_device_drive_uninhibit_polling (DevkitDisksDevice *device,
+ char *cookie,
+ DBusGMethodInvocation *context)
+{
+ const gchar *sender;
+ DevkitDisksInhibitor *inhibitor;
+ GList *l;
+
+ sender = dbus_g_method_get_sender (context);
+
+ inhibitor = NULL;
+ for (l = device->priv->polling_inhibitors; l != NULL; l = l->next) {
+ DevkitDisksInhibitor *i = DEVKIT_DISKS_INHIBITOR (l->data);
+
+ if (g_strcmp0 (devkit_disks_inhibitor_get_unique_dbus_name (i), sender) == 0 &&
+ g_strcmp0 (devkit_disks_inhibitor_get_cookie (i), cookie) == 0) {
+ inhibitor = i;
+ break;
+ }
+ }
+
+ if (inhibitor == NULL) {
+ throw_error (context,
+ DEVKIT_DISKS_ERROR_FAILED,
+ "No such inhibitor");
+ goto out;
+ }
+
+ device->priv->polling_inhibitors = g_list_remove (device->priv->polling_inhibitors, inhibitor);
+ g_object_unref (inhibitor);
+
+ update_info (device);
+ devkit_disks_daemon_local_update_poller (device->priv->daemon);
+
+ dbus_g_method_return (context);
+
+ out:
+ return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+gboolean
+devkit_disks_device_drive_poll_media (DevkitDisksDevice *device,
+ DBusGMethodInvocation *context)
+{
+ PolKitCaller *pk_caller;
+
+ if ((pk_caller = devkit_disks_damon_local_get_caller_for_context (device->priv->daemon, context)) == NULL)
+ goto out;
+
+ if (!device->priv->info.device_is_drive) {
+ throw_error (context, DEVKIT_DISKS_ERROR_NOT_DRIVE,
+ "Device is not a drive");
+ goto out;
+ }
+
+ if (!devkit_disks_damon_local_check_auth (device->priv->daemon,
+ pk_caller,
+ "org.freedesktop.devicekit.disks.inhibit-polling",
+ context))
+ goto out;
+
+ poller_poll_device (device->priv->info.device_file);
+
+ dbus_g_method_return (context);
+
+out:
+ if (pk_caller != NULL)
+ polkit_caller_unref (pk_caller);
+ return TRUE;
+}
+
gboolean devkit_disks_device_local_is_busy (DevkitDisksDevice *device);
gboolean devkit_disks_device_local_partitions_are_busy (DevkitDisksDevice *device);
+gboolean devkit_disks_device_local_update_media_detection (DevkitDisksDevice *device);
+
/* exported methods */
gboolean devkit_disks_device_job_cancel (DevkitDisksDevice *device,
char **options,
DBusGMethodInvocation *context);
+gboolean devkit_disks_device_drive_inhibit_polling (DevkitDisksDevice *device,
+ char **options,
+ DBusGMethodInvocation *context);
+
+gboolean devkit_disks_device_drive_uninhibit_polling (DevkitDisksDevice *device,
+ char *cookie,
+ DBusGMethodInvocation *context);
+
+gboolean devkit_disks_device_drive_poll_media (DevkitDisksDevice *device,
+ DBusGMethodInvocation *context);
+
G_END_DECLS
#endif /* __DEVKIT_DISKS_DEVICE_H__ */
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "devkit-disks-inhibitor.h"
+
+struct DevkitDisksInhibitorPrivate
+{
+ gchar *unique_dbus_name;
+ gchar *cookie;
+};
+
+enum
+{
+ DISCONNECTED_SIGNAL,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (DevkitDisksInhibitor, devkit_disks_inhibitor, G_TYPE_OBJECT)
+
+static GList *inhibitors = NULL;
+
+static void
+devkit_disks_inhibitor_finalize (GObject *object)
+{
+ DevkitDisksInhibitor *inhibitor;
+
+ inhibitor = DEVKIT_DISKS_INHIBITOR (object);
+
+ inhibitors = g_list_remove (inhibitors, inhibitor);
+
+ g_free (inhibitor->priv->unique_dbus_name);
+ g_free (inhibitor->priv->cookie);
+
+ G_OBJECT_CLASS (devkit_disks_inhibitor_parent_class)->finalize (object);
+}
+
+static void
+devkit_disks_inhibitor_init (DevkitDisksInhibitor *inhibitor)
+{
+ inhibitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (inhibitor, DEVKIT_TYPE_DISKS_INHIBITOR, DevkitDisksInhibitorPrivate);
+}
+
+static void
+devkit_disks_inhibitor_class_init (DevkitDisksInhibitorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = devkit_disks_inhibitor_finalize;
+
+ g_type_class_add_private (klass, sizeof (DevkitDisksInhibitorPrivate));
+
+ signals[DISCONNECTED_SIGNAL] =
+ g_signal_new ("disconnected",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+DevkitDisksInhibitor *
+devkit_disks_inhibitor_new (DBusGMethodInvocation *context)
+{
+ DevkitDisksInhibitor *inhibitor;
+ static gint inhibitor_count = 0;
+
+ inhibitor = DEVKIT_DISKS_INHIBITOR (g_object_new (DEVKIT_TYPE_DISKS_INHIBITOR, NULL));
+
+ inhibitor->priv->unique_dbus_name = g_strdup (dbus_g_method_get_sender (context));
+
+ /* TODO: maybe use a real random number (if it turns out we need this to be cryptographically secure etc.) */
+ inhibitor->priv->cookie = g_strdup_printf ("devkit_disks_inhibitor_%d", inhibitor_count++);
+
+ inhibitors = g_list_prepend (inhibitors, inhibitor);
+
+ return inhibitor;
+}
+
+const gchar *
+devkit_disks_inhibitor_get_unique_dbus_name (DevkitDisksInhibitor *inhibitor)
+{
+ return inhibitor->priv->unique_dbus_name;
+}
+
+const gchar *
+devkit_disks_inhibitor_get_cookie (DevkitDisksInhibitor *inhibitor)
+{
+ return inhibitor->priv->cookie;
+}
+
+
+void devkit_disks_inhibitor_name_owner_changed (DBusMessage *message);
+
+void
+devkit_disks_inhibitor_name_owner_changed (DBusMessage *message)
+{
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
+ char *name;
+ char *new_owner;
+ char *old_owner;
+
+ if (!dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &old_owner,
+ DBUS_TYPE_STRING, &new_owner,
+ DBUS_TYPE_INVALID)) {
+
+ g_warning ("The NameOwnerChanged signal has the wrong signature.");
+ goto out;
+ }
+
+ if (strlen (new_owner) == 0) {
+ GList *l;
+
+ for (l = inhibitors; l != NULL; l = l->next) {
+ DevkitDisksInhibitor *inhibitor = DEVKIT_DISKS_INHIBITOR (l->data);
+
+ g_debug (" looking at %s", inhibitor->priv->unique_dbus_name);
+ if (g_strcmp0 (name, inhibitor->priv->unique_dbus_name) == 0) {
+ g_signal_emit_by_name (inhibitor, "disconnected");
+ }
+ }
+ }
+ }
+
+ out:
+ ;
+}
+
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __DEVKIT_DISKS_INHIBITOR_H__
+#define __DEVKIT_DISKS_INHIBITOR_H__
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define DEVKIT_TYPE_DISKS_INHIBITOR (devkit_disks_inhibitor_get_type ())
+#define DEVKIT_DISKS_INHIBITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVKIT_TYPE_DISKS_INHIBITOR, DevkitDisksInhibitor))
+#define DEVKIT_DISKS_INHIBITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DEVKIT_TYPE_DISKS_INHIBITOR, DevkitDisksInhibitorClass))
+#define DEVKIT_IS_DISKS_INHIBITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVKIT_TYPE_DISKS_INHIBITOR))
+#define DEVKIT_IS_DISKS_INHIBITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVKIT_TYPE_DISKS_INHIBITOR))
+#define DEVKIT_DISKS_INHIBITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DEVKIT_TYPE_DISKS_INHIBITOR, DevkitDisksInhibitorClass))
+
+typedef struct DevkitDisksInhibitor DevkitDisksInhibitor;
+typedef struct DevkitDisksInhibitorClass DevkitDisksInhibitorClass;
+typedef struct DevkitDisksInhibitorPrivate DevkitDisksInhibitorPrivate;
+
+struct DevkitDisksInhibitor
+{
+ GObject parent;
+ DevkitDisksInhibitorPrivate *priv;
+};
+
+struct DevkitDisksInhibitorClass
+{
+ GObjectClass parent_class;
+};
+
+GType devkit_disks_inhibitor_get_type (void) G_GNUC_CONST;
+DevkitDisksInhibitor *devkit_disks_inhibitor_new (DBusGMethodInvocation *context);
+const gchar *devkit_disks_inhibitor_get_unique_dbus_name (DevkitDisksInhibitor *inhibitor);
+const gchar *devkit_disks_inhibitor_get_cookie (DevkitDisksInhibitor *inhibitor);
+
+G_END_DECLS
+
+#endif /* __DEVKIT_DISKS_INHIBITOR_H__ */
#include <dbus/dbus-glib-lowlevel.h>
#include <devkit-gobject/devkit-gobject.h>
+#include "poller.h"
#include "devkit-disks-daemon.h"
};
ret = 1;
+ error = NULL;
/* run with a controlled path */
if (!g_setenv ("PATH", PACKAGE_LIBEXEC_DIR ":/sbin:/bin:/usr/sbin:/usr/bin", TRUE)) {
g_type_init ();
+ /* fork the polling process early */
+ if (!poller_setup (argc, argv)) {
+ goto out;
+ }
+
context = g_option_context_new ("DeviceKit Disks Daemon");
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
- error = NULL;
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
g_warning ("Couldn't connect to system bus: %s", error->message);
<!-- ************************************************************ -->
+ <method name="DriveInhibitPolling">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="options" direction="in" type="as">
+ <doc:doc><doc:summary>Inhibit options. Currently no options are recognized.</doc:summary></doc:doc>
+ </arg>
+
+ <arg name="cookie" direction="out" type="s">
+ <doc:doc><doc:summary>
+ A cookie that can be used in the
+ <doc:ref type="method" to="Device.DriveUninhibitPolling">DriveUninhibitPolling()</doc:ref> method
+ to stop inhibiting polling of the device.
+ </doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Inhibits the daemon from polling the device for media changes.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller will need one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.devicekit.disks.inhibit-polling</doc:term>
+ <doc:definition>To inhibit polling</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="&ERROR_NOT_AUTHORIZED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_FAILED;">if incoming parameters are invalid or an unknown error occured</doc:error>
+ <doc:error name="&ERROR_NOT_DRIVE;">device is not a drive</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="DriveUninhibitPolling">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+
+ <arg name="cookie" direction="in" type="s">
+ <doc:doc><doc:summary>
+ A cookie obtained from the
+ <doc:ref type="method" to="Device.DriveInhibitPolling">DriveInhibitPolling()</doc:ref> method.
+ </doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Uninhibits daemon from polling the device for media changes.
+ </doc:para>
+ </doc:description>
+ <doc:errors>
+ <doc:error name="&ERROR_FAILED;">if the given cookie is malformed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+
+ <!-- ************************************************************ -->
+
+ <method name="DrivePollMedia">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Polls the drive for media. This is typically only useful when the
+ <doc:ref type="property" to="Device:device-is-media-change-detected">device-is-media-change-detected</doc:ref> property
+ is FALSE.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller will need one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.devicekit.disks.inhibit-polling</doc:term>
+ <doc:definition>To inhibit polling</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="&ERROR_FAILED;">if an unknown error occured</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
<method name="DriveEject">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="options" direction="in" type="as">
TRUE if media is available in the device.
</doc:para></doc:description></doc:doc>
</property>
+ <property name="device-is-media-change-detected" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ TRUE if media changes are detected.
+ </doc:para></doc:description></doc:doc>
+ </property>
+ <property name="device-is-media-change-detection-inhibitable" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ TRUE if it is possible to inhibit media detection on the device (to avoid keeping the device in a high power state).
+ </doc:para></doc:description></doc:doc>
+ </property>
+ <property name="device-is-media-change-detection-inhibited" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ TRUE if media detection is inhibited (to avoid keeping the device in a high power state).
+ </doc:para></doc:description></doc:doc>
+ </property>
<property name="device-is-read-only" type="b" access="read">
<doc:doc><doc:description><doc:para>
TRUE if the device read-only.
<!-- ************************************************************ -->
+ <method name="DriveInhibitAllPolling">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="options" direction="in" type="as">
+ <doc:doc><doc:summary>Inhibit options. Currently no options are recognized.</doc:summary></doc:doc>
+ </arg>
+
+ <arg name="cookie" direction="out" type="s">
+ <doc:doc><doc:summary>
+ A cookie that can be used in the
+ <doc:ref type="method" to="Disks.DriveUninhibitAllPolling">DriveUninhibitAllPolling()</doc:ref> method
+ to stop inhibiting polling of all devices.
+ </doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Inhibits the daemon from polling devices for media changes.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller will need one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.devicekit.disks.inhibit-polling</doc:term>
+ <doc:definition>To inhibit polling</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="&ERROR_NOT_AUTHORIZED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_FAILED;">if incoming parameters are invalid or an unknown error occured</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="DriveUninhibitAllPolling">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+
+ <arg name="cookie" direction="in" type="s">
+ <doc:doc><doc:summary>
+ A cookie obtained from the
+ <doc:ref type="method" to="Disks.DriveInhibitAllPolling">DriveInhibitAllPolling()</doc:ref> method.
+ </doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Uninhibits daemon from polling devices for media changes.
+ </doc:para>
+ </doc:description>
+ <doc:errors>
+ <doc:error name="&ERROR_FAILED;">if the given cookie is malformed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
<method name="LinuxMdStart">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="components" direction="in" type="ao">
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david@fubar.dk>
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "poller.h"
+#include "devkit-disks-device.h"
+#include "devkit-disks-device-private.h"
+
+static gchar **poller_devices_to_poll = NULL;
+
+static guint poller_timeout_id = 0;
+
+void
+poller_poll_device (const gchar *device_file)
+{
+ gboolean is_cdrom;
+ int fd;
+
+ /* the device file is the canonical device file from udev */
+ is_cdrom = (g_str_has_prefix (device_file, "/dev/sr") || g_str_has_prefix (device_file, "/dev/scd"));
+
+ g_debug ("polling '%s'", device_file);
+
+ if (is_cdrom) {
+ /* optical drives need special care
+ *
+ * - use O_NONBLOCK to avoid closing the door
+ * - use O_EXCL to avoid interferring with cd burning software / audio playback / etc
+ */
+ fd = open (device_file, O_RDONLY | O_NONBLOCK | O_EXCL);
+ if (fd != -1) {
+ close (fd);
+ }
+
+ } else {
+ fd = open (device_file, O_RDONLY);
+ if (fd != -1) {
+ close (fd);
+ }
+ }
+}
+
+
+static gboolean
+poller_timeout_cb (gpointer user_data)
+{
+ guint n;
+
+ for (n = 0; poller_devices_to_poll != NULL && poller_devices_to_poll[n] != NULL; n++) {
+ const gchar *device_file = poller_devices_to_poll[n];
+
+ poller_poll_device (device_file);
+ }
+
+ /* don't remove the source */
+ return TRUE;
+}
+
+static gboolean
+poller_have_data (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ gchar *line;
+ gsize line_length;
+ GError *error;
+ gint status;
+
+ error = NULL;
+
+ again:
+ status = g_io_channel_read_line (channel,
+ &line,
+ &line_length,
+ NULL,
+ &error);
+ if (error != NULL) {
+ g_warning ("Error reading line from daemon: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ if (status == G_IO_STATUS_AGAIN) {
+ goto again;
+ }
+
+ //g_debug ("polling process read '%s'", line);
+
+ if (line[line_length - 1] == '\n')
+ line[line_length - 1] = '\0';
+
+ if (line[line_length - 2] == ' ')
+ line[line_length - 2] = '\0';
+
+ g_strfreev (poller_devices_to_poll);
+ poller_devices_to_poll = g_strsplit (line, " ", 0);
+
+ if (g_strv_length (poller_devices_to_poll) == 0) {
+ if (poller_timeout_id > 0) {
+ g_source_remove (poller_timeout_id);
+ poller_timeout_id = 0;
+ }
+
+ g_print ("poller: not polling any devices\n");
+ } else {
+ g_print ("poller: polling %s", line);
+
+ if (poller_timeout_id == 0) {
+ poller_timeout_id = g_timeout_add_seconds (2, poller_timeout_cb, NULL);
+ }
+ }
+
+ g_free (line);
+
+ out:
+ /* keep the IOChannel around */
+ return TRUE;
+}
+
+static void
+poller_run (gint fd)
+{
+ GMainLoop *loop;
+ GIOChannel *io_channel;
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ io_channel = g_io_channel_unix_new (fd);
+ g_io_channel_set_flags (io_channel, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_add_watch (io_channel, G_IO_IN, poller_have_data, NULL);
+
+ g_main_loop_run (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gint poller_daemon_write_end_fd;
+
+gboolean
+poller_setup (int argc, char *argv[])
+{
+ gint pipefds[2];
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (pipe (pipefds) != 0) {
+ g_warning ("Couldn't set up polling process, pipe() failed: %m");
+ goto out;
+ }
+
+ switch (fork ()) {
+ case 0:
+ /* child */
+ close (pipefds[1]); /* close write end */
+ poller_run (pipefds[0]);
+ break;
+
+ default:
+ /* parent */
+ close (pipefds[0]); /* close read end */
+ poller_daemon_write_end_fd = pipefds[1];
+ break;
+
+ case -1:
+ g_warning ("Couldn't set up polling process, fork() failed: %m");
+ goto out;
+ break;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+void
+poller_set_devices (GList *devices)
+{
+ GList *l;
+ gchar **device_array;
+ guint n;
+ gchar *devices_to_poll;
+ static gchar *devices_currently_polled = NULL;
+
+ device_array = g_new0 (gchar *, g_list_length (devices) + 2);
+
+ for (l = devices, n = 0; l != NULL; l = l->next) {
+ DevkitDisksDevice *device = DEVKIT_DISKS_DEVICE (l->data);
+
+ device_array[n++] = device->priv->info.device_file;
+ }
+
+ g_qsort_with_data (device_array, n, sizeof (gchar *), (GCompareDataFunc) g_strcmp0, NULL);
+
+ device_array[n] = "\n";
+
+ devices_to_poll = g_strjoinv (" ", device_array);
+ g_free (device_array);
+
+ if (g_strcmp0 (devices_to_poll, devices_currently_polled) != 0) {
+ g_free (devices_currently_polled);
+ devices_currently_polled = devices_to_poll;
+
+ write (poller_daemon_write_end_fd, devices_currently_polled, strlen (devices_currently_polled));
+ //g_debug ("Wanna poll: '%s'", devices_currently_polled);
+ } else {
+ g_free (devices_to_poll);
+ }
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __POLLER_H__
+#define __POLLER_H__
+
+#include <devkit-disks-device.h>
+
+gboolean poller_setup (int argc, char *argv[]);
+void poller_set_devices (GList *devices);
+void poller_poll_device (const gchar *device_file);
+
+
+#endif /* __POLLER_H */
if [ "${COMP_WORDS[$(($COMP_CWORD - 1))]}" = "--show-info" ] ; then
COMPREPLY=($(compgen -W "$(devkit-disks --enumerate)" -- $cur))
+ elif [ "${COMP_WORDS[$(($COMP_CWORD - 1))]}" = "--inhibit-polling" ] ; then
+ COMPREPLY=($(compgen -W "$(devkit-disks --enumerate)" -- $cur))
elif [ "${COMP_WORDS[$(($COMP_CWORD - 1))]}" = "--mount" ] ; then
COMPREPLY=($(compgen -W "$(devkit-disks --enumerate)" -- $cur))
elif [ "${COMP_WORDS[$(($COMP_CWORD - 1))]}" = "--unmount" ] ; then
elif [ "${COMP_WORDS[$(($COMP_CWORD - 1))]}" = "--create-fs" ] ; then
COMPREPLY=($(compgen -W "$(devkit-disks --enumerate)" -- $cur))
else
- COMPREPLY=($(IFS=: compgen -S' ' -W "--inhibit:--enumerate:--monitor:--monitor-detail:--show-info:--help:--mount:--mount-fstype:--mount-options:--unmount:--unmount-options:--create-fs:--create-fs-type:--create-fs-options" -- $cur))
+ COMPREPLY=($(IFS=: compgen -S' ' -W "--inhibit-polling:--inhibit-all-polling:--enumerate:--monitor:--monitor-detail:--show-info:--help:--mount:--mount-fstype:--mount-options:--unmount:--unmount-options:--create-fs:--create-fs-type:--create-fs-options" -- $cur))
fi
}
static gboolean opt_monitor = FALSE;
static gboolean opt_monitor_detail = FALSE;
static char *opt_show_info = NULL;
+static char *opt_inhibit_polling = NULL;
+static gboolean opt_inhibit_all_polling = FALSE;
static char *opt_mount = NULL;
static char *opt_mount_fstype = NULL;
static char *opt_mount_options = NULL;
{
if (job_in_progress) {
if (job_num_tasks > 0) {
- g_print (" job underway: %s: %d/%d tasks (%s",
+ g_print (" job underway: %s: %d/%d tasks (%s",
job_id,
job_cur_task + 1,
job_num_tasks,
g_print (", initiated by uid %d", job_initiated_by_uid);
g_print (")\n");
} else {
- g_print (" job underway: %s: unknown progress", job_id);
+ g_print (" job underway: %s: unknown progress", job_id);
if (job_is_cancellable)
g_print (", cancellable");
g_print (", initiated by uid %d", job_initiated_by_uid);
g_print ("\n");
}
} else {
- g_print (" job underway: no\n");
+ g_print (" job underway: no\n");
}
}
gboolean device_is_partition_table;
gboolean device_is_removable;
gboolean device_is_media_available;
+ gboolean device_is_media_change_detected;
+ gboolean device_is_media_change_detection_inhibitable;
+ gboolean device_is_media_change_detection_inhibited;
gboolean device_is_read_only;
gboolean device_is_drive;
gboolean device_is_optical_disc;
props->device_is_removable = g_value_get_boolean (value);
else if (strcmp (key, "device-is-media-available") == 0)
props->device_is_media_available = g_value_get_boolean (value);
+ else if (strcmp (key, "device-is-media-change-detected") == 0)
+ props->device_is_media_change_detected = g_value_get_boolean (value);
+ else if (strcmp (key, "device-is-media-change-detection-inhibitable") == 0)
+ props->device_is_media_change_detection_inhibitable = g_value_get_boolean (value);
+ else if (strcmp (key, "device-is-media-change-detection-inhibited") == 0)
+ props->device_is_media_change_detection_inhibited = g_value_get_boolean (value);
else if (strcmp (key, "device-is-read-only") == 0)
props->device_is_read_only = g_value_get_boolean (value);
else if (strcmp (key, "device-is-drive") == 0)
return;
g_print ("Showing information for %s\n", object_path);
- g_print (" native-path: %s\n", props->native_path);
- g_print (" device-file: %s\n", props->device_file);
+ g_print (" native-path: %s\n", props->native_path);
+ g_print (" device-file: %s\n", props->device_file);
for (n = 0; props->device_file_by_id[n] != NULL; n++)
- g_print (" by-id: %s\n", (char *) props->device_file_by_id[n]);
+ g_print (" by-id: %s\n", (char *) props->device_file_by_id[n]);
for (n = 0; props->device_file_by_path[n] != NULL; n++)
- g_print (" by-path: %s\n", (char *) props->device_file_by_path[n]);
- g_print (" system internal: %d\n", props->device_is_system_internal);
- g_print (" removable: %d\n", props->device_is_removable);
- g_print (" has media: %d\n", props->device_is_media_available);
- g_print (" is read only: %d\n", props->device_is_read_only);
- g_print (" is mounted: %d\n", props->device_is_mounted);
- g_print (" is busy: %d\n", props->device_is_busy);
- g_print (" mount path: %s\n", props->device_mount_path);
- g_print (" mounted by uid: %d\n", props->device_mounted_by_uid);
- g_print (" size: %" G_GUINT64_FORMAT "\n", props->device_size);
- g_print (" block size: %" G_GUINT64_FORMAT "\n", props->device_block_size);
+ g_print (" by-path: %s\n", (char *) props->device_file_by_path[n]);
+ g_print (" system internal: %d\n", props->device_is_system_internal);
+ g_print (" removable: %d\n", props->device_is_removable);
+ g_print (" has media: %d\n", props->device_is_media_available);
+ g_print (" detects change: %d\n", props->device_is_media_change_detected);
+ g_print (" detection inhibitable: %d\n", props->device_is_media_change_detection_inhibitable);
+ g_print (" detection inhibited: %d\n", props->device_is_media_change_detection_inhibited);
+ g_print (" is read only: %d\n", props->device_is_read_only);
+ g_print (" is mounted: %d\n", props->device_is_mounted);
+ g_print (" is busy: %d\n", props->device_is_busy);
+ g_print (" mount path: %s\n", props->device_mount_path);
+ g_print (" mounted by uid: %d\n", props->device_mounted_by_uid);
+ g_print (" size: %" G_GUINT64_FORMAT "\n", props->device_size);
+ g_print (" block size: %" G_GUINT64_FORMAT "\n", props->device_block_size);
print_job (props->job_in_progress,
props->job_id,
props->job_cur_task,
props->job_cur_task_id,
props->job_cur_task_percentage);
- g_print (" usage: %s\n", props->id_usage);
- g_print (" type: %s\n", props->id_type);
- g_print (" version: %s\n", props->id_version);
- g_print (" uuid: %s\n", props->id_uuid);
- g_print (" label: %s\n", props->id_label);
+ g_print (" usage: %s\n", props->id_usage);
+ g_print (" type: %s\n", props->id_type);
+ g_print (" version: %s\n", props->id_version);
+ g_print (" uuid: %s\n", props->id_uuid);
+ g_print (" label: %s\n", props->id_label);
if (props->device_is_linux_md_component) {
struct tm *time_tm;
time_t time;
strftime (time_buf, sizeof time_buf, "%c", time_tm);
g_print (" linux md component:\n");
- g_print (" RAID level: %s\n", props->linux_md_component_level);
- g_print (" num comp: %d\n", props->linux_md_component_num_raid_devices);
- g_print (" uuid: %s\n", props->linux_md_component_uuid);
- g_print (" home host: %s\n", props->linux_md_component_home_host);
- g_print (" name: %s\n", props->linux_md_component_name);
- g_print (" version: %s\n", props->linux_md_component_version);
- g_print (" update time: %" G_GUINT64_FORMAT " (%s)\n", props->linux_md_component_update_time, time_buf);
- g_print (" events: %" G_GUINT64_FORMAT "\n", props->linux_md_component_events);
+ g_print (" RAID level: %s\n", props->linux_md_component_level);
+ g_print (" num comp: %d\n", props->linux_md_component_num_raid_devices);
+ g_print (" uuid: %s\n", props->linux_md_component_uuid);
+ g_print (" home host: %s\n", props->linux_md_component_home_host);
+ g_print (" name: %s\n", props->linux_md_component_name);
+ g_print (" version: %s\n", props->linux_md_component_version);
+ g_print (" update time: %" G_GUINT64_FORMAT " (%s)\n", props->linux_md_component_update_time, time_buf);
+ g_print (" events: %" G_GUINT64_FORMAT "\n", props->linux_md_component_events);
}
if (props->device_is_linux_md) {
g_print (" linux md:\n");
- g_print (" RAID level: %s\n", props->linux_md_level);
- g_print (" uuid: %s\n", props->linux_md_uuid);
- g_print (" home host: %s\n", props->linux_md_home_host);
- g_print (" name: %s\n", props->linux_md_name);
- g_print (" num comp: %d\n", props->linux_md_num_raid_devices);
- g_print (" version: %s\n", props->linux_md_version);
- g_print (" degraded: %d\n", props->linux_md_is_degraded);
- g_print (" sync action: %s\n", props->linux_md_sync_action);
+ g_print (" RAID level: %s\n", props->linux_md_level);
+ g_print (" uuid: %s\n", props->linux_md_uuid);
+ g_print (" home host: %s\n", props->linux_md_home_host);
+ g_print (" name: %s\n", props->linux_md_name);
+ g_print (" num comp: %d\n", props->linux_md_num_raid_devices);
+ g_print (" version: %s\n", props->linux_md_version);
+ g_print (" degraded: %d\n", props->linux_md_is_degraded);
+ g_print (" sync action: %s\n", props->linux_md_sync_action);
if (strcmp (props->linux_md_sync_action, "idle") != 0) {
- g_print (" complete: %3.01f%%\n", props->linux_md_sync_percentage);
- g_print (" speed: %" G_GINT64_FORMAT " bytes/sec\n", props->linux_md_sync_speed);
+ g_print (" complete: %3.01f%%\n", props->linux_md_sync_percentage);
+ g_print (" speed: %" G_GINT64_FORMAT " bytes/sec\n", props->linux_md_sync_speed);
}
g_print (" slaves:\n");
for (n = 0; props->linux_md_slaves[n] != NULL; n++)
- g_print (" %s (state: %s)\n",
+ g_print (" %s (state: %s)\n",
props->linux_md_slaves[n], props->linux_md_slaves_state[n]);
}
if (props->device_is_luks) {
g_print (" luks device:\n");
- g_print (" holder: %s\n", props->luks_holder);
+ g_print (" holder: %s\n", props->luks_holder);
}
if (props->device_is_luks_cleartext) {
g_print (" cleartext luks device:\n");
- g_print (" backed by: %s\n", props->luks_cleartext_slave);
- g_print (" unlocked by: uid %d\n", props->luks_cleartext_unlocked_by_uid);
+ g_print (" backed by: %s\n", props->luks_cleartext_slave);
+ g_print (" unlocked by: uid %d\n", props->luks_cleartext_unlocked_by_uid);
}
if (props->device_is_partition_table) {
g_print (" partition table:\n");
- g_print (" scheme: %s\n", props->partition_table_scheme);
- g_print (" count: %d\n", props->partition_table_count);
- g_print (" max number: %d\n", props->partition_table_max_number);
+ g_print (" scheme: %s\n", props->partition_table_scheme);
+ g_print (" count: %d\n", props->partition_table_count);
+ g_print (" max number: %d\n", props->partition_table_max_number);
}
if (props->device_is_partition) {
g_print (" partition:\n");
- g_print (" part of: %s\n", props->partition_slave);
- g_print (" scheme: %s\n", props->partition_scheme);
- g_print (" number: %d\n", props->partition_number);
- g_print (" type: %s\n", props->partition_type);
- g_print (" flags: ");
+ g_print (" part of: %s\n", props->partition_slave);
+ g_print (" scheme: %s\n", props->partition_scheme);
+ g_print (" number: %d\n", props->partition_number);
+ g_print (" type: %s\n", props->partition_type);
+ g_print (" flags: ");
for (n = 0; props->partition_flags[n] != NULL; n++)
g_print (" %s", (char *) props->partition_flags[n]);
g_print ("\n");
- g_print (" offset: %" G_GINT64_FORMAT "\n", props->partition_offset);
- g_print (" size: %" G_GINT64_FORMAT "\n", props->partition_size);
- g_print (" label: %s\n", props->partition_label);
- g_print (" uuid: %s\n", props->partition_uuid);
+ g_print (" offset: %" G_GINT64_FORMAT "\n", props->partition_offset);
+ g_print (" size: %" G_GINT64_FORMAT "\n", props->partition_size);
+ g_print (" label: %s\n", props->partition_label);
+ g_print (" uuid: %s\n", props->partition_uuid);
}
if (props->device_is_optical_disc) {
g_print (" optical disc:\n");
- g_print (" recordable: %d\n", props->optical_disc_is_recordable);
- g_print (" rewritable: %d\n", props->optical_disc_is_rewritable);
- g_print (" blank: %d\n", props->optical_disc_is_blank);
- g_print (" appendable: %d\n", props->optical_disc_is_appendable);
- g_print (" closed: %d\n", props->optical_disc_is_closed);
- g_print (" has audio: %d\n", props->optical_disc_has_audio);
- g_print (" num tracks: %d\n", props->optical_disc_num_tracks);
- g_print (" num sessions: %d\n", props->optical_disc_num_sessions);
+ g_print (" recordable: %d\n", props->optical_disc_is_recordable);
+ g_print (" rewritable: %d\n", props->optical_disc_is_rewritable);
+ g_print (" blank: %d\n", props->optical_disc_is_blank);
+ g_print (" appendable: %d\n", props->optical_disc_is_appendable);
+ g_print (" closed: %d\n", props->optical_disc_is_closed);
+ g_print (" has audio: %d\n", props->optical_disc_has_audio);
+ g_print (" num tracks: %d\n", props->optical_disc_num_tracks);
+ g_print (" num sessions: %d\n", props->optical_disc_num_sessions);
}
if (props->device_is_drive) {
g_print (" drive:\n");
- g_print (" vendor: %s\n", props->drive_vendor);
- g_print (" model: %s\n", props->drive_model);
- g_print (" revision: %s\n", props->drive_revision);
- g_print (" serial: %s\n", props->drive_serial);
- g_print (" ejectable: %d\n", props->drive_is_media_ejectable);
- g_print (" require eject: %d\n", props->drive_requires_eject);
- g_print (" media: %s\n", props->drive_media);
- g_print (" compat: ");
+ g_print (" vendor: %s\n", props->drive_vendor);
+ g_print (" model: %s\n", props->drive_model);
+ g_print (" revision: %s\n", props->drive_revision);
+ g_print (" serial: %s\n", props->drive_serial);
+ g_print (" ejectable: %d\n", props->drive_is_media_ejectable);
+ g_print (" require eject: %d\n", props->drive_requires_eject);
+ g_print (" media: %s\n", props->drive_media);
+ g_print (" compat: ");
for (n = 0; props->drive_media_compatibility[n] != NULL; n++)
g_print (" %s", (char *) props->drive_media_compatibility[n]);
g_print ("\n");
if (props->drive_connection_interface == NULL || strlen (props->drive_connection_interface) == 0)
g_print (" interface: (unknown)\n");
else
- g_print (" interface: %s\n", props->drive_connection_interface);
+ g_print (" interface: %s\n", props->drive_connection_interface);
if (props->drive_connection_speed == 0)
- g_print (" if speed: (unknown)\n");
+ g_print (" if speed: (unknown)\n");
else
- g_print (" if speed: %" G_GINT64_FORMAT " bits/s\n", props->drive_connection_speed);
+ g_print (" if speed: %" G_GINT64_FORMAT " bits/s\n", props->drive_connection_speed);
if (!props->drive_smart_is_capable) {
- g_print (" S.M.A.R.T.: not capable\n");
+ g_print (" S.M.A.R.T.: not capable\n");
} else if (props->drive_smart_time_collected == 0) {
- g_print (" S.M.A.R.T.: not collected\n");
+ g_print (" S.M.A.R.T.: not collected\n");
} else {
struct tm *time_tm;
time_t time;
time_tm = localtime (&time);
strftime (time_buf, sizeof time_buf, "%c", time_tm);
- g_print (" S.M.A.R.T.: Information collected at %s\n", time_buf);
+ g_print (" S.M.A.R.T.: Information collected at %s\n", time_buf);
if (!props->drive_smart_is_capable) {
- g_print (" not capable\n");
+ g_print (" not capable\n");
} else if (!props->drive_smart_is_enabled) {
- g_print (" not enabled\n");
+ g_print (" not enabled\n");
} else {
- g_print (" assessment: %s\n",
+ g_print (" assessment: %s\n",
props->drive_smart_is_failing ? "FAILING" : "Passed");
- g_print (" temperature: %g° C / %g° F\n",
+ g_print (" temperature: %g° C / %g° F\n",
props->drive_smart_temperature,
9 * props->drive_smart_temperature / 5 + 32);
- g_print (" powered on: %" G_GUINT64_FORMAT " hours\n", props->drive_smart_time_powered_on / 3600);
+ g_print (" powered on: %" G_GUINT64_FORMAT " hours\n", props->drive_smart_time_powered_on / 3600);
//g_print (" 196 Reallocated_Event_Count 0x0032 100 100 0 443023360\n",
#if 0
int m;
device_properties_free (props);
}
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+do_inhibit_polling (const char *object_path)
+{
+ char *cookie;
+ DBusGProxy *proxy;
+ GError *error;
+ char **options;
+
+ options = NULL;
+
+ proxy = dbus_g_proxy_new_for_name (bus,
+ "org.freedesktop.DeviceKit.Disks",
+ object_path,
+ "org.freedesktop.DeviceKit.Disks.Device");
+
+ error = NULL;
+ if (!org_freedesktop_DeviceKit_Disks_Device_drive_inhibit_polling (proxy,
+ (const char **) options,
+ &cookie,
+ &error)) {
+ g_print ("Inhibit polling failed: %s\n", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ g_print ("Inhibiting polling on %s. Press Ctrl+C to exit.\n", object_path);
+ while (TRUE)
+ sleep (100000000);
+
+ g_free (cookie);
+out:
+ ;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+
+static void
+do_inhibit_all_polling (void)
+{
+ char *cookie;
+ DBusGProxy *proxy;
+ GError *error;
+ char **options;
+
+ options = NULL;
+
+ proxy = dbus_g_proxy_new_for_name (bus,
+ "org.freedesktop.DeviceKit.Disks",
+ "/",
+ "org.freedesktop.DeviceKit.Disks");
+
+ error = NULL;
+ if (!org_freedesktop_DeviceKit_Disks_drive_inhibit_all_polling (proxy,
+ (const char **) options,
+ &cookie,
+ &error)) {
+ g_print ("Inhibit all polling failed: %s\n", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ g_print ("Inhibiting polling on all devices. Press Ctrl+C to exit.\n");
+ while (TRUE)
+ sleep (100000000);
+
+ g_free (cookie);
+out:
+ ;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
int
main (int argc, char **argv)
{
{ "monitor", 0, 0, G_OPTION_ARG_NONE, &opt_monitor, "Monitor activity from the disk daemon", NULL },
{ "monitor-detail", 0, 0, G_OPTION_ARG_NONE, &opt_monitor_detail, "Monitor with detail", NULL },
{ "show-info", 0, 0, G_OPTION_ARG_STRING, &opt_show_info, "Show information about object path", NULL },
+ { "inhibit-polling", 0, 0, G_OPTION_ARG_STRING, &opt_inhibit_polling, "Inhibit polling", NULL },
+ { "inhibit-all-polling", 0, 0, G_OPTION_ARG_NONE, &opt_inhibit_all_polling, "Inhibit all polling", NULL },
{ "mount", 0, 0, G_OPTION_ARG_STRING, &opt_mount, "Mount the device given by the object path", NULL },
{ "mount-fstype", 0, 0, G_OPTION_ARG_STRING, &opt_mount_fstype, "Specify file system type", NULL },
goto out;
} else if (opt_show_info != NULL) {
do_show_info (opt_show_info);
+ } else if (opt_inhibit_polling != NULL) {
+ do_inhibit_polling (opt_inhibit_polling);
+ } else if (opt_inhibit_all_polling) {
+ do_inhibit_all_polling ();
} else if (opt_mount != NULL) {
do_mount (opt_mount, opt_mount_fstype, opt_mount_options);
} else if (opt_unmount != NULL) {