[gnome-disk-utility] Add support for ATA secure erase and non-cancelable jobs



commit 1b0499d457d9ebbf37c29c8fea4c6899785f807b
Author: David Zeuthen <zeuthen gmail com>
Date:   Mon Jul 2 17:48:24 2012 -0400

    Add support for ATA secure erase and non-cancelable jobs
    
    http://people.freedesktop.org/~david/gnome-disks-ata-secure-erase.png
    http://people.freedesktop.org/~david/gnome-disks-ata-secure-erase-warning.png
    http://people.freedesktop.org/~david/gnome-disks-ata-secure-erase-confirmation.png
    http://people.freedesktop.org/~david/gnome-disks-ata-secure-erase-progress.png
    
    Signed-off-by: David Zeuthen <zeuthen gmail com>

 src/disks/gduformatdiskdialog.c |  161 +++++++++++++++++++++++++++++++++++----
 src/disks/gduwindow.c           |   25 +++++-
 2 files changed, 169 insertions(+), 17 deletions(-)
---
diff --git a/src/disks/gduformatdiskdialog.c b/src/disks/gduformatdiskdialog.c
index 138162e..3ffb5ca 100644
--- a/src/disks/gduformatdiskdialog.c
+++ b/src/disks/gduformatdiskdialog.c
@@ -38,6 +38,7 @@ enum
   MODEL_COLUMN_ID,
   MODEL_COLUMN_MARKUP,
   MODEL_COLUMN_SEPARATOR,
+  MODEL_COLUMN_SENSITIVE,
   MODEL_N_COLUMNS,
 };
 
@@ -47,6 +48,7 @@ typedef struct
   UDisksObject *object;
   UDisksBlock *block;
   UDisksDrive *drive;
+  UDisksDriveAta *ata;
 
   GtkBuilder *builder;
   GtkWidget *dialog;
@@ -61,6 +63,7 @@ format_disk_data_free (FormatDiskData *data)
   g_object_unref (data->object);
   g_object_unref (data->block);
   g_clear_object (&data->drive);
+  g_clear_object (&data->ata);
   if (data->dialog != NULL)
     {
       gtk_widget_hide (data->dialog);
@@ -101,16 +104,46 @@ separator_func (GtkTreeModel *model,
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static gchar *
+get_erase_duration_string (gint minutes)
+{
+  gchar *s;
+  if (minutes == 510)
+    {
+      gchar *s2 = gdu_utils_format_duration_usec ((minutes - 2) * 60LL * G_USEC_PER_SEC,
+                                                  GDU_FORMAT_DURATION_FLAGS_NONE);
+      /* Translators: Used to convey that something takes at least
+       * some specificed duration but may take longer. The %s is a
+       * time duration e.g. "8 hours and 28 minutes"
+       */
+      s = g_strdup_printf (_("At least %s"), s2);
+      g_free (s2);
+    }
+  else
+    {
+      gchar *s2 = gdu_utils_format_duration_usec (minutes * 60LL * G_USEC_PER_SEC,
+                                                  GDU_FORMAT_DURATION_FLAGS_NONE);
+      /* Translators: Used to convey that something takes
+       * approximately some specificed duration. The %s is a time
+       * duration e.g. "2 hours and 2 minutes"
+       */
+      s = g_strdup_printf (_("Approximately %s"), s2);
+      g_free (s2);
+    }
+  return s;
+}
+
 static void
 populate_erase_combobox (FormatDiskData *data)
 {
   GtkListStore *model;
   GtkCellRenderer *renderer;
-  gchar *s;
+  gchar *s, *s2;
 
   model = gtk_list_store_new (MODEL_N_COLUMNS,
                               G_TYPE_STRING,
                               G_TYPE_STRING,
+                              G_TYPE_BOOLEAN,
                               G_TYPE_BOOLEAN);
   gtk_combo_box_set_model (GTK_COMBO_BOX (data->erase_combobox), GTK_TREE_MODEL (model));
   g_object_unref (model);
@@ -119,6 +152,7 @@ populate_erase_combobox (FormatDiskData *data)
   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (data->erase_combobox), renderer, FALSE);
   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (data->erase_combobox), renderer,
                                   "markup", MODEL_COLUMN_MARKUP,
+                                  "sensitive", MODEL_COLUMN_SENSITIVE,
                                   NULL);
 
   gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (data->erase_combobox),
@@ -131,7 +165,10 @@ populate_erase_combobox (FormatDiskData *data)
                        _("Don't overwrite existing data"),
                        _("Quick"));
   gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
-                                     MODEL_COLUMN_ID, "", MODEL_COLUMN_MARKUP, s, -1);
+                                     MODEL_COLUMN_ID, "",
+                                     MODEL_COLUMN_MARKUP, s,
+                                     MODEL_COLUMN_SENSITIVE, TRUE,
+                                     -1);
   g_free (s);
 
   /* Full */
@@ -139,12 +176,63 @@ populate_erase_combobox (FormatDiskData *data)
                        _("Overwrite existing data with zeroes"),
                        _("Slow"));
   gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
