</varlistentry>
<varlistentry>
+ <term>
+ <option>--inhibit</option>
+ <arg><option>-- program arg ...</option></arg>
+ </term>
+ <listitem>
+ <para>
+ Inhibits clients from invoking methods on the daemon of
+ the daemon that require authorization (all methods will
+ return the
+ <literal>org.freedesktop.DeviceKit.Disks.Error.Inhibited</literal> error) if
+ the caller is not the super user. This is typically used
+ by OS installers and other programs that expects full
+ control of the system, specifically to avoid automounting
+ devices. Only the super user can do this.
+ </para>
+ <para>
+ If no program is given,
+ polling is inhibited until Ctrl+C is pressed. Otherwise the program is spawned and the polling
+ is only inhibited until the program terminates.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--help</option></term>
<listitem>
<para>
{
PROP_0,
PROP_DAEMON_VERSION,
+ PROP_DAEMON_IS_INHIBITED,
PROP_SUPPORTS_LUKS_DEVICES,
PROP_KNOWN_FILESYSTEMS,
};
DevkitDisksLogger *logger;
GList *polling_inhibitors;
+
+ GList *inhibitors;
};
static void devkit_disks_daemon_class_init (DevkitDisksDaemonClass *klass);
static void daemon_polling_inhibitor_disconnected_cb (DevkitDisksInhibitor *inhibitor,
DevkitDisksDaemon *daemon);
+static void daemon_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_DISKS_TYPE_DAEMON, DevkitDisksDaemonPrivate))
static const GEnumValue values[] =
{
ENUM_ENTRY (DEVKIT_DISKS_ERROR_FAILED, "Failed"),
+ ENUM_ENTRY (DEVKIT_DISKS_ERROR_INHIBITED, "Inhibited"),
ENUM_ENTRY (DEVKIT_DISKS_ERROR_BUSY, "Busy"),
ENUM_ENTRY (DEVKIT_DISKS_ERROR_CANCELLED, "Cancelled"),
ENUM_ENTRY (DEVKIT_DISKS_ERROR_INVALID_OPTION, "InvalidOption"),
g_value_set_string (value, VERSION);
break;
+ case PROP_DAEMON_IS_INHIBITED:
+ g_value_set_boolean (value, (daemon->priv->inhibitors != NULL));
+ break;
+
case PROP_SUPPORTS_LUKS_DEVICES:
/* TODO: probably Linux only */
g_value_set_boolean (value, TRUE);
g_object_class_install_property (
object_class,
+ PROP_DAEMON_IS_INHIBITED,
+ g_param_spec_boolean ("daemon-is-inhibited", NULL, NULL, FALSE, G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
PROP_SUPPORTS_LUKS_DEVICES,
g_param_spec_boolean ("supports-luks-devices", NULL, NULL, FALSE, G_PARAM_READABLE));
}
g_list_free (daemon->priv->polling_inhibitors);
+ for (l = daemon->priv->inhibitors; l != NULL; l = l->next) {
+ DevkitDisksInhibitor *inhibitor = DEVKIT_DISKS_INHIBITOR (l->data);
+ g_signal_handlers_disconnect_by_func (inhibitor, daemon_inhibitor_disconnected_cb, daemon);
+ g_object_unref (inhibitor);
+ }
+ g_list_free (daemon->priv->inhibitors);
+
G_OBJECT_CLASS (devkit_disks_daemon_parent_class)->finalize (object);
}
return pk_caller;
}
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static gboolean
+throw_error (DBusGMethodInvocation *context, int error_code, const char *format, ...)
+{
+ GError *error;
+ va_list args;
+ char *message;
+
+ va_start (args, format);
+ message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ error = g_error_new (DEVKIT_DISKS_ERROR,
+ error_code,
+ "%s", message);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ g_free (message);
+ return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
gboolean
devkit_disks_damon_local_check_auth (DevkitDisksDaemon *daemon,
PolKitCaller *pk_caller,
ret = FALSE;
+ if (daemon->priv->inhibitors != NULL) {
+ uid_t uid;
+
+ uid = (uid_t) -1;
+ if (!polkit_caller_get_uid (pk_caller, &uid) || uid != 0) {
+ throw_error (context,
+ DEVKIT_DISKS_ERROR_INHIBITED,
+ "Daemon is being inhibited");
+ }
+ goto out;
+ }
+
pk_action = polkit_action_new ();
polkit_action_set_action_id (pk_action, action_id);
pk_result = polkit_context_is_caller_authorized (daemon->priv->pk_context,
dbus_error_free (&d_error);
}
polkit_action_unref (pk_action);
+
+ out:
return ret;
}
}
/*--------------------------------------------------------------------------------------------------------------*/
-
-static gboolean
-throw_error (DBusGMethodInvocation *context, int error_code, const char *format, ...)
-{
- GError *error;
- va_list args;
- char *message;
-
- va_start (args, format);
- message = g_strdup_vprintf (format, args);
- va_end (args);
-
- error = g_error_new (DEVKIT_DISKS_ERROR,
- error_code,
- "%s", message);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- g_free (message);
- return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
/* exported methods */
static void
}
/*--------------------------------------------------------------------------------------------------------------*/
+
+static void
+daemon_inhibitor_disconnected_cb (DevkitDisksInhibitor *inhibitor,
+ DevkitDisksDaemon *daemon)
+{
+ daemon->priv->inhibitors = g_list_remove (daemon->priv->inhibitors, inhibitor);
+ g_signal_handlers_disconnect_by_func (inhibitor, daemon_inhibitor_disconnected_cb, daemon);
+ g_object_unref (inhibitor);
+}
+
+gboolean
+devkit_disks_daemon_local_has_inhibitors (DevkitDisksDaemon *daemon)
+{
+ return daemon->priv->inhibitors != NULL;
+}
+
+gboolean
+devkit_disks_daemon_inhibit (DevkitDisksDaemon *daemon,
+ DBusGMethodInvocation *context)
+{
+ DevkitDisksInhibitor *inhibitor;
+ PolKitCaller *pk_caller;
+ uid_t uid;
+
+
+ if ((pk_caller = devkit_disks_damon_local_get_caller_for_context (daemon, context)) == NULL)
+ goto out;
+
+ uid = (uid_t) -1;
+ if (!polkit_caller_get_uid (pk_caller, &uid) || uid != 0) {
+ throw_error (context,
+ DEVKIT_DISKS_ERROR_FAILED,
+ "Only uid 0 is authorized to inhibit the daemon");
+ goto out;
+ }
+
+ inhibitor = devkit_disks_inhibitor_new (context);
+
+ daemon->priv->inhibitors = g_list_prepend (daemon->priv->inhibitors, inhibitor);
+ g_signal_connect (inhibitor, "disconnected", G_CALLBACK (daemon_inhibitor_disconnected_cb), 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_uninhibit (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->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->inhibitors = g_list_remove (daemon->priv->inhibitors, inhibitor);
+ g_object_unref (inhibitor);
+
+ dbus_g_method_return (context);
+
+ out:
+ return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
typedef enum
{
DEVKIT_DISKS_ERROR_FAILED,
+ DEVKIT_DISKS_ERROR_INHIBITED,
DEVKIT_DISKS_ERROR_BUSY,
DEVKIT_DISKS_ERROR_CANCELLED,
DEVKIT_DISKS_ERROR_INVALID_OPTION,
gboolean devkit_disks_daemon_local_has_polling_inhibitors (DevkitDisksDaemon *daemon);
+gboolean devkit_disks_daemon_local_has_inhibitors (DevkitDisksDaemon *daemon);
+
DevkitDisksLogger *devkit_disks_daemon_local_get_logger (DevkitDisksDaemon *daemon);
DevkitDisksMountMonitor *devkit_disks_daemon_local_get_mount_monitor (DevkitDisksDaemon *daemon);
char *cookie,
DBusGMethodInvocation *context);
+gboolean devkit_disks_daemon_inhibit (DevkitDisksDaemon *daemon,
+ DBusGMethodInvocation *context);
+
+gboolean devkit_disks_daemon_uninhibit (DevkitDisksDaemon *daemon,
+ char *cookie,
+ DBusGMethodInvocation *context);
+
G_END_DECLS
#endif /* __DEVKIT_DISKS_DAEMON_H__ */
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" [
<!ENTITY ERROR_FAILED "org.freedesktop.DeviceKit.Disks.Error.Failed">
+ <!ENTITY ERROR_INHIBITED "org.freedesktop.DeviceKit.Disks.Error.Inhibited">
<!ENTITY ERROR_BUSY "org.freedesktop.DeviceKit.Disks.Error.Busy">
<!ENTITY ERROR_CANCELLED "org.freedesktop.DeviceKit.Disks.Error.Cancelled">
<!ENTITY ERROR_INVALID_OPTION "org.freedesktop.DeviceKit.Disks.Error.InvalidOption">
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" [
<!ENTITY ERROR_FAILED "org.freedesktop.DeviceKit.Disks.Error.Failed">
+ <!ENTITY ERROR_INHIBITED "org.freedesktop.DeviceKit.Disks.Error.Inhibited">
<!ENTITY ERROR_BUSY "org.freedesktop.DeviceKit.Disks.Error.Busy">
<!ENTITY ERROR_CANCELLED "org.freedesktop.DeviceKit.Disks.Error.Cancelled">
<!ENTITY ERROR_INVALID_OPTION "org.freedesktop.DeviceKit.Disks.Error.InvalidOption">
<!-- ************************************************************ -->
+ <method name="Inhibit">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <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.Uninhibit">Uninhibit()</doc:ref> method.
+ to stop inhibiting the daemon.
+ </doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Inhibits clients from invoking methods on the daemon
+ of the daemon that require authorization (all methods
+ will return the <doc:tt>&ERROR_INHIBITED;</doc:tt> error)
+ if the caller is not the super user.
+ This is typically used by OS installers and other
+ programs that expects full control of the system, specifically
+ to avoid automounting devices.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ Only the super user can invoke this method.
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="&ERROR_NOT_AUTHORIZED;">if the caller is not the super user</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Uninhibit">
+ <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.Inhibit">Inhibit()</doc:ref> method.
+ </doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Uninhibits other clients from using the daemon.
+ </doc:para>
+ </doc:description>
+ <doc:errors>
+ <doc:error name="&ERROR_FAILED;">if the given cookie is malformed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+
+ <!-- ************************************************************ -->
+
<signal name="DeviceAdded">
<arg name="device" type="o">
<doc:doc><doc:summary>Object path of device that was added.</doc:summary></doc:doc>
</doc:para></doc:description></doc:doc>
</property>
+ <property name="daemon-is-inhibited" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ TRUE only if the daemon is inhibited.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
<property name="supports-luks-devices" type="b" access="read">
<doc:doc><doc:description><doc:para>
TRUE only if the daemon can create encrypted LUKS block devices, see the
static gboolean opt_monitor_detail = FALSE;
static char *opt_show_info = NULL;
static char *opt_inhibit_polling = NULL;
+static gboolean opt_inhibit = FALSE;
static gboolean opt_inhibit_all_polling = FALSE;
static char *opt_mount = NULL;
static char *opt_mount_fstype = NULL;
/* ---------------------------------------------------------------------------------------------------- */
-
static gint
do_inhibit_all_polling (gint argc,
gchar *argv[])
/* ---------------------------------------------------------------------------------------------------- */
+static gint
+do_inhibit (gint argc,
+ gchar *argv[])
+{
+ char *cookie;
+ DBusGProxy *proxy;
+ GError *error;
+ gint ret;
+
+ cookie = NULL;
+ ret = 127;
+
+ proxy = dbus_g_proxy_new_for_name (bus,
+ "org.freedesktop.DeviceKit.Disks",
+ "/",
+ "org.freedesktop.DeviceKit.Disks");
+
+ error = NULL;
+ if (!org_freedesktop_DeviceKit_Disks_inhibit (proxy,
+ &cookie,
+ &error)) {
+ g_print ("Inhibit all polling failed: %s\n", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ if (argc == 0) {
+ g_print ("Inhibiting the daemon. Press Ctrl+C to exit.\n");
+ while (TRUE)
+ sleep (100000000);
+ } else {
+ GError *error;
+ gint exit_status;
+
+ error = NULL;
+ if (!g_spawn_sync (NULL, /* working dir */
+ argv,
+ NULL, /* envp */
+ G_SPAWN_SEARCH_PATH,
+ NULL, /* child_setup */
+ NULL, /* user_data */
+ NULL, /* standard_output */
+ NULL, /* standard_error */
+ &exit_status, /* exit_status */
+ &error)) {
+ g_printerr ("Error launching program: %s\n", error->message);
+ g_error_free (error);
+ ret = 126;
+ goto out;
+ }
+
+ if (WIFEXITED (exit_status))
+ ret = WEXITSTATUS (exit_status);
+ else
+ ret = 125;
+ }
+
+out:
+ g_free (cookie);
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
int
main (int argc, char **argv)
{
{ "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 },
+ { "inhibit", 0, 0, G_OPTION_ARG_NONE, &opt_inhibit, "Inhibit the daemon", 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 },
} else if (opt_inhibit_all_polling) {
ret = do_inhibit_all_polling (argc - 1, argv + 1);
goto out;
+ } else if (opt_inhibit) {
+ ret = do_inhibit (argc - 1, argv + 1);
+ goto out;
} else if (opt_mount != NULL) {
do_mount (opt_mount, opt_mount_fstype, opt_mount_options);
} else if (opt_unmount != NULL) {