[gnome-disk-utility] disk-image-mounter: support partitioned disk images



commit 85042e9a46c0d1b84cbd3971a4411e72081cfe38
Author: David Zeuthen <davidz redhat com>
Date:   Fri May 4 14:24:17 2012 -0400

    disk-image-mounter: support partitioned disk images
    
    ... by mounting all partitions in the disk image.
    
    We ignore partitions with UDISKS_IGNORE=1 just like the desktop
    automounter would... this is for e.g. ISO files for OS installers that
    contain firmware partitions etc.
    
    Signed-off-by: David Zeuthen <davidz redhat com>

 src/disk-image-mounter/main.c |  149 ++++++++++++++++++++++++++--------------
 1 files changed, 97 insertions(+), 52 deletions(-)
---
diff --git a/src/disk-image-mounter/main.c b/src/disk-image-mounter/main.c
index ba0fe72..188def0 100644
--- a/src/disk-image-mounter/main.c
+++ b/src/disk-image-mounter/main.c
@@ -208,15 +208,17 @@ main (int argc, char *argv[])
     {
       const gchar *uri;
       gchar *filename;
-      GUnixFDList *fd_list;
+      GUnixFDList *fd_list = NULL;
       GVariantBuilder options_builder;
       gint fd;
       GError *error;
       gchar *loop_object_path;
       UDisksObject *object;
-      UDisksLoop *loop;
       UDisksFilesystem *filesystem;
+      UDisksPartitionTable *partition_table;
       GFile *file;
+      UDisksLoop *loop = NULL;
+      guint num_mounts = 0;
 
       uri = l->data;
       file = g_file_new_for_commandline_arg (uri);
@@ -226,19 +228,17 @@ main (int argc, char *argv[])
       if (filename == NULL)
         {
           show_error (_("Cannot open `%s' - maybe the volume isn't mounted?"), uri);
-          goto out;
+          goto done_with_image;
         }
 
       fd = open (filename, opt_writable ? O_RDWR : O_RDONLY);
       if (fd == -1)
         {
           show_error (_("Error opening `%s': %m"), filename);
-          g_free (filename);
-          goto out;
+          goto done_with_image;
         }
 
       g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
-      g_variant_builder_add (&options_builder, "{sv}", "no-part-scan", g_variant_new_boolean (TRUE));
       if (!opt_writable)
         g_variant_builder_add (&options_builder, "{sv}", "read-only", g_variant_new_boolean (TRUE));
 
@@ -258,50 +258,112 @@ main (int argc, char *argv[])
           show_error (_("Error attaching disk image: %s (%s, %d)"),
                       error->message, g_quark_to_string (error->domain), error->code);
           g_error_free (error);
-          g_object_unref (fd_list);
-          g_free (filename);
-          goto out;
+          goto done_with_image;
         }
-      g_object_unref (fd_list);
 
       udisks_client_settle (udisks_client);
 
-      /* ... and then mount it */
+      /* ... and then mount whatever is inside it */
       object = udisks_client_peek_object (udisks_client, loop_object_path);
       g_free (loop_object_path);
       g_assert (object != NULL);
       loop = udisks_object_peek_loop (object);
       g_assert (loop != NULL);
       filesystem = udisks_object_peek_filesystem (object);
