From 23a37a803a180dadb78fd36ef746ae129dd69779 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Mon, 25 Jun 2012 11:38:29 -0400 Subject: [PATCH] Add erase parameter to Block.Format() to zero out device before formatting it ... and also provide new job properties so it's possible to build a meaningful UI around it. This makes things like this possible http://people.freedesktop.org/~david/gnome-disks-erase-overwrite-option.png http://people.freedesktop.org/~david/gnome-disks-long-running-operations.png Signed-off-by: David Zeuthen --- data/org.freedesktop.UDisks2.xml | 85 ++++++++++++++++++++-- data/org.freedesktop.udisks2.policy.in | 25 +++++++ doc/udisks2-sections.txt | 1 + src/tests/test.c | 40 +++++------ src/udisksbasejob.c | 100 +++++++++++++++++++++++++- src/udisksbasejob.h | 2 + src/udiskscleanup.c | 2 + src/udisksdaemon.c | 24 ++++++- src/udisksdaemon.h | 12 +++- src/udisksdaemonutil.c | 1 + src/udiskslinuxblock.c | 126 +++++++++++++++++++++++++++++++++ src/udiskslinuxdrive.c | 17 +++++ src/udiskslinuxdriveata.c | 54 ++++++++++++++ src/udiskslinuxencrypted.c | 3 + src/udiskslinuxfilesystem.c | 24 ++++++- src/udiskslinuxloop.c | 1 + src/udiskslinuxpartition.c | 68 ++++++++++++++++++ src/udiskslinuxpartitiontable.c | 18 +++++ src/udiskslinuxswapspace.c | 35 +++++++++ src/udiskssimplejob.c | 7 +- src/udiskssimplejob.h | 3 +- src/udisksspawnedjob.c | 5 ++ src/udisksspawnedjob.h | 1 + src/udisksthreadedjob.c | 5 ++ src/udisksthreadedjob.h | 1 + udisks/udisksclient.c | 52 ++++++++++++++ udisks/udisksclient.h | 3 + 27 files changed, 679 insertions(+), 36 deletions(-) diff --git a/data/org.freedesktop.UDisks2.xml b/data/org.freedesktop.UDisks2.xml index fef2b9f..956a921 100644 --- a/data/org.freedesktop.UDisks2.xml +++ b/data/org.freedesktop.UDisks2.xml @@ -947,7 +947,7 @@ @@ -1508,9 +1513,15 @@ things, this can be used to draw a spinner in the user interface next to e.g. an icon for the drive or device in question. - A job may convey progress (if the - underlying tool used supports it), see the - #org.freedesktop.UDisks2.Job:ExpectedEndTime property. + The #org.freedesktop.UDisks2.Job:Operation property is used to + convey the type of job currently in progress. + + The user id of the user who started the job is set in the + #org.freedesktop.UDisks2.Job:StartedByUID property. + + A job may convey how much progress has been + made, see the #org.freedesktop.UDisks2.Job:Progress and + #org.freedesktop.UDisks2.Job:ProgressValid properties. When a job completes, the #org.freedesktop.UDisks2.Job::Completed signal is emitted. @@ -1518,12 +1529,67 @@ To cancel a job use the org.freedesktop.UDisks2.Job.Cancel() method. This will cause the job to complete (with @success set to %FALSE) and the D-Bus method used to initiate the operation - to return, usually returning the org.freedesktop.UDisks2.Error.Cancelled error. + to return, usually returning the + org.freedesktop.UDisks2.Error.Cancelled error. --> - + + + + + + + + + + + + + + + + + <_description>Cancel job + <_message>Authentication is required to cancel a job + + auth_admin + auth_admin + yes + + + + + + <_description>Cancel job started by another user + <_message>Authentication is required to cancel a job started by another user + + auth_admin + auth_admin + auth_admin_keep + + + diff --git a/doc/udisks2-sections.txt b/doc/udisks2-sections.txt index 1ac10b6..9871c1f 100644 --- a/doc/udisks2-sections.txt +++ b/doc/udisks2-sections.txt @@ -47,6 +47,7 @@ udisks_client_get_partition_table udisks_client_get_loop_for_block udisks_client_get_partitions udisks_client_get_jobs_for_object +udisks_client_get_job_description udisks_client_get_drive_info udisks_client_get_partition_info diff --git a/src/tests/test.c b/src/tests/test.c index 1855deb..7f25ecb 100644 --- a/src/tests/test.c +++ b/src/tests/test.c @@ -69,7 +69,7 @@ test_spawned_job_successful (void) { UDisksSpawnedJob *job; - job = udisks_spawned_job_new ("/bin/true", NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new ("/bin/true", NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_success), NULL); g_object_unref (job); } @@ -81,7 +81,7 @@ test_spawned_job_failure (void) { UDisksSpawnedJob *job; - job = udisks_spawned_job_new ("/bin/false", NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new ("/bin/false", NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), "Command-line `/bin/false' exited with non-zero exit status 1: "); g_object_unref (job); @@ -94,7 +94,7 @@ test_spawned_job_missing_program (void) { UDisksSpawnedJob *job; - job = udisks_spawned_job_new ("/path/to/unknown/file", NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new ("/path/to/unknown/file", NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), "Error spawning command-line `/path/to/unknown/file': Failed to execute child process \"/path/to/unknown/file\" (No such file or directory) (g-exec-error-quark, 8)"); g_object_unref (job); @@ -110,7 +110,7 @@ test_spawned_job_cancelled_at_start (void) cancellable = g_cancellable_new (); g_cancellable_cancel (cancellable); - job = udisks_spawned_job_new ("/bin/true", NULL, getuid (), geteuid (), cancellable); + job = udisks_spawned_job_new ("/bin/true", NULL, getuid (), geteuid (), NULL, cancellable); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), "Operation was cancelled (g-io-error-quark, 19)"); g_object_unref (job); @@ -135,7 +135,7 @@ test_spawned_job_cancelled_midway (void) GCancellable *cancellable; cancellable = g_cancellable_new (); - job = udisks_spawned_job_new ("/bin/sleep 0.5", NULL, getuid (), geteuid (), cancellable); + job = udisks_spawned_job_new ("/bin/sleep 0.5", NULL, getuid (), geteuid (), NULL, cancellable); g_timeout_add (10, on_timeout, cancellable); /* 10 msec */ g_main_loop_run (loop); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), @@ -167,7 +167,7 @@ test_spawned_job_override_signal_handler (void) UDisksSpawnedJob *job; gboolean handler_ran; - job = udisks_spawned_job_new ("/path/to/unknown/file", NULL, getuid (), geteuid (), NULL /* GCancellable */); + job = udisks_spawned_job_new ("/path/to/unknown/file", NULL, getuid (), geteuid (), NULL, NULL /* GCancellable */); handler_ran = FALSE; g_signal_connect (job, "spawned-job-completed", G_CALLBACK (on_spawned_job_completed), &handler_ran); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), @@ -183,7 +183,7 @@ test_spawned_job_premature_termination (void) { UDisksSpawnedJob *job; - job = udisks_spawned_job_new ("/bin/sleep 1000", NULL, getuid (), geteuid (), NULL /* GCancellable */); + job = udisks_spawned_job_new ("/bin/sleep 1000", NULL, getuid (), geteuid (), NULL, NULL /* GCancellable */); g_object_unref (job); } @@ -214,7 +214,7 @@ test_spawned_job_read_stdout (void) gchar *s; s = g_strdup_printf (UDISKS_TEST_DIR "/udisks-test-helper 0"); - job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "spawned-job-completed", G_CALLBACK (read_stdout_on_spawned_job_completed), NULL); g_object_unref (job); g_free (s); @@ -247,7 +247,7 @@ test_spawned_job_read_stderr (void) gchar *s; s = g_strdup_printf (UDISKS_TEST_DIR "/udisks-test-helper 1"); - job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "spawned-job-completed", G_CALLBACK (read_stderr_on_spawned_job_completed), NULL); g_object_unref (job); g_free (s); @@ -278,14 +278,14 @@ test_spawned_job_exit_status (void) gchar *s; s = g_strdup_printf (UDISKS_TEST_DIR "/udisks-test-helper 2"); - job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "spawned-job-completed", G_CALLBACK (exit_status_on_spawned_job_completed), GINT_TO_POINTER (1)); g_object_unref (job); g_free (s); s = g_strdup_printf (UDISKS_TEST_DIR "/udisks-test-helper 3"); - job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "spawned-job-completed", G_CALLBACK (exit_status_on_spawned_job_completed), GINT_TO_POINTER (2)); g_object_unref (job); @@ -301,7 +301,7 @@ test_spawned_job_abnormal_termination (void) gchar *s; s = g_strdup_printf (UDISKS_TEST_DIR "/udisks-test-helper 4"); - job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), "Command-line `./udisks-test-helper 4' was signaled with signal SIGSEGV (11): " "OK, deliberately causing a segfault\n"); @@ -309,7 +309,7 @@ test_spawned_job_abnormal_termination (void) g_free (s); s = g_strdup_printf (UDISKS_TEST_DIR "/udisks-test-helper 5"); - job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), "Command-line `./udisks-test-helper 5' was signaled with signal SIGABRT (6): " "OK, deliberately abort()'ing\n"); @@ -350,7 +350,7 @@ test_spawned_job_binary_output (void) gchar *s; s = g_strdup_printf (UDISKS_TEST_DIR "/udisks-test-helper 6"); - job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL); + job = udisks_spawned_job_new (s, NULL, getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "spawned-job-completed", G_CALLBACK (binary_output_on_spawned_job_completed), NULL); g_object_unref (job); g_free (s); @@ -381,7 +381,7 @@ test_spawned_job_input_string (void) gchar *s; s = g_strdup_printf (UDISKS_TEST_DIR "/udisks-test-helper 7"); - job = udisks_spawned_job_new (s, "foobar", getuid (), geteuid (), NULL); + job = udisks_spawned_job_new (s, "foobar", getuid (), geteuid (), NULL, NULL); _g_assert_signal_received (job, "spawned-job-completed", G_CALLBACK (input_string_on_spawned_job_completed), NULL); g_object_unref (job); g_free (s); @@ -404,7 +404,7 @@ test_threaded_job_successful (void) { UDisksThreadedJob *job; - job = udisks_threaded_job_new (threaded_job_successful_func, NULL, NULL, NULL); + job = udisks_threaded_job_new (threaded_job_successful_func, NULL, NULL, NULL, NULL); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_success), NULL); g_object_unref (job); } @@ -430,7 +430,7 @@ test_threaded_job_failure (void) { UDisksThreadedJob *job; - job = udisks_threaded_job_new (threaded_job_failure_func, NULL, NULL, NULL); + job = udisks_threaded_job_new (threaded_job_failure_func, NULL, NULL, NULL, NULL); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), "Threaded job failed with error: some error (g-key-file-error-quark, 5)"); g_object_unref (job); @@ -446,7 +446,7 @@ test_threaded_job_cancelled_at_start (void) cancellable = g_cancellable_new (); g_cancellable_cancel (cancellable); - job = udisks_threaded_job_new (threaded_job_successful_func, NULL, NULL, cancellable); + job = udisks_threaded_job_new (threaded_job_successful_func, NULL, NULL, NULL, cancellable); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), "Threaded job failed with error: Operation was cancelled (g-io-error-quark, 19)"); g_object_unref (job); @@ -485,7 +485,7 @@ test_threaded_job_cancelled_midway (void) cancellable = g_cancellable_new (); count = 0; - job = udisks_threaded_job_new (threaded_job_sleep_until_cancelled, &count, NULL, cancellable); + job = udisks_threaded_job_new (threaded_job_sleep_until_cancelled, &count, NULL, NULL, cancellable); g_timeout_add (10, on_timeout, cancellable); /* 10 msec */ g_main_loop_run (loop); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), @@ -518,7 +518,7 @@ test_threaded_job_override_signal_handler (void) UDisksThreadedJob *job; gboolean handler_ran; - job = udisks_threaded_job_new (threaded_job_failure_func, NULL, NULL, NULL); + job = udisks_threaded_job_new (threaded_job_failure_func, NULL, NULL, NULL, NULL); handler_ran = FALSE; g_signal_connect (job, "threaded-job-completed", G_CALLBACK (on_threaded_job_completed), &handler_ran); _g_assert_signal_received (job, "completed", G_CALLBACK (on_completed_expect_failure), diff --git a/src/udisksbasejob.c b/src/udisksbasejob.c index d298792..e113b67 100644 --- a/src/udisksbasejob.c +++ b/src/udisksbasejob.c @@ -25,6 +25,8 @@ #include #include "udisksbasejob.h" +#include "udisksdaemon.h" +#include "udisksdaemonutil.h" #include "udisks-daemon-marshal.h" /** @@ -38,6 +40,7 @@ struct _UDisksBaseJobPrivate { GCancellable *cancellable; + UDisksDaemon *daemon; }; static void job_iface_init (UDisksJobIface *iface); @@ -45,6 +48,7 @@ static void job_iface_init (UDisksJobIface *iface); enum { PROP_0, + PROP_DAEMON, PROP_CANCELLABLE, }; @@ -76,6 +80,10 @@ udisks_base_job_get_property (GObject *object, switch (prop_id) { + case PROP_DAEMON: + g_value_set_object (value, udisks_base_job_get_daemon (job)); + break; + case PROP_CANCELLABLE: g_value_set_object (value, job->priv->cancellable); break; @@ -96,6 +104,12 @@ udisks_base_job_set_property (GObject *object, switch (prop_id) { + case PROP_DAEMON: + g_assert (job->priv->daemon == NULL); + /* we don't take a reference to the daemon */ + job->priv->daemon = g_value_get_object (value); + break; + case PROP_CANCELLABLE: g_assert (job->priv->cancellable == NULL); job->priv->cancellable = g_value_dup_object (value); @@ -126,7 +140,12 @@ udisks_base_job_constructed (GObject *object) static void udisks_base_job_init (UDisksBaseJob *job) { + gint64 now_usec; + job->priv = G_TYPE_INSTANCE_GET_PRIVATE (job, UDISKS_TYPE_BASE_JOB, UDisksBaseJobPrivate); + + now_usec = g_get_real_time (); + udisks_job_set_start_time (UDISKS_JOB (job), now_usec / G_USEC_PER_SEC); } static void @@ -141,6 +160,22 @@ udisks_base_job_class_init (UDisksBaseJobClass *klass) gobject_class->get_property = udisks_base_job_get_property; /** + * UDisksBaseJob:daemon: + * + * The #UDisksDaemon the object is for. + */ + g_object_class_install_property (gobject_class, + PROP_DAEMON, + g_param_spec_object ("daemon", + "Daemon", + "The daemon the object is for", + UDISKS_TYPE_DAEMON, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** * UDisksBaseJob:cancellable: * * The #GCancellable to use. @@ -179,6 +214,23 @@ udisks_base_job_get_cancellable (UDisksBaseJob *job) /* ---------------------------------------------------------------------------------------------------- */ /** + * udisks_base_job_get_daemon: + * @job: A #UDisksBaseJob. + * + * Gets the #UDisksDaemon for @job. + * + * Returns: A #UDisksDaemon. Do not free, the object belongs to @job. + */ +UDisksDaemon * +udisks_base_job_get_daemon (UDisksBaseJob *job) +{ + g_return_val_if_fail (UDISKS_IS_BASE_JOB (job), NULL); + return job->priv->daemon; +} + +/* ---------------------------------------------------------------------------------------------------- */ + +/** * udisks_base_job_add_object: * @job: A #UDisksBaseJob. * @object: A #UDisksObject. @@ -264,11 +316,51 @@ udisks_base_job_remove_object (UDisksBaseJob *job, /* ---------------------------------------------------------------------------------------------------- */ static gboolean -handle_cancel (UDisksJob *object, +handle_cancel (UDisksJob *_job, GDBusMethodInvocation *invocation, GVariant *options) { - UDisksBaseJob *job = UDISKS_BASE_JOB (object); + UDisksBaseJob *job = UDISKS_BASE_JOB (_job); + UDisksObject *object = NULL; + const gchar *action_id; + const gchar *message; + uid_t caller_uid; + gid_t caller_gid; + GError *error = NULL; + + object = udisks_daemon_util_dup_object (job, &error); + if (object == NULL) + { + g_dbus_method_invocation_take_error (invocation, error); + goto out; + } + + if (!udisks_daemon_util_get_caller_uid_sync (job->priv->daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_take_error (invocation, error); + goto out; + } + + /* Translators: Shown in authentication dialog when canceling a job. + */ + message = N_("Authentication is required to cancel a job"); + action_id = "org.freedesktop.udisks2.cancel-job"; + if (caller_uid != udisks_job_get_started_by_uid (UDISKS_JOB (job))) + action_id = "org.freedesktop.udisks2.cancel-job-other-user"; + + if (!udisks_daemon_util_check_authorization_sync (job->priv->daemon, + object, + action_id, + options, + message, + invocation)) + goto out; if (g_cancellable_is_cancelled (job->priv->cancellable)) { @@ -280,9 +372,11 @@ handle_cancel (UDisksJob *object, else { g_cancellable_cancel (job->priv->cancellable); - udisks_job_complete_cancel (object, invocation); + udisks_job_complete_cancel (UDISKS_JOB (job), invocation); } + out: + g_clear_object (&object); return TRUE; } diff --git a/src/udisksbasejob.h b/src/udisksbasejob.h index 35f8495..c78eb30 100644 --- a/src/udisksbasejob.h +++ b/src/udisksbasejob.h @@ -62,7 +62,9 @@ struct _UDisksBaseJobClass }; GType udisks_base_job_get_type (void) G_GNUC_CONST; +UDisksDaemon *udisks_base_job_get_daemon (UDisksBaseJob *job); GCancellable *udisks_base_job_get_cancellable (UDisksBaseJob *job); + void udisks_base_job_add_object (UDisksBaseJob *job, UDisksObject *object); void udisks_base_job_remove_object (UDisksBaseJob *job, diff --git a/src/udiskscleanup.c b/src/udiskscleanup.c index 4ec1fd7..308cc21 100644 --- a/src/udiskscleanup.c +++ b/src/udiskscleanup.c @@ -677,6 +677,7 @@ udisks_cleanup_check_mounted_fs_entry (UDisksCleanup *cleanup, /* right now -l is the only way to "force unmount" file systems... */ if (!udisks_daemon_launch_spawned_job_sync (cleanup->daemon, NULL, /* UDisksObject */ + "cleanup", 0, /* StartedByUID */ NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -1168,6 +1169,7 @@ udisks_cleanup_check_unlocked_luks_entry (UDisksCleanup *cleanup, escaped_device_file = udisks_daemon_util_escape_and_quote (device_file_cleartext); if (!udisks_daemon_launch_spawned_job_sync (cleanup->daemon, NULL, /* UDisksObject */ + "cleanup", 0, /* StartedByUID */ NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ diff --git a/src/udisksdaemon.c b/src/udisksdaemon.c index 2929ee7..4042412 100644 --- a/src/udisksdaemon.c +++ b/src/udisksdaemon.c @@ -518,6 +518,8 @@ static guint job_id = 0; UDisksBaseJob * udisks_daemon_launch_simple_job (UDisksDaemon *daemon, UDisksObject *object, + const gchar *job_operation, + uid_t job_started_by_uid, GCancellable *cancellable) { UDisksSimpleJob *job; @@ -526,7 +528,7 @@ udisks_daemon_launch_simple_job (UDisksDaemon *daemon, g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL); - job = udisks_simple_job_new (cancellable); + job = udisks_simple_job_new (daemon, cancellable); if (object != NULL) udisks_base_job_add_object (UDISKS_BASE_JOB (job), object); @@ -536,6 +538,9 @@ udisks_daemon_launch_simple_job (UDisksDaemon *daemon, udisks_object_skeleton_set_job (job_object, UDISKS_JOB (job)); g_free (job_object_path); + udisks_job_set_operation (UDISKS_JOB (job), job_operation); + udisks_job_set_started_by_uid (UDISKS_JOB (job), job_started_by_uid); + g_dbus_object_manager_server_export (daemon->object_manager, G_DBUS_OBJECT_SKELETON (job_object)); g_signal_connect_after (job, "completed", @@ -575,6 +580,8 @@ udisks_daemon_launch_simple_job (UDisksDaemon *daemon, UDisksBaseJob * udisks_daemon_launch_threaded_job (UDisksDaemon *daemon, UDisksObject *object, + const gchar *job_operation, + uid_t job_started_by_uid, UDisksThreadedJobFunc job_func, gpointer user_data, GDestroyNotify user_data_free_func, @@ -590,6 +597,7 @@ udisks_daemon_launch_threaded_job (UDisksDaemon *daemon, job = udisks_threaded_job_new (job_func, user_data, user_data_free_func, + daemon, cancellable); if (object != NULL) udisks_base_job_add_object (UDISKS_BASE_JOB (job), object); @@ -600,6 +608,9 @@ udisks_daemon_launch_threaded_job (UDisksDaemon *daemon, udisks_object_skeleton_set_job (job_object, UDISKS_JOB (job)); g_free (job_object_path); + udisks_job_set_operation (UDISKS_JOB (job), job_operation); + udisks_job_set_started_by_uid (UDISKS_JOB (job), job_started_by_uid); + g_dbus_object_manager_server_export (daemon->object_manager, G_DBUS_OBJECT_SKELETON (job_object)); g_signal_connect_after (job, "completed", @@ -638,6 +649,8 @@ udisks_daemon_launch_threaded_job (UDisksDaemon *daemon, UDisksBaseJob * udisks_daemon_launch_spawned_job (UDisksDaemon *daemon, UDisksObject *object, + const gchar *job_operation, + uid_t job_started_by_uid, GCancellable *cancellable, uid_t run_as_uid, uid_t run_as_euid, @@ -658,7 +671,7 @@ udisks_daemon_launch_spawned_job (UDisksDaemon *daemon, va_start (var_args, command_line_format); command_line = g_strdup_vprintf (command_line_format, var_args); va_end (var_args); - job = udisks_spawned_job_new (command_line, input_string, run_as_uid, run_as_euid, cancellable); + job = udisks_spawned_job_new (command_line, input_string, run_as_uid, run_as_euid, daemon, cancellable); g_free (command_line); if (object != NULL) @@ -670,6 +683,9 @@ udisks_daemon_launch_spawned_job (UDisksDaemon *daemon, udisks_object_skeleton_set_job (job_object, UDISKS_JOB (job)); g_free (job_object_path); + udisks_job_set_operation (UDISKS_JOB (job), job_operation); + udisks_job_set_started_by_uid (UDISKS_JOB (job), job_started_by_uid); + g_dbus_object_manager_server_export (daemon->object_manager, G_DBUS_OBJECT_SKELETON (job_object)); g_signal_connect_after (job, "completed", @@ -736,6 +752,8 @@ spawned_job_sync_on_completed (UDisksJob *job, gboolean udisks_daemon_launch_spawned_job_sync (UDisksDaemon *daemon, UDisksObject *object, + const gchar *job_operation, + uid_t job_started_by_uid, GCancellable *cancellable, uid_t run_as_uid, uid_t run_as_euid, @@ -766,6 +784,8 @@ udisks_daemon_launch_spawned_job_sync (UDisksDaemon *daemon, va_end (var_args); job = udisks_daemon_launch_spawned_job (daemon, object, + job_operation, + job_started_by_uid, cancellable, run_as_uid, run_as_euid, diff --git a/src/udisksdaemon.h b/src/udisksdaemon.h index f0ad422..47ac61e 100644 --- a/src/udisksdaemon.h +++ b/src/udisksdaemon.h @@ -76,17 +76,23 @@ UDisksObject *udisks_daemon_find_object (UDisksDaemon UDisksBaseJob *udisks_daemon_launch_simple_job (UDisksDaemon *daemon, UDisksObject *object, + const gchar *job_operation, + uid_t job_started_by_uid, GCancellable *cancellable); UDisksBaseJob *udisks_daemon_launch_spawned_job (UDisksDaemon *daemon, UDisksObject *object, + const gchar *job_operation, + uid_t job_started_by_uid, GCancellable *cancellable, uid_t run_as_uid, uid_t run_as_euid, const gchar *input_string, const gchar *command_line_format, - ...) G_GNUC_PRINTF (7, 8); + ...) G_GNUC_PRINTF (9, 10); gboolean udisks_daemon_launch_spawned_job_sync (UDisksDaemon *daemon, UDisksObject *object, + const gchar *job_operation, + uid_t job_started_by_uid, GCancellable *cancellable, uid_t run_as_uid, uid_t run_as_euid, @@ -94,9 +100,11 @@ gboolean udisks_daemon_launch_spawned_job_sync (UDisksDaemon gchar **out_message, const gchar *input_string, const gchar *command_line_format, - ...) G_GNUC_PRINTF (9, 10); + ...) G_GNUC_PRINTF (11, 12); UDisksBaseJob *udisks_daemon_launch_threaded_job (UDisksDaemon *daemon, UDisksObject *object, + const gchar *job_operation, + uid_t job_started_by_uid, UDisksThreadedJobFunc job_func, gpointer user_data, GDestroyNotify user_data_free_func, diff --git a/src/udisksdaemonutil.c b/src/udisksdaemonutil.c index ff50fba..06982d1 100644 --- a/src/udisksdaemonutil.c +++ b/src/udisksdaemonutil.c @@ -20,6 +20,7 @@ #include "config.h" #include +#include #include diff --git a/src/udiskslinuxblock.c b/src/udiskslinuxblock.c index ac1df48..2948050 100644 --- a/src/udiskslinuxblock.c +++ b/src/udiskslinuxblock.c @@ -51,6 +51,8 @@ #include "udiskscrypttabmonitor.h" #include "udiskscrypttabentry.h" #include "udisksdaemonutil.h" +#include "udisksbasejob.h" +#include "udiskssimplejob.h" /** * SECTION:udiskslinuxblock @@ -1717,6 +1719,112 @@ wait_for_luks_cleartext (UDisksDaemon *daemon, /* ---------------------------------------------------------------------------------------------------- */ +#define ERASE_SIZE (1 * 1024*1024) + +static gboolean +erase_device (UDisksBlock *block, + UDisksObject *object, + UDisksDaemon *daemon, + uid_t caller_uid, + const gchar *erase_type, + GError **error) +{ + gboolean ret = FALSE; + const gchar *device_file = NULL; + UDisksBaseJob *job = NULL; + gint fd = -1; + guint64 size; + guint64 pos; + guchar *buf = NULL; + gint64 time_of_last_signal; + GError *local_error = NULL; + + if (g_strcmp0 (erase_type, "zero") != 0) + { + g_set_error (&local_error, UDISKS_ERROR, UDISKS_ERROR_FAILED, + "Unknown or unsupported erase type `%s'", + erase_type); + goto out; + } + + device_file = udisks_block_get_device (block); + fd = open (device_file, O_WRONLY | O_SYNC | O_EXCL); + if (fd == -1) + { + g_set_error (&local_error, UDISKS_ERROR, UDISKS_ERROR_FAILED, + "Error opening device %s: %m", device_file); + goto out; + } + + job = udisks_daemon_launch_simple_job (daemon, object, "format-erase", caller_uid, NULL); + udisks_job_set_progress_valid (UDISKS_JOB (job), TRUE); + + if (ioctl (fd, BLKGETSIZE64, &size) != 0) + { + g_set_error (&local_error, UDISKS_ERROR, UDISKS_ERROR_FAILED, + "Error doing BLKGETSIZE64 iotctl on %s: %m", device_file); + goto out; + } + + buf = g_new0 (guchar, ERASE_SIZE); + pos = 0; + time_of_last_signal = g_get_monotonic_time (); + while (pos < size) + { + size_t to_write; + ssize_t num_written; + gint64 now; + + to_write = MIN (size - pos, ERASE_SIZE); + again: + num_written = write (fd, buf, to_write); + if (num_written == -1 || num_written == 0) + { + if (errno == EINTR) + goto again; + g_set_error (&local_error, UDISKS_ERROR, UDISKS_ERROR_FAILED, + "Error writing %d bytes to %s: %m", + (gint) to_write, device_file); + goto out; + } + pos += num_written; + + if (g_cancellable_is_cancelled (udisks_base_job_get_cancellable (job))) + { + g_set_error (&local_error, UDISKS_ERROR, UDISKS_ERROR_CANCELLED, + "Job was canceled"); + goto out; + } + + /* only emit D-Bus signal at most once a second */ + now = g_get_monotonic_time (); + if (now - time_of_last_signal > G_USEC_PER_SEC) + { + /* TODO: estimation etc. */ + udisks_job_set_progress (UDISKS_JOB (job), ((gdouble) pos) / size); + time_of_last_signal = now; + } + } + + ret = TRUE; + + out: + if (job != NULL) + { + if (local_error != NULL) + udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), FALSE, local_error->message); + else + udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), TRUE, ""); + } + g_propagate_error (error, local_error); + g_free (buf); + if (fd != -1) + close (fd); + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + static gboolean handle_format (UDisksBlock *block, GDBusMethodInvocation *invocation, @@ -1745,6 +1853,7 @@ handle_format (UDisksBlock *block, pid_t caller_pid; gboolean take_ownership = FALSE; gchar *encrypt_passphrase = NULL; + gchar *erase_type = NULL; gchar *mapped_name = NULL; const gchar *label = NULL; gchar *escaped_device = NULL; @@ -1824,6 +1933,7 @@ handle_format (UDisksBlock *block, g_variant_lookup (options, "take-ownership", "b", &take_ownership); g_variant_lookup (options, "encrypt.passphrase", "s", &encrypt_passphrase); + g_variant_lookup (options, "erase", "s", &erase_type); escaped_device = udisks_daemon_util_escape_and_quote (udisks_block_get_device (block)); @@ -1832,6 +1942,7 @@ handle_format (UDisksBlock *block, wait_data->object = object; if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "format-erase", caller_uid, NULL, /* cancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -1861,6 +1972,17 @@ handle_format (UDisksBlock *block, goto out; } + /* Erase the device, if requested */ + if (erase_type != NULL) + { + if (!erase_device (block, object, daemon, caller_uid, erase_type, &error)) + { + g_prefix_error (&error, "Error erasing device: "); + g_dbus_method_invocation_take_error (invocation, error); + goto out; + } + } + /* And now create the desired filesystem */ wait_data->type = type; @@ -1869,6 +1991,7 @@ handle_format (UDisksBlock *block, /* Create it */ if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "format-mkfs", caller_uid, NULL, /* cancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -1904,6 +2027,7 @@ handle_format (UDisksBlock *block, mapped_name = g_strdup_printf ("luks-%s", udisks_block_get_id_uuid (block)); if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "format-mkfs", caller_uid, NULL, /* cancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -1982,6 +2106,7 @@ handle_format (UDisksBlock *block, g_free (tmp); if (!udisks_daemon_launch_spawned_job_sync (daemon, object_to_mkfs, + "format-mkfs", caller_uid, NULL, /* cancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -2096,6 +2221,7 @@ handle_format (UDisksBlock *block, g_free (escaped_device); g_free (mapped_name); g_free (command); + g_free (erase_type); g_free (encrypt_passphrase); g_clear_object (&cleartext_object); g_clear_object (&cleartext_block); diff --git a/src/udiskslinuxdrive.c b/src/udiskslinuxdrive.c index 5c7eba3..c7a81d7 100644 --- a/src/udiskslinuxdrive.c +++ b/src/udiskslinuxdrive.c @@ -894,6 +894,8 @@ handle_eject (UDisksDrive *_drive, gchar *error_message = NULL; GError *error = NULL; gchar *escaped_device = NULL; + uid_t caller_uid; + gid_t caller_gid; pid_t caller_pid; object = udisks_daemon_util_dup_object (drive, &error); @@ -935,6 +937,20 @@ handle_eject (UDisksDrive *_drive, goto out; } + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + /* Translators: Shown in authentication dialog when the user * requests ejecting media from a drive. * @@ -965,6 +981,7 @@ handle_eject (UDisksDrive *_drive, if (!udisks_daemon_launch_spawned_job_sync (daemon, UDISKS_OBJECT (object), + "drive-eject", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ diff --git a/src/udiskslinuxdriveata.c b/src/udiskslinuxdriveata.c index d93a550..bbebbfb 100644 --- a/src/udiskslinuxdriveata.c +++ b/src/udiskslinuxdriveata.c @@ -872,10 +872,14 @@ selftest_job_func (UDisksThreadedJob *job, if (object == NULL) goto out; + udisks_job_set_progress_valid (UDISKS_JOB (job), TRUE); + udisks_job_set_progress (UDISKS_JOB (job), 0.0); + while (TRUE) { gboolean still_in_progress; GPollFD poll_fd; + gdouble progress; if (!udisks_linux_drive_ata_refresh_smart_sync (drive, FALSE, /* nowakeup */ @@ -893,6 +897,7 @@ selftest_job_func (UDisksThreadedJob *job, G_LOCK (object_lock); still_in_progress = (g_strcmp0 (drive->smart_selftest_status, "inprogress") == 0); + progress = (100.0 - drive->smart_selftest_percent_remaining) / 100.0; G_UNLOCK (object_lock); if (!still_in_progress) { @@ -900,6 +905,12 @@ selftest_job_func (UDisksThreadedJob *job, goto out; } + if (progress < 0.0) + progress = 0.0; + if (progress > 1.0) + progress = 1.0; + udisks_job_set_progress (UDISKS_JOB (job), progress); + /* Sleep for 30 seconds or until we're cancelled */ if (g_cancellable_make_pollfd (cancellable, &poll_fd)) { @@ -923,10 +934,36 @@ selftest_job_func (UDisksThreadedJob *job, /* Check if we're cancelled */ if (g_cancellable_is_cancelled (cancellable)) { + GError *c_error; + g_set_error (error, UDISKS_ERROR, UDISKS_ERROR_CANCELLED, "Self-test was cancelled"); + + /* OK, cancelled ... still need to a) abort the test; and b) update the status */ + c_error = NULL; + if (!udisks_linux_drive_ata_smart_selftest_sync (drive, + "abort", + NULL, /* cancellable */ + &c_error)) + { + udisks_warning ("Error aborting SMART selftest for %s on cancel path: %s (%s, %d)", + g_dbus_object_get_object_path (G_DBUS_OBJECT (object)), + c_error->message, g_quark_to_string (c_error->domain), c_error->code); + g_clear_error (&c_error); + } + if (!udisks_linux_drive_ata_refresh_smart_sync (drive, + FALSE, /* nowakeup */ + NULL, /* blob */ + NULL, /* cancellable */ + &c_error)) + { + udisks_warning ("Error updating ATA smart for %s on cancel path: %s (%s, %d)", + g_dbus_object_get_object_path (G_DBUS_OBJECT (object)), + c_error->message, g_quark_to_string (c_error->domain), c_error->code); + g_clear_error (&c_error); + } goto out; } } @@ -953,6 +990,8 @@ handle_smart_selftest_start (UDisksDriveAta *_drive, UDisksLinuxBlockObject *block_object; UDisksDaemon *daemon; UDisksLinuxDriveAta *drive = UDISKS_LINUX_DRIVE_ATA (_drive); + uid_t caller_uid; + gid_t caller_gid; GError *error; error = NULL; @@ -984,6 +1023,20 @@ handle_smart_selftest_start (UDisksDriveAta *_drive, goto out; } + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + G_LOCK (object_lock); if (drive->selftest_job != NULL) { @@ -1028,6 +1081,7 @@ handle_smart_selftest_start (UDisksDriveAta *_drive, { drive->selftest_job = UDISKS_THREADED_JOB (udisks_daemon_launch_threaded_job (daemon, UDISKS_OBJECT (object), + "ata-smart-selftest", caller_uid, selftest_job_func, g_object_ref (drive), g_object_unref, diff --git a/src/udiskslinuxencrypted.c b/src/udiskslinuxencrypted.c index 5fad4ef..a8418f5 100644 --- a/src/udiskslinuxencrypted.c +++ b/src/udiskslinuxencrypted.c @@ -395,6 +395,7 @@ handle_unlock (UDisksEncrypted *encrypted, if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "encrypted-unlock", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -590,6 +591,7 @@ handle_lock (UDisksEncrypted *encrypted, if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "encrypted-lock", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -710,6 +712,7 @@ handle_change_passphrase (UDisksEncrypted *encrypted, passphrases = g_strdup_printf ("%s\n%s", passphrase, new_passphrase); if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "encrypted-modify", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c index b6ed08d..efd030a 100644 --- a/src/udiskslinuxfilesystem.c +++ b/src/udiskslinuxfilesystem.c @@ -1103,9 +1103,9 @@ handle_mount (UDisksFilesystem *filesystem, UDisksBlock *block; UDisksDaemon *daemon; UDisksCleanup *cleanup; - pid_t caller_pid; uid_t caller_uid; gid_t caller_gid; + pid_t caller_pid; const gchar * const *existing_mount_points; const gchar *probed_fs_usage; gchar *fs_type_to_use; @@ -1260,6 +1260,7 @@ handle_mount (UDisksFilesystem *filesystem, mount_fstab_again: if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "filesystem-mount", caller_uid, NULL, /* GCancellable */ mount_fstab_as_root ? 0 : caller_uid, /* uid_t run_as_uid */ mount_fstab_as_root ? 0 : caller_uid, /* uid_t run_as_euid */ @@ -1436,6 +1437,7 @@ handle_mount (UDisksFilesystem *filesystem, /* run mount(8) */ if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "filesystem-mount", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -1601,6 +1603,7 @@ handle_unmount (UDisksFilesystem *filesystem, /* right now -l is the only way to "force unmount" file systems... */ if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "filesystem-unmount", caller_uid, NULL, /* GCancellable */ unmount_fstab_as_root ? 0 : caller_uid, /* uid_t run_as_uid */ unmount_fstab_as_root ? 0 : caller_uid, /* uid_t run_as_euid */ @@ -1698,6 +1701,7 @@ handle_unmount (UDisksFilesystem *filesystem, escaped_mount_point = udisks_daemon_util_escape_and_quote (mount_point); rc = udisks_daemon_launch_spawned_job_sync (daemon, object, + "filesystem-unmount", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -1713,6 +1717,7 @@ handle_unmount (UDisksFilesystem *filesystem, /* mount_point == NULL */ rc = udisks_daemon_launch_spawned_job_sync (daemon, object, + "filesystem-unmount", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -1795,6 +1800,8 @@ handle_set_label (UDisksFilesystem *filesystem, UDisksBaseJob *job; const gchar *action_id; const gchar *message; + uid_t caller_uid; + gid_t caller_gid; pid_t caller_pid; gchar *command; gchar *tmp; @@ -1827,6 +1834,20 @@ handle_set_label (UDisksFilesystem *filesystem, goto out; } + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + probed_fs_usage = udisks_block_get_id_usage (block); probed_fs_type = udisks_block_get_id_type (block); @@ -1931,6 +1952,7 @@ handle_set_label (UDisksFilesystem *filesystem, job = udisks_daemon_launch_spawned_job (daemon, object, + "filesystem-modify", caller_uid, NULL, /* cancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ diff --git a/src/udiskslinuxloop.c b/src/udiskslinuxloop.c index b83babb..d59fa6a 100644 --- a/src/udiskslinuxloop.c +++ b/src/udiskslinuxloop.c @@ -250,6 +250,7 @@ handle_delete (UDisksLoop *loop, if (!udisks_daemon_launch_spawned_job_sync (daemon, NULL, /* UDisksObject */ + "loop-setup", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ diff --git a/src/udiskslinuxpartition.c b/src/udiskslinuxpartition.c index 195554d..07e6ba5 100644 --- a/src/udiskslinuxpartition.c +++ b/src/udiskslinuxpartition.c @@ -225,6 +225,8 @@ handle_set_flags (UDisksPartition *partition, UDisksBlock *partition_table_block = NULL; gchar *command_line = NULL; gint fd = -1; + uid_t caller_uid; + gid_t caller_gid; pid_t caller_pid; GError *error; @@ -251,6 +253,20 @@ handle_set_flags (UDisksPartition *partition, goto out; } + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + partition_table_object = udisks_daemon_find_object (daemon, udisks_partition_get_table (partition)); partition_table = udisks_object_get_partition_table (partition_table_object); partition_table_block = udisks_object_get_block (partition_table_object); @@ -311,6 +327,7 @@ handle_set_flags (UDisksPartition *partition, if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "partition-modify", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -370,6 +387,8 @@ handle_set_name (UDisksPartition *partition, UDisksBlock *partition_table_block = NULL; gchar *command_line = NULL; gint fd = -1; + uid_t caller_uid; + gid_t caller_gid; pid_t caller_pid; GError *error; @@ -396,6 +415,20 @@ handle_set_name (UDisksPartition *partition, goto out; } + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + partition_table_object = udisks_daemon_find_object (daemon, udisks_partition_get_table (partition)); partition_table = udisks_object_get_partition_table (partition_table_object); partition_table_block = udisks_object_get_block (partition_table_object); @@ -461,6 +494,7 @@ handle_set_name (UDisksPartition *partition, if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "partition-modify", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -552,6 +586,8 @@ handle_set_type (UDisksPartition *partition, UDisksBlock *partition_table_block = NULL; gchar *command_line = NULL; gint fd = -1; + uid_t caller_uid; + gid_t caller_gid; pid_t caller_pid; GError *error; @@ -578,6 +614,20 @@ handle_set_type (UDisksPartition *partition, goto out; } + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + partition_table_object = udisks_daemon_find_object (daemon, udisks_partition_get_table (partition)); partition_table = udisks_object_get_partition_table (partition_table_object); partition_table_block = udisks_object_get_block (partition_table_object); @@ -668,6 +718,7 @@ handle_set_type (UDisksPartition *partition, if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "partition-modify", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -725,6 +776,8 @@ handle_delete (UDisksPartition *partition, UDisksPartitionTable *partition_table = NULL; UDisksBlock *partition_table_block = NULL; gchar *command_line = NULL; + uid_t caller_uid; + gid_t caller_gid; pid_t caller_pid; GError *error; @@ -751,6 +804,20 @@ handle_delete (UDisksPartition *partition, goto out; } + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + partition_table_object = udisks_daemon_find_object (daemon, udisks_partition_get_table (partition)); partition_table = udisks_object_get_partition_table (partition_table_object); partition_table_block = udisks_object_get_block (partition_table_object); @@ -784,6 +851,7 @@ handle_delete (UDisksPartition *partition, if (!udisks_daemon_launch_spawned_job_sync (daemon, partition_table_object, + "partition-delete", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ diff --git a/src/udiskslinuxpartitiontable.c b/src/udiskslinuxpartitiontable.c index 055bd30..e95e502 100644 --- a/src/udiskslinuxpartitiontable.c +++ b/src/udiskslinuxpartitiontable.c @@ -291,6 +291,8 @@ handle_create_partition (UDisksPartitionTable *table, gchar *escaped_partition_device = NULL; const gchar *table_type; pid_t caller_pid; + uid_t caller_uid; + gid_t caller_gid; GError *error; error = NULL; @@ -322,6 +324,20 @@ handle_create_partition (UDisksPartitionTable *table, goto out; } + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + action_id = "org.freedesktop.udisks2.modify-device"; /* Translators: Shown in authentication dialog when the user * requests creating a new partition. @@ -502,6 +518,7 @@ handle_create_partition (UDisksPartitionTable *table, if (!udisks_daemon_launch_spawned_job_sync (daemon, object, + "partition-create", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -552,6 +569,7 @@ handle_create_partition (UDisksPartitionTable *table, /* wipe the newly created partition */ if (!udisks_daemon_launch_spawned_job_sync (daemon, partition_object, + "partition-create", caller_uid, NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ diff --git a/src/udiskslinuxswapspace.c b/src/udiskslinuxswapspace.c index 2309c92..29e83e6 100644 --- a/src/udiskslinuxswapspace.c +++ b/src/udiskslinuxswapspace.c @@ -160,6 +160,8 @@ handle_start (UDisksSwapspace *swapspace, UDisksBaseJob *job; GError *error; gchar *escaped_device = NULL; + uid_t caller_uid; + gid_t caller_gid; error = NULL; object = udisks_daemon_util_dup_object (swapspace, &error); @@ -172,6 +174,20 @@ handle_start (UDisksSwapspace *swapspace, daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); block = udisks_object_peek_block (object); + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + if (!udisks_daemon_util_check_authorization_sync (daemon, object, "org.freedesktop.udisks2.manage-swapspace", @@ -190,6 +206,7 @@ handle_start (UDisksSwapspace *swapspace, job = udisks_daemon_launch_spawned_job (daemon, object, + "swapspace-start", caller_uid, NULL, /* cancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ @@ -235,12 +252,29 @@ handle_stop (UDisksSwapspace *swapspace, UDisksDaemon *daemon; UDisksBlock *block; UDisksBaseJob *job; + uid_t caller_uid; + gid_t caller_gid; gchar *escaped_device = NULL; + GError *error = NULL; object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (swapspace))); daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); block = udisks_object_peek_block (object); + error = NULL; + if (!udisks_daemon_util_get_caller_uid_sync (daemon, + invocation, + NULL /* GCancellable */, + &caller_uid, + &caller_gid, + NULL, + &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + goto out; + } + /* Now, check that the user is actually authorized to stop the swap space. * * TODO: want nicer authentication message + special treatment if the @@ -264,6 +298,7 @@ handle_stop (UDisksSwapspace *swapspace, job = udisks_daemon_launch_spawned_job (daemon, object, + "swapspace-stop", caller_uid, NULL, /* cancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ diff --git a/src/udiskssimplejob.c b/src/udiskssimplejob.c index b8bcdf3..d13ef36 100644 --- a/src/udiskssimplejob.c +++ b/src/udiskssimplejob.c @@ -27,6 +27,7 @@ #include "udisksbasejob.h" #include "udiskssimplejob.h" #include "udisks-daemon-marshal.h" +#include "udisksdaemon.h" /** * SECTION:udiskssimplejob @@ -74,6 +75,7 @@ udisks_simple_job_class_init (UDisksSimpleJobClass *klass) /** * udisks_simple_job_new: + * @daemon: A #UDisksDaemon. * @cancellable: A #GCancellable or %NULL. * * Creates a new #UDisksSimpleJob instance. @@ -83,10 +85,13 @@ udisks_simple_job_class_init (UDisksSimpleJobClass *klass) * Returns: A new #UDisksSimpleJob. Free with g_object_unref(). */ UDisksSimpleJob * -udisks_simple_job_new (GCancellable *cancellable) +udisks_simple_job_new (UDisksDaemon *daemon, + GCancellable *cancellable) { + /* g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL); */ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); return UDISKS_SIMPLE_JOB (g_object_new (UDISKS_TYPE_SIMPLE_JOB, + "daemon", daemon, "cancellable", cancellable, NULL)); } diff --git a/src/udiskssimplejob.h b/src/udiskssimplejob.h index c61ca4f..493b008 100644 --- a/src/udiskssimplejob.h +++ b/src/udiskssimplejob.h @@ -30,7 +30,8 @@ G_BEGIN_DECLS #define UDISKS_IS_SIMPLE_JOB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_SIMPLE_JOB)) GType udisks_simple_job_get_type (void) G_GNUC_CONST; -UDisksSimpleJob *udisks_simple_job_new (GCancellable *cancellable); +UDisksSimpleJob *udisks_simple_job_new (UDisksDaemon *daemon, + GCancellable *cancellable); void udisks_simple_job_complete (UDisksSimpleJob *job, gboolean succeess, const gchar *message); diff --git a/src/udisksspawnedjob.c b/src/udisksspawnedjob.c index 41cbc6c..802551f 100644 --- a/src/udisksspawnedjob.c +++ b/src/udisksspawnedjob.c @@ -33,6 +33,7 @@ #include "udisksbasejob.h" #include "udisksspawnedjob.h" #include "udisks-daemon-marshal.h" +#include "udisksdaemon.h" /** * SECTION:udisksspawnedjob @@ -662,6 +663,7 @@ udisks_spawned_job_class_init (UDisksSpawnedJobClass *klass) * @input_string: A string to write to stdin of the spawned program or %NULL. * @run_as_uid: The #uid_t to run the program as. * @run_as_euid: The effective #uid_t to run the program as. + * @daemon: A #UDisksDaemon. * @cancellable: A #GCancellable or %NULL. * * Creates a new #UDisksSpawnedJob instance. @@ -677,15 +679,18 @@ udisks_spawned_job_new (const gchar *command_line, const gchar *input_string, uid_t run_as_uid, uid_t run_as_euid, + UDisksDaemon *daemon, GCancellable *cancellable) { g_return_val_if_fail (command_line != NULL, NULL); + /* g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL); */ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); return UDISKS_SPAWNED_JOB (g_object_new (UDISKS_TYPE_SPAWNED_JOB, "command-line", command_line, "input-string", input_string, "run-as-uid", run_as_uid, "run-as-euid", run_as_euid, + "daemon", daemon, "cancellable", cancellable, NULL)); } diff --git a/src/udisksspawnedjob.h b/src/udisksspawnedjob.h index f14e876..311931a 100644 --- a/src/udisksspawnedjob.h +++ b/src/udisksspawnedjob.h @@ -34,6 +34,7 @@ UDisksSpawnedJob *udisks_spawned_job_new (const gchar *command_li const gchar *input_string, uid_t run_as_uid, uid_t run_as_euid, + UDisksDaemon *daemon, GCancellable *cancellable); const gchar *udisks_spawned_job_get_command_line (UDisksSpawnedJob *job); diff --git a/src/udisksthreadedjob.c b/src/udisksthreadedjob.c index 891171e..2ecf8ce 100644 --- a/src/udisksthreadedjob.c +++ b/src/udisksthreadedjob.c @@ -27,6 +27,7 @@ #include "udisksbasejob.h" #include "udisksthreadedjob.h" #include "udisks-daemon-marshal.h" +#include "udisksdaemon.h" /** * SECTION:udisksthreadedjob @@ -334,6 +335,7 @@ udisks_threaded_job_class_init (UDisksThreadedJobClass *klass) * @job_func: The function to run in another thread. * @user_data: User data to pass to @job_func. * @user_data_free_func: Function to free @user_data with or %NULL. + * @daemon: A #UDisksDaemon. * @cancellable: A #GCancellable or %NULL. * * Creates a new #UDisksThreadedJob instance. @@ -348,13 +350,16 @@ UDisksThreadedJob * udisks_threaded_job_new (UDisksThreadedJobFunc job_func, gpointer user_data, GDestroyNotify user_data_free_func, + UDisksDaemon *daemon, GCancellable *cancellable) { + /* g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL); */ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); return UDISKS_THREADED_JOB (g_object_new (UDISKS_TYPE_THREADED_JOB, "job-func", job_func, "user-data", user_data, "user-data-free-func", user_data_free_func, + "daemon", daemon, "cancellable", cancellable, NULL)); } diff --git a/src/udisksthreadedjob.h b/src/udisksthreadedjob.h index 800fd84..6463e41 100644 --- a/src/udisksthreadedjob.h +++ b/src/udisksthreadedjob.h @@ -33,6 +33,7 @@ GType udisks_threaded_job_get_type (void) G_GNUC_CONST; UDisksThreadedJob *udisks_threaded_job_new (UDisksThreadedJobFunc job_func, gpointer user_data, GDestroyNotify user_data_free_func, + UDisksDaemon *daemon, GCancellable *cancellable); gpointer udisks_threaded_job_get_user_data (UDisksThreadedJob *job); diff --git a/udisks/udisksclient.c b/udisks/udisksclient.c index 6c6e0f6..93ef677 100644 --- a/udisks/udisksclient.c +++ b/udisks/udisksclient.c @@ -2594,6 +2594,58 @@ udisks_client_get_partition_type_for_display (UDisksClient *client, /* ---------------------------------------------------------------------------------------------------- */ +/** + * udisks_client_get_job_description: + * @client: A #UDisksClient. + * @job: A #UDisksJob. + * + * Gets a human-readable and localized text string describing the + * operation of @job. + * + * Returns: A string that should be freed with g_free(). + */ +gchar * +udisks_client_get_job_description (UDisksClient *client, + UDisksJob *job) +{ + static gsize once = 0; + static GHashTable *hash = NULL; + gchar *ret = NULL; + + g_return_val_if_fail (UDISKS_IS_CLIENT (client), NULL); + + if (g_once_init_enter (&once)) + { + hash = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (hash, "ata-smart-selftest", (gpointer) C_("job", "SMART self-test")); + g_hash_table_insert (hash, "drive-eject", (gpointer) C_("job", "Ejecting Medium")); + g_hash_table_insert (hash, "encrypted-unlock", (gpointer) C_("job", "Unlocking Device")); + g_hash_table_insert (hash, "encrypted-lock", (gpointer) C_("job", "Locking Device")); + g_hash_table_insert (hash, "encrypted-modify", (gpointer) C_("job", "Modifying Encrypted Device")); + g_hash_table_insert (hash, "swapspace-start", (gpointer) C_("job", "Starting Swap Device")); + g_hash_table_insert (hash, "swapspace-stop", (gpointer) C_("job", "Stopping Swap Device")); + g_hash_table_insert (hash, "filesystem-mount", (gpointer) C_("job", "Mounting Filesystem")); + g_hash_table_insert (hash, "filesystem-unmount", (gpointer) C_("job", "Unmounting Filesystem")); + g_hash_table_insert (hash, "filesystem-modify", (gpointer) C_("job", "Modifying Filesystem")); + g_hash_table_insert (hash, "format-erase", (gpointer) C_("job", "Erasing Device")); + g_hash_table_insert (hash, "format-mkfs", (gpointer) C_("job", "Creating Filesystem")); + g_hash_table_insert (hash, "loop-setup", (gpointer) C_("job", "Setting Up Loop Device")); + g_hash_table_insert (hash, "partition-modify", (gpointer) C_("job", "Modifying Partition")); + g_hash_table_insert (hash, "partition-delete", (gpointer) C_("job", "Deleting Partition")); + g_hash_table_insert (hash, "partition-create", (gpointer) C_("job", "Creating Partition")); + g_hash_table_insert (hash, "cleanup", (gpointer) C_("job", "Cleaning Up")); + g_once_init_leave (&once, (gsize) 1); + } + + ret = g_strdup (g_hash_table_lookup (hash, udisks_job_get_operation (job))); + if (ret == NULL) + ret = g_strdup_printf (C_("unknown-job", "Unknown (%s)"), udisks_job_get_operation (job)); + + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + static UDisksPartitionTypeInfo * udisks_partition_type_info_new (void) { diff --git a/udisks/udisksclient.h b/udisks/udisksclient.h index 7b716b4..d8d917f 100644 --- a/udisks/udisksclient.h +++ b/udisks/udisksclient.h @@ -125,6 +125,9 @@ const gchar *udisks_client_get_partition_table_subtype_for_display (UDisk const gchar *partition_table_type, const gchar *partition_table_subtype); +gchar *udisks_client_get_job_description (UDisksClient *client, + UDisksJob *job); + /** * UDisksPartitionTypeInfo: * @table_type: A partition table type e.g. 'dos' or 'gpt' -- 2.7.4