-                                     MODEL_COLUMN_ID, "zero", MODEL_COLUMN_MARKUP, s, -1);
+                                     MODEL_COLUMN_ID, "zero",
+                                     MODEL_COLUMN_MARKUP, s,
+                                     MODEL_COLUMN_SENSITIVE, TRUE,
+                                     -1);
   g_free (s);
 
   /* TODO: include 7-pass and 35-pass (DoD 5220-22 M) */
 
-  /* TODO: include ATA SECURE ERASE */
+  if (data->ata != NULL)
+    {
+      gint erase_minutes, enhanced_erase_minutes;
+      gboolean frozen;
+
+      erase_minutes = udisks_drive_ata_get_security_erase_unit_minutes (data->ata);
+      enhanced_erase_minutes = udisks_drive_ata_get_security_enhanced_erase_unit_minutes (data->ata);
+      frozen = udisks_drive_ata_get_security_frozen (data->ata);
+
+      if (erase_minutes > 0 || enhanced_erase_minutes > 0)
+        {
+          /* separator */
+          gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                             MODEL_COLUMN_SEPARATOR, TRUE,
+                                             MODEL_COLUMN_SENSITIVE, TRUE,
+                                             -1);
+
+          /* if both normal and enhanced erase methods are available, only show the enhanced one */
+          if (erase_minutes > 0 && enhanced_erase_minutes == 0)
+            {
+              s2 = get_erase_duration_string (erase_minutes);
+              s = g_strdup_printf ("%s <span size=\"small\">(%s)</span>",
+                                   _("ATA Secure Erase"),
+                                   s2);
+              gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                                 MODEL_COLUMN_ID, "ata-secure-erase",
+                                                 MODEL_COLUMN_MARKUP, s,
+                                                 MODEL_COLUMN_SENSITIVE, !frozen,
+                                                 -1);
+              g_free (s);
+              g_free (s2);
+            }
+
+          if (enhanced_erase_minutes > 0)
+            {
+              s2 = get_erase_duration_string (enhanced_erase_minutes);
+              s = g_strdup_printf ("%s <span size=\"small\">(%s)</span>",
+                                   _("ATA Enhanced Secure Erase"),
+                                   s2);
+              gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                                 MODEL_COLUMN_ID, "ata-secure-erase-enhanced",
+                                                 MODEL_COLUMN_MARKUP, s,
+                                                 MODEL_COLUMN_SENSITIVE, !frozen,
+                                                 -1);
+              g_free (s);
+              g_free (s2);
+            }
+        }
+    }
 
   gtk_combo_box_set_active_id (GTK_COMBO_BOX (data->erase_combobox), "");
 }
@@ -159,6 +247,7 @@ populate_partitioning_combobox (FormatDiskData *data)
   model = gtk_list_store_new (MODEL_N_COLUMNS,
                               G_TYPE_STRING,
                               G_TYPE_STRING,
+                              G_TYPE_BOOLEAN,
                               G_TYPE_BOOLEAN);
   gtk_combo_box_set_model (GTK_COMBO_BOX (data->type_combobox), GTK_TREE_MODEL (model));
   g_object_unref (model);
@@ -179,7 +268,10 @@ populate_partitioning_combobox (FormatDiskData *data)
                        _("Compatible with all systems and devices"),
                        _("MBR / DOS"));
   gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
-                                     MODEL_COLUMN_ID, "dos", MODEL_COLUMN_MARKUP, s, -1);
+                                     MODEL_COLUMN_ID, "dos",
+                                     MODEL_COLUMN_MARKUP, s,
+                                     MODEL_COLUMN_SENSITIVE, TRUE,
+                                     -1);
   g_free (s);
 
   /* GPT */
@@ -187,12 +279,17 @@ populate_partitioning_combobox (FormatDiskData *data)
                        _("Compatible with modern systems and hard disks > 2TB"),
                        _("GPT"));
   gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
-                                     MODEL_COLUMN_ID, "gpt", MODEL_COLUMN_MARKUP, s, -1);
+                                     MODEL_COLUMN_ID, "gpt",
+                                     MODEL_COLUMN_MARKUP, s,
+                                     MODEL_COLUMN_SENSITIVE, TRUE,
+                                     -1);
   g_free (s);
 
   /* separator */
   gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
-                                     MODEL_COLUMN_SEPARATOR, TRUE, -1);
+                                     MODEL_COLUMN_SEPARATOR, TRUE,
+                                     MODEL_COLUMN_SENSITIVE, TRUE,
+                                     -1);
 
 
   /* Empty */
@@ -200,7 +297,10 @@ populate_partitioning_combobox (FormatDiskData *data)
                        _("No partitioning"),
                        _("Empty"));
   gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
-                                     MODEL_COLUMN_ID, "empty", MODEL_COLUMN_MARKUP, s, -1);
+                                     MODEL_COLUMN_ID, "empty",
+                                     MODEL_COLUMN_MARKUP, s,
+                                     MODEL_COLUMN_SENSITIVE, TRUE,
+                                     -1);
   g_free (s);
 
 
