static void edit_partition_update (EditPartitionData *data) { gboolean differs = FALSE; gchar *type; gchar *name; guint64 flags; edit_partition_get (data, &type, &name, &flags); if (g_strcmp0 (udisks_partition_get_type_ (data->partition), type) != 0) differs = TRUE; if (g_strcmp0 (udisks_partition_get_name (data->partition), name) != 0) differs = TRUE; if (udisks_partition_get_flags (data->partition) != flags) differs = TRUE; gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, differs); g_free (type); g_free (name); }
void gdu_partition_dialog_show (GduWindow *window, UDisksObject *object) { EditPartitionData *data; gint response; data = g_new0 (EditPartitionData, 1); data->window = g_object_ref (window); data->object = g_object_ref (object); data->partition = udisks_object_get_partition (object); g_assert (data->partition != NULL); data->partition_table = udisks_client_get_partition_table (gdu_window_get_client (window), data->partition); g_assert (data->partition_table != NULL); data->partition_table_type = udisks_partition_table_dup_type_ (data->partition_table); if (g_strcmp0 (data->partition_table_type, "gpt") == 0) { data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window), "edit-gpt-partition-dialog.ui", "edit-gpt-partition-dialog", &data->builder)); data->name_entry = GTK_WIDGET (gtk_builder_get_object (data->builder, "name-entry")); data->system_checkbutton = GTK_WIDGET (gtk_builder_get_object (data->builder, "system-checkbutton")); data->hide_from_firmware_checkbutton = GTK_WIDGET (gtk_builder_get_object (data->builder, "hide-from-firmware-checkbutton")); data->bootable_checkbutton = GTK_WIDGET (gtk_builder_get_object (data->builder, "bootable-checkbutton")); g_signal_connect (data->name_entry, "notify::text", G_CALLBACK (edit_partition_property_changed), data); g_signal_connect (data->system_checkbutton, "notify::active", G_CALLBACK (edit_partition_property_changed), data); g_signal_connect (data->hide_from_firmware_checkbutton, "notify::active", G_CALLBACK (edit_partition_property_changed), data); g_signal_connect (data->bootable_checkbutton, "notify::active", G_CALLBACK (edit_partition_property_changed), data); } else if (g_strcmp0 (data->partition_table_type, "dos") == 0) { data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window), "edit-dos-partition-dialog.ui", "edit-dos-partition-dialog", &data->builder)); data->bootable_checkbutton = GTK_WIDGET (gtk_builder_get_object (data->builder, "bootable-checkbutton")); g_signal_connect (data->bootable_checkbutton, "notify::active", G_CALLBACK (edit_partition_property_changed), data); } else { data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window), "edit-partition-dialog.ui", "edit-partition-dialog", &data->builder)); } data->type_combobox = GTK_WIDGET (gtk_builder_get_object (data->builder, "type-combobox")); g_signal_connect (data->type_combobox, "notify::active", G_CALLBACK (edit_partition_property_changed), data); gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (window)); gtk_dialog_set_default_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK); edit_partition_populate (data); edit_partition_update (data); gtk_widget_show_all (data->dialog); gtk_widget_grab_focus (data->type_combobox); /* TODO: do this async */ response = gtk_dialog_run (GTK_DIALOG (data->dialog)); if (response == GTK_RESPONSE_OK) { gchar *type; gchar *name; guint64 flags; GError *error; edit_partition_get (data, &type, &name, &flags); if (g_strcmp0 (udisks_partition_get_type_ (data->partition), type) != 0) { error = NULL; if (!udisks_partition_call_set_type_sync (data->partition, type, g_variant_new ("a{sv}", NULL), /* options */ NULL, /* GCancellable */ &error)) { gdu_utils_show_error (GTK_WINDOW (window), _("Error setting partition type"), error); g_error_free (error); goto set_out; } } if (g_strcmp0 (udisks_partition_get_name (data->partition), name) != 0) { error = NULL; if (!udisks_partition_call_set_name_sync (data->partition, name, g_variant_new ("a{sv}", NULL), /* options */ NULL, /* GCancellable */ &error)) { gdu_utils_show_error (GTK_WINDOW (window), _("Error setting partition name"), error); g_error_free (error); goto set_out; } } if (udisks_partition_get_flags (data->partition) != flags) { error = NULL; if (!udisks_partition_call_set_flags_sync (data->partition, flags, g_variant_new ("a{sv}", NULL), /* options */ NULL, /* GCancellable */ &error)) { gdu_utils_show_error (GTK_WINDOW (window), _("Error setting partition flags"), error); g_error_free (error); goto set_out; } } set_out: g_free (type); g_free (name); } edit_partition_data_free (data); }
static void edit_partition_populate (EditPartitionData *data) { const gchar *cur_type; GList *l; guint n; GtkTreeIter *active_iter = NULL; GtkListStore *model; GList *infos; const gchar *cur_table_subtype; UDisksClient *client; GtkCellRenderer *renderer; client = gdu_window_get_client (data->window); model = gtk_list_store_new (MODEL_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING); cur_type = udisks_partition_get_type_ (data->partition); infos = udisks_client_get_partition_type_infos (client, data->partition_table_type, NULL); /* assume that table subtypes are in order */ cur_table_subtype = NULL; for (l = infos, n = 0; l != NULL; l = l->next, n++) { UDisksPartitionTypeInfo *info = l->data; const gchar *type_for_display; gchar *escaped_type_for_display; gchar *s; GtkTreeIter iter; /* skip type like 'Extended Partition' (dos 0x05) since we can't * just change the partition type to that */ if (info->flags & UDISKS_PARTITION_TYPE_INFO_FLAGS_CREATE_ONLY) continue; if (g_strcmp0 (info->table_subtype, cur_table_subtype) != 0) { s = g_strdup_printf ("<i>%s</i>", udisks_client_get_partition_table_subtype_for_display (client, info->table_type, info->table_subtype)); gtk_list_store_insert_with_values (model, NULL, /* out iter */ G_MAXINT, /* position */ MODEL_COLUMN_SELECTABLE, FALSE, MODEL_COLUMN_NAME_MARKUP, s, MODEL_COLUMN_TYPE, NULL, -1); g_free (s); cur_table_subtype = info->table_subtype; } #if UDISKS_CHECK_VERSION(2, 1, 1) type_for_display = udisks_client_get_partition_type_and_subtype_for_display (client, data->partition_table_type, info->table_subtype, info->type); #else type_for_display = udisks_client_get_partition_type_for_display (client, data->partition_table_type, info->type); #endif escaped_type_for_display = g_markup_escape_text (type_for_display, -1); s = g_strdup_printf ("%s <span size=\"small\">(%s)</span>", escaped_type_for_display, info->type); g_free (escaped_type_for_display); gtk_list_store_insert_with_values (model, &iter, G_MAXINT, /* position */ MODEL_COLUMN_SELECTABLE, TRUE, MODEL_COLUMN_NAME_MARKUP, s, MODEL_COLUMN_TYPE, info->type, -1); if (active_iter == NULL && g_strcmp0 (info->type, cur_type) == 0) active_iter = gtk_tree_iter_copy (&iter); g_free (s); } gtk_combo_box_set_model (GTK_COMBO_BOX (data->type_combobox), GTK_TREE_MODEL (model)); if (active_iter != NULL) { gtk_combo_box_set_active_iter (GTK_COMBO_BOX (data->type_combobox), active_iter); gtk_tree_iter_free (active_iter); } renderer = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (data->type_combobox), renderer, FALSE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (data->type_combobox), renderer, "sensitive", MODEL_COLUMN_SELECTABLE, "markup", MODEL_COLUMN_NAME_MARKUP, NULL); if (g_strcmp0 (data->partition_table_type, "gpt") == 0) { guint64 flags; gtk_entry_set_text (GTK_ENTRY (data->name_entry), udisks_partition_get_name (data->partition)); flags = udisks_partition_get_flags (data->partition); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->system_checkbutton), (flags & (1UL<< 0)) != 0); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->hide_from_firmware_checkbutton), (flags & (1UL<< 1)) != 0); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->bootable_checkbutton), (flags & (1UL<< 2)) != 0); } else if (g_strcmp0 (data->partition_table_type, "dos") == 0) { guint64 flags; flags = udisks_partition_get_flags (data->partition); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->bootable_checkbutton), (flags & (1UL<< 7)) != 0); } g_list_foreach (infos, (GFunc) udisks_partition_type_info_free, NULL); g_list_free (infos); g_object_unref (model); }
/** * udisks_daemon_util_check_authorization_sync: * @daemon: A #UDisksDaemon. * @object: (allow-none): The #GDBusObject that the call is on or %NULL. * @action_id: The action id to check for. * @options: (allow-none): A #GVariant to check for the <quote>auth.no_user_interaction</quote> option or %NULL. * @message: The message to convey (use N_). * @invocation: The invocation to check for. * * Checks if the caller represented by @invocation is authorized for * the action identified by @action_id, optionally displaying @message * if authentication is needed. Additionally, if the caller is not * authorized, the appropriate error is already returned to the caller * via @invocation. * * The calling thread is blocked for the duration of the authorization * check which could be a very long time since it may involve * presenting an authentication dialog and having a human user use * it. If <quote>auth.no_user_interaction</quote> in @options is %TRUE * no authentication dialog will be presented and the check is not * expected to take a long time. * * See <xref linkend="udisks-polkit-details"/> for the variables that * can be used in @message but note that not all variables can be used * in all checks. For example, any check involving a #UDisksDrive or a * #UDisksBlock object can safely include the fragment * <quote>$(drive)</quote> since it will always expand to the name of * the drive, e.g. <quote>INTEL SSDSA2MH080G1GC (/dev/sda1)</quote> or * the block device file e.g. <quote>/dev/vg_lucifer/lv_root</quote> * or <quote>/dev/sda1</quote>. However this won't work for operations * that isn't on a drive or block device, for example calls on the * <link linkend="gdbus-interface-org-freedesktop-UDisks2-Manager.top_of_page">Manager</link> * object. * * Returns: %TRUE if caller is authorized, %FALSE if not. */ gboolean udisks_daemon_util_check_authorization_sync (UDisksDaemon *daemon, UDisksObject *object, const gchar *action_id, GVariant *options, const gchar *message, GDBusMethodInvocation *invocation) { PolkitAuthority *authority = NULL; PolkitSubject *subject = NULL; PolkitDetails *details = NULL; PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; PolkitAuthorizationResult *result = NULL; GError *error = NULL; gboolean ret = FALSE; UDisksBlock *block = NULL; UDisksDrive *drive = NULL; UDisksPartition *partition = NULL; UDisksObject *block_object = NULL; UDisksObject *drive_object = NULL; gboolean auth_no_user_interaction = FALSE; const gchar *details_device = NULL; gchar *details_drive = NULL; authority = udisks_daemon_get_authority (daemon); if (authority == NULL) { ret = check_authorization_no_polkit (daemon, object, action_id, options, message, invocation); goto out; } subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (invocation)); if (options != NULL) { g_variant_lookup (options, "auth.no_user_interaction", "b", &auth_no_user_interaction); } if (!auth_no_user_interaction) flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION; details = polkit_details_new (); polkit_details_insert (details, "polkit.message", message); polkit_details_insert (details, "polkit.gettext_domain", "udisks2"); /* Find drive associated with the block device, if any */ if (object != NULL) { block = udisks_object_get_block (object); if (block != NULL) { block_object = g_object_ref (object); drive_object = udisks_daemon_find_object (daemon, udisks_block_get_drive (block)); if (drive_object != NULL) drive = udisks_object_get_drive (drive_object); } partition = udisks_object_get_partition (object); if (drive == NULL) drive = udisks_object_get_drive (object); } if (block != NULL) details_device = udisks_block_get_preferred_device (block); /* If we have a drive, use vendor/model in the message (in addition to Block:preferred-device) */ if (drive != NULL) { gchar *s; const gchar *vendor; const gchar *model; vendor = udisks_drive_get_vendor (drive); model = udisks_drive_get_model (drive); if (vendor == NULL) vendor = ""; if (model == NULL) model = ""; if (strlen (vendor) > 0 && strlen (model) > 0) s = g_strdup_printf ("%s %s", vendor, model); else if (strlen (vendor) > 0) s = g_strdup (vendor); else s = g_strdup (model); if (block != NULL) { details_drive = g_strdup_printf ("%s (%s)", s, udisks_block_get_preferred_device (block)); } else { details_drive = s; s = NULL; } g_free (s); _safe_polkit_details_insert (details, "drive.wwn", udisks_drive_get_wwn (drive)); _safe_polkit_details_insert (details, "drive.serial", udisks_drive_get_serial (drive)); _safe_polkit_details_insert (details, "drive.vendor", udisks_drive_get_vendor (drive)); _safe_polkit_details_insert (details, "drive.model", udisks_drive_get_model (drive)); _safe_polkit_details_insert (details, "drive.revision", udisks_drive_get_revision (drive)); if (udisks_drive_get_removable (drive)) { const gchar *const *media_compat; GString *media_compat_str; const gchar *sep = ","; polkit_details_insert (details, "drive.removable", "true"); _safe_polkit_details_insert (details, "drive.removable.bus", udisks_drive_get_connection_bus (drive)); media_compat_str = g_string_new (NULL); media_compat = udisks_drive_get_media_compatibility (drive); if (media_compat) { guint i; for (i = 0; media_compat[i] && strlen(media_compat[i]); i++) { if (i) g_string_append (media_compat_str, sep); g_string_append (media_compat_str, media_compat[i]); } } _safe_polkit_details_insert (details, "drive.removable.media", media_compat_str->str); g_string_free (media_compat_str, TRUE); } } if (block != NULL) { _safe_polkit_details_insert (details, "id.type", udisks_block_get_id_type (block)); _safe_polkit_details_insert (details, "id.usage", udisks_block_get_id_usage (block)); _safe_polkit_details_insert (details, "id.version", udisks_block_get_id_version (block)); _safe_polkit_details_insert (details, "id.label", udisks_block_get_id_label (block)); _safe_polkit_details_insert (details, "id.uuid", udisks_block_get_id_uuid (block)); } if (partition != NULL) { _safe_polkit_details_insert_int (details, "partition.number", udisks_partition_get_number (partition)); _safe_polkit_details_insert (details, "partition.type", udisks_partition_get_type_ (partition)); _safe_polkit_details_insert_uint64 (details, "partition.flags", udisks_partition_get_flags (partition)); _safe_polkit_details_insert (details, "partition.name", udisks_partition_get_name (partition)); _safe_polkit_details_insert (details, "partition.uuid", udisks_partition_get_uuid (partition)); } /* Fall back to Block:preferred-device */ if (details_drive == NULL && block != NULL) details_drive = udisks_block_dup_preferred_device (block); if (details_device != NULL) polkit_details_insert (details, "device", details_device); if (details_drive != NULL) polkit_details_insert (details, "drive", details_drive); error = NULL; result = polkit_authority_check_authorization_sync (authority, subject, action_id, details, flags, NULL, /* GCancellable* */ &error); if (result == NULL) { if (error->domain != POLKIT_ERROR) { /* assume polkit authority is not available (e.g. could be the service * manager returning org.freedesktop.systemd1.Masked) */ g_error_free (error); ret = check_authorization_no_polkit (daemon, object, action_id, options, message, invocation); } else { g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED, "Error checking authorization: %s (%s, %d)", error->message, g_quark_to_string (error->domain), error->code); g_error_free (error); } goto out; } if (!polkit_authorization_result_get_is_authorized (result)) { if (polkit_authorization_result_get_dismissed (result)) g_dbus_method_invocation_return_error_literal (invocation, UDISKS_ERROR, UDISKS_ERROR_NOT_AUTHORIZED_DISMISSED, "The authentication dialog was dismissed"); else g_dbus_method_invocation_return_error_literal (invocation, UDISKS_ERROR, polkit_authorization_result_get_is_challenge (result) ? UDISKS_ERROR_NOT_AUTHORIZED_CAN_OBTAIN : UDISKS_ERROR_NOT_AUTHORIZED, "Not authorized to perform operation"); goto out; } ret = TRUE; out: g_free (details_drive); g_clear_object (&block_object); g_clear_object (&drive_object); g_clear_object (&block); g_clear_object (&partition); g_clear_object (&drive); g_clear_object (&subject); g_clear_object (&details); g_clear_object (&result); return ret; }