Make sure that Drive:SortKey sorts e.g. sdz before sdaa
authorDavid Zeuthen <davidz@redhat.com>
Thu, 26 Jan 2012 16:04:47 +0000 (11:04 -0500)
committerDavid Zeuthen <davidz@redhat.com>
Thu, 26 Jan 2012 16:04:47 +0000 (11:04 -0500)
Also make sure that we e.g. process sdb before sdad to get
Drive:SortKey set using sdb rather than sdad.

With this change we get the expected output that corresponds to kernel
probing order. Which (on good days) may correspond to slot and
enclosure order.

MODEL                     REVISION  SERIAL               DEVICE
--------------------------------------------------------------------------
HP LOGICAL VOLUME         3.00      5001438008F61790     sda
SEAGATE ST3300657SS       0006      3SJ1S7K600009051M0CE sdad sdb
SEAGATE ST3300657SS       0006      3SJ1S4MH00009052RG6Z sdae sdc
SEAGATE ST3300657SS       0006      3SJ1RFP900009051HZ5S sdaf sdd
SEAGATE ST3300657SS       0006      3SJ1S66L00009052QGZA sdag sde
SEAGATE ST3300657SS       0006      3SJ1RPFJ00009052BZ10 sdah sdf
SEAGATE ST3300657SS       0006      3SJ1RWZ100009101T12H sdai sdg
SEAGATE ST3300657SS       0006      3SJ1S7C500009052RKPP sdaj sdh
SEAGATE ST3300657SS       0006      3SJ1S40K00009101T1XU sdak sdi
SEAGATE ST3300657SS       0006      3SJ1RJS700009050VYEA sdal sdj
SEAGATE ST3300657SS       0006      3SJ1RSJC00009052MWTB sdam sdk
SEAGATE ST3300657SS       0006      3SJ1QNMQ00009052NECM sdan sdl
SEAGATE ST3300657SS       0006      3SJ1S3NE00009101TB5Y sdao sdm
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30012560      sdn
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30064749      sdo
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30039741      sdp
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30064055      sdq
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30030732      sdr
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30010853      sds
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30024753      sdt
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30065104      sdu
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30031826      sdv
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30025874      sdw
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30063724      sdx
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30064486      sdy
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30032003      sdz
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30021345      sdaa
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30067287      sdab
WDC WD1002FAEX-00Y9A0     01.01V10  WD-WCAW30014347      sdac

Signed-off-by: David Zeuthen <davidz@redhat.com>
src/udiskslinuxdrive.c
src/udiskslinuxprovider.c

index 46e3e4e..eb2ca08 100644 (file)
@@ -402,6 +402,30 @@ set_media_time_detected (UDisksLinuxDrive *drive,
   udisks_drive_set_time_media_detected (iface, drive->time_media_detected);
 }
 
+static gchar *
+append_fixedup_sd (const gchar *prefix,
+                   const gchar *device_name)
+{
+  guint num_alphas, n;
+  GString *str;
+
+  g_return_val_if_fail (g_str_has_prefix (device_name, "sd"), NULL);
+
+  /* make sure sdaa comes after e.g. sdz by inserting up to 5 '_' characters
+   * between sd and a in sda...
+   */
+  for (num_alphas = 0; g_ascii_isalpha (device_name[num_alphas + 2]); num_alphas++)
+    ;
+  str = g_string_new (prefix);
+  g_string_append (str, "sd");
+  for (n = 0; n < 5 - num_alphas; n++)
+    g_string_append_c (str, '_');
+
+  g_string_append (str, device_name + 2);
+
+  return g_string_free (str, FALSE);
+}
+
 /**
  * udisks_linux_drive_update:
  * @drive: A #UDisksLinuxDrive.
@@ -606,15 +630,28 @@ udisks_linux_drive_update (UDisksLinuxDrive       *drive,
             {
               /* make sure fd* BEFORE sr* BEFORE sd* */
               if (g_str_has_prefix (device_name, "fd"))
-                drive->sort_key = g_strdup_printf ("00coldplug/10removable/%s", device_name);
+                {
+                  drive->sort_key = g_strdup_printf ("00coldplug/10removable/%s", device_name);
+                }
               else if (g_str_has_prefix (device_name, "sr"))
-                drive->sort_key = g_strdup_printf ("00coldplug/11removable/%s", device_name);
+                {
+                  drive->sort_key = g_strdup_printf ("00coldplug/11removable/%s", device_name);
+                }
+              else if (g_str_has_prefix (device_name, "sd"))
+                {
+                  drive->sort_key = append_fixedup_sd ("00coldplug/12removable/", device_name);
+                }
               else
-                drive->sort_key = g_strdup_printf ("00coldplug/12removable/%s", device_name);
+                {
+                  drive->sort_key = g_strdup_printf ("00coldplug/12removable/%s", device_name);
+                }
             }
           else
             {
-              drive->sort_key = g_strdup_printf ("00coldplug/00fixed/%s", device_name);
+              if (g_str_has_prefix (device_name, "sd"))
+                drive->sort_key = append_fixedup_sd ("00coldplug/00fixed/", device_name);
+              else
+                drive->sort_key = g_strdup_printf ("00coldplug/00fixed/%s", device_name);
             }
         }
       else
index 70bde48..1dd4db5 100644 (file)
@@ -163,6 +163,42 @@ udisks_linux_provider_init (UDisksLinuxProvider *provider)
                     provider);
 }
 
+static guint
+count_alphas (const gchar *str)
+{
+  guint n = 0;
+  while (g_ascii_isalpha (str[n]))
+    n++;
+  return n;
+}
+
+static gint
+device_name_cmp (const gchar *a,
+                 const gchar *b)
+{
+  /* Ensures that sda comes before sdz%d and sdz%d comes before sdaa%d */
+  if (g_str_has_prefix (a, "sd") && g_str_has_prefix (b, "sd"))
+    {
+      gint la = count_alphas (a);
+      gint lb = count_alphas (b);
+      if (la != lb)
+        return la - lb;
+      else
+        return g_strcmp0 (a, b);
+    }
+  else
+    {
+      return g_strcmp0 (a, b);
+    }
+}
+
+static gint
+udev_device_name_cmp (GUdevDevice *a,
+                      GUdevDevice *b)
+{
+  return device_name_cmp (g_udev_device_get_name (a), g_udev_device_get_name (b));
+}
+
 static void
 udisks_linux_provider_start (UDisksProvider *_provider)
 {
@@ -201,6 +237,8 @@ udisks_linux_provider_start (UDisksProvider *_provider)
                                                          NULL);
 
   devices = g_udev_client_query_by_subsystem (provider->gudev_client, "block");
+  /* make sure we process sda before sdz and sdz before sdaa */
+  devices = g_list_sort (devices, (GCompareFunc) udev_device_name_cmp);
   for (l = devices; l != NULL; l = l->next)
     udisks_linux_provider_handle_uevent (provider, "add", G_UDEV_DEVICE (l->data));
   g_list_foreach (devices, (GFunc) g_object_unref, NULL);