@@ -258,7 +358,15 @@ gdu_format_disk_dialog_show (GduWindow    *window,
   data->block = udisks_object_get_block (object);
   g_assert (data->block != NULL);
   data->drive = udisks_client_get_drive_for_block (gdu_window_get_client (window), data->block);
-
+  if (data->drive != NULL)
+    {
+      GDBusObject *drive_object;
+      drive_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (data->drive));
+      if (drive_object != NULL)
+        {
+          data->ata = udisks_object_get_drive_ata (UDISKS_OBJECT (drive_object));
+        }
+    }
   data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window),
                                                          "format-disk-dialog.ui",
                                                          "format-disk-dialog",
@@ -281,18 +389,43 @@ gdu_format_disk_dialog_show (GduWindow    *window,
     {
       const gchar *partition_table_type;
       const gchar *erase_type;
+      const gchar *primary_message;
       GVariantBuilder options_builder;
+      GString *str;
 
       partition_table_type = gtk_combo_box_get_active_id (GTK_COMBO_BOX (data->type_combobox));
+      erase_type = gtk_combo_box_get_active_id (GTK_COMBO_BOX (data->erase_combobox));
+
+      primary_message = _("Are you sure you want to format the disk?");
+      if (g_strcmp0 (erase_type, "") == 0)
+        {
+          /* Translators: warning used for quick format */
+          str = g_string_new (_("All data on the disk will be lost"));
+        }
+      else
+        {
+          /* Translators: warning used when overwriting data */
+          str = g_string_new (_("All data on the disk will be irrevocably lost and will likely not be recoverable by data recovery services"));
+        }
+
+      if (data->ata != NULL &&
+          (g_strcmp0 (erase_type, "ata-secure-erase") == 0 ||
+           g_strcmp0 (erase_type, "ata-secure-erase-enhanced") == 0))
+        {
+          g_string_append (str, "\n\n");
+          g_string_append (str, _("<b>WARNING</b>: The Secure Erase command may take a very long time to complete, can't be canceled and may not work properly with some hardware. In the worst case, your drive may be rendered unusable or your system may crash or lock up. Before proceeding, please read the article about <a href='https://ata.wiki.kernel.org/index.php/ATA_Secure_Erase'>ATA Secure Erase</a> and make sure you understand the risks"));
+        }
 
       gtk_widget_hide (data->dialog);
       if (!gdu_window_show_confirmation (window,
-                                         _("Are you sure you want to format the disk?"),
-                                         _("All data on the volume will be lost"),
+                                         primary_message,
+                                         str->str,
                                          _("_Format")))
-        goto out;
-
-      erase_type = gtk_combo_box_get_active_id (GTK_COMBO_BOX (data->erase_combobox));
+        {
+          g_string_free (str, TRUE);
+          goto out;
+        }
+      g_string_free (str, TRUE);
 
       g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
       if (strlen (erase_type) > 0)
diff --git a/src/disks/gduwindow.c b/src/disks/gduwindow.c
index 24f7025..cf42032 100644
--- a/src/disks/gduwindow.c
+++ b/src/disks/gduwindow.c
@@ -1713,10 +1713,21 @@ get_job_progress_text (GduWindow *window,
       gchar *s2, *s3;
 
       usec_left = expected_end_time_usec - g_get_real_time ();
-      s2 = gdu_utils_format_duration_usec (usec_left, GDU_FORMAT_DURATION_FLAGS_NONE);
-      s3 = g_strdup_printf (C_("job-remaining", "%s remaining"), s2);
+      if (usec_left < 0)
+        {
+          /* Translators: Shown instead of e.g. "10 seconds remaining" when we've passed
+           * the expected end time...
+           */
+          s3 = g_strdup_printf (C_("job-remaining-exceeded", "Almost done..."));
+        }
+      else
+        {
+          s2 = gdu_utils_format_duration_usec (usec_left, GDU_FORMAT_DURATION_FLAGS_NONE);
+          s3 = g_strdup_printf (C_("job-remaining", "%s remaining"), s2);
+          g_free (s2);
+        }
       s = g_strdup_printf ("<small>%s â %s</small>", desc, s3);
-      g_free (s2);
+      g_free (s3);
     }
   else
     {
@@ -2003,6 +2014,10 @@ update_device_page_for_drive (GduWindow      *window,
           gtk_label_set_text (GTK_LABEL (window->devtab_drive_job_no_progress_label), s);
           g_free (s);
         }
+      if (udisks_job_get_cancelable (job))
+        gtk_widget_show (window->devtab_drive_job_cancel_button);
+      else
+        gtk_widget_hide (window->devtab_drive_job_cancel_button);
     }
   g_list_foreach (jobs, (GFunc) g_object_unref, NULL);
   g_list_free (jobs);
@@ -2367,6 +2382,10 @@ update_device_page_for_block (GduWindow          *window,
           gtk_label_set_text (GTK_LABEL (window->devtab_job_no_progress_label), s);
           g_free (s);
         }
+      if (udisks_job_get_cancelable (job))
+        gtk_widget_show (window->devtab_job_cancel_button);
+      else
+        gtk_widget_hide (window->devtab_job_cancel_button);
     }
   g_list_foreach (jobs, (GFunc) g_object_unref, NULL);
   g_list_free (jobs);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]