-      if (filesystem == NULL)
+      partition_table = udisks_object_peek_partition_table (object);
+      if (partition_table != NULL)
+        {
+          GList *partitions, *l;
+          partitions = udisks_client_get_partitions (udisks_client, partition_table);
+          for (l = partitions; l != NULL; l = l->next)
+            {
+              UDisksPartition *partition = UDISKS_PARTITION (l->data);
+              UDisksObject *partition_object;
+              UDisksBlock *partition_block;
+              UDisksFilesystem *partition_filesystem;
+
+              partition_object = (UDisksObject *) g_dbus_interface_get_object (G_DBUS_INTERFACE (partition));
+              if (partition_object == NULL)
+                continue;
+
+              partition_block = udisks_object_peek_block (partition_object);
+              g_assert (partition_block != NULL);
+
+              if (udisks_block_get_hint_ignore (partition_block))
+                continue;
+
+              partition_filesystem = udisks_object_peek_filesystem (partition_object);
+              if (partition_filesystem == NULL)
+                continue;
+
+              error = NULL;
+              if (!udisks_filesystem_call_mount_sync (partition_filesystem,
+                                                      g_variant_new ("a{sv}", NULL), /* options */
+                                                      NULL, /* out_mount_path */
+                                                      NULL, /* cancellable */
+                                                      &error))
+                {
+                  show_error (_("Error mounting filesystem on partition %d of disk image: %s (%s, %d)"),
+                              udisks_partition_get_number (partition),
+                              error->message, g_quark_to_string (error->domain), error->code);
+                  g_error_free (error);
+                  goto done_with_image;
+                }
+              num_mounts++;
+            }
+          g_list_free_full (partitions, g_object_unref);
+        }
+      else
         {
-          show_error (_("The file `%s' does not appear to contain a mountable filesystem"), filename);
-          /* clean up */
+          /* not partitioned */
+          if (filesystem == NULL)
+            {
+              show_error (_("The file `%s' does not appear to contain a mountable filesystem or partition table"), filename);
+              goto done_with_image;
+            }
+
           error = NULL;
-          if (!udisks_loop_call_delete_sync (loop,
-                                             g_variant_new ("a{sv}", NULL), /* options */
-                                             NULL, /* cancellable */
-                                             &error))
+          if (!udisks_filesystem_call_mount_sync (filesystem,
+                                                  g_variant_new ("a{sv}", NULL), /* options */
+                                                  NULL, /* out_mount_path */
+                                                  NULL, /* cancellable */
+                                                  &error))
             {
-              show_error (_("Error cleaning up loop device: %s (%s, %d)"),
+              show_error (_("Error mounting filesystem: %s (%s, %d)"),
                           error->message, g_quark_to_string (error->domain), error->code);
               g_error_free (error);
+              goto done_with_image;
             }
-          g_free (filename);
-          goto out;
+          num_mounts++;
         }
 
-      error = NULL;
-      if (!udisks_filesystem_call_mount_sync (filesystem,
-                                              g_variant_new ("a{sv}", NULL), /* options */
-                                              NULL, /* out_mount_path */
-                                              NULL, /* cancellable */
-                                              &error))
+    done_with_image:
+      /* We arrive here both if it worked or if something failed.
+       *
+       * Now, if we did mount anything, set Autoclear to TRUE to
+       * ensure that the loop device goes bye-bye when the last mount
+       * is unmounted
+       */
+      if (num_mounts > 0)
         {
-          show_error (_("Error mounting filesystem: %s (%s, %d)"),
-                      error->message, g_quark_to_string (error->domain), error->code);
-          g_error_free (error);
-          /* clean up */
+          error = NULL;
+          if (!udisks_loop_call_set_autoclear_sync (loop,
+                                                    TRUE,
+                                                    g_variant_new ("a{sv}", NULL), /* options */
+                                                    NULL, /* cancellable */
+                                                    &error))
+            {
+              /* this is not fatal but can happen when using FUSE crap where uid 0 is
+               * not permitted to view files on a FUSE mount
+               */
+              g_printerr (_("Non-fatal error: error setting autoclear to TRUE: %s (%s, %d)\n"),
+                          error->message, g_quark_to_string (error->domain), error->code);
+              g_error_free (error);
+            }
+        }
+      else if (loop != NULL)
+        {
+          /* otherwise, if we didn't mount anything, nuke the loop device */
           error = NULL;
           if (!udisks_loop_call_delete_sync (loop,
                                              g_variant_new ("a{sv}", NULL), /* options */
@@ -312,34 +374,17 @@ main (int argc, char *argv[])
                           error->message, g_quark_to_string (error->domain), error->code);
               g_error_free (error);
             }
-          g_free (filename);
-          goto out;
-        }
-
-      /* Finally set autoclear to TRUE so the loop device will get removed
-       * when the filesystem is unmounted
-       */
-      error = NULL;
-      if (!udisks_loop_call_set_autoclear_sync (loop,
-                                                TRUE,
-                                                g_variant_new ("a{sv}", NULL), /* options */
-                                                NULL, /* cancellable */
-                                                &error))
-        {
-          /* this is not fatal but can happen when using FUSE crap where uid 0 is
-           * not permitted to view files on a FUSE mount
-           */
-          g_printerr (_("Non-fatal error: error setting autoclear to TRUE: %s (%s, %d)\n"),
-                      error->message, g_quark_to_string (error->domain), error->code);
-          g_error_free (error);
         }
 
+      g_clear_object (&fd_list);
       g_free (filename);
-    }
+
+    } /* for each image */
 
   ret = 0;
 
  out:
+
   g_slist_free_full (uris, g_free);
   g_clear_object (&udisks_client);
   return ret;



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