[gnome-disk-utility] Add "Disk Image Mounter" utility and associate with application/x-cd-image
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility] Add "Disk Image Mounter" utility and associate with application/x-cd-image
- Date: Tue, 1 May 2012 23:35:22 +0000 (UTC)
commit 2794ee121829d656d460da58c0ecaa84271e6fe7
Author: David Zeuthen <davidz redhat com>
Date: Tue May 1 19:26:28 2012 -0400
Add "Disk Image Mounter" utility and associate with application/x-cd-image
The MINE association makes the utility show up in Nautilus for .iso
files... basically, if you open an ISO file (or even a selection of
multiple ISO files) with this tool through Nautilus the right thing
happens... that is, for each ISO file, a loop device is created and
its filesystem is mounted. This results in a set of GVolume/GMount
objects in Nautilus' sidebar and the shell will run its sniffing
machinery and ask if you want to e.g. watch the DVD movie.
Additionally, the loop.autoclear option is used so the loop device
goes away when the loop device is unmounted.
Signed-off-by: David Zeuthen <davidz redhat com>
configure.ac | 1 +
data/Makefile.am | 2 +-
data/gnome-disk-image-mounter.desktop.in | 10 +
po/POTFILES.in | 2 +
src/Makefile.am | 2 +-
src/gnome-disk-image-mounter/Makefile.am | 33 +++
src/gnome-disk-image-mounter/main.c | 324 ++++++++++++++++++++++++++++++
7 files changed, 372 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 5bf50fe..08a8aba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -78,6 +78,7 @@ AC_CONFIG_FILES([
Makefile
src/Makefile
src/palimpsest/Makefile
+src/gnome-disk-image-mounter/Makefile
po/Makefile.in
data/Makefile
data/icons/Makefile
diff --git a/data/Makefile.am b/data/Makefile.am
index 9a15d39..53df243 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -3,7 +3,7 @@ NULL =
SUBDIRS = ui icons
desktopdir = $(datadir)/applications
-desktop_in_files = palimpsest.desktop.in
+desktop_in_files = palimpsest.desktop.in gnome-disk-image-mounter.desktop.in
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
@INTLTOOL_DESKTOP_RULE@
diff --git a/data/gnome-disk-image-mounter.desktop.in b/data/gnome-disk-image-mounter.desktop.in
new file mode 100644
index 0000000..475d071
--- /dev/null
+++ b/data/gnome-disk-image-mounter.desktop.in
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Disk Image Mounter
+Exec=gnome-disk-image-mounter attach %u
+Icon=drive-removable-media
+MimeType=application/x-cd-image
+Terminal=false
+StartupNotify=false
+Type=Application
+NoDisplay=true
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a857840..c21ecce 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,6 +1,7 @@
[encoding: UTF-8]
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
+data/gnome-disk-image-mounter.desktop.in
data/palimpsest.desktop.in
[type: gettext/glade]data/ui/about-dialog.ui
[type: gettext/glade]data/ui/app-menu.ui
@@ -20,6 +21,7 @@ data/palimpsest.desktop.in
[type: gettext/glade]data/ui/restore-disk-image-dialog.ui
[type: gettext/glade]data/ui/smart-dialog.ui
[type: gettext/glade]data/ui/unlock-device-dialog.ui
+src/gnome-disk-image-mounter/main.c
src/palimpsest/gduapplication.c
src/palimpsest/gduatasmartdialog.c
src/palimpsest/gduchangepassphrasedialog.c
diff --git a/src/Makefile.am b/src/Makefile.am
index e851430..39fa482 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = palimpsest
+SUBDIRS = palimpsest gnome-disk-image-mounter
clean-local :
rm -f *~
diff --git a/src/gnome-disk-image-mounter/Makefile.am b/src/gnome-disk-image-mounter/Makefile.am
new file mode 100644
index 0000000..29fc1dc
--- /dev/null
+++ b/src/gnome-disk-image-mounter/Makefile.am
@@ -0,0 +1,33 @@
+
+NULL =
+
+bin_PROGRAMS = gnome-disk-image-mounter
+
+gnome_disk_image_mounter_SOURCES = \
+ main.c \
+ $(NULL)
+
+gnome_disk_image_mounter_CPPFLAGS = \
+ -I$(top_srcdir)/src/ \
+ -I$(top_builddir)/src/ \
+ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+ -DG_LOG_DOMAIN=\"gnome-disk-image-mounter\" \
+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+ -DUDISKS_API_IS_SUBJECT_TO_CHANGE \
+ $(NULL)
+
+gnome_disk_image_mounter_CFLAGS = \
+ $(GLIB2_CFLAGS) \
+ $(UDISKS2_CFLAGS) \
+ $(GTK3_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(NULL)
+
+gnome_disk_image_mounter_LDADD = \
+ $(GLIB2_LIBS) \
+ $(UDISKS2_LIBS) \
+ $(GTK3_LIBS) \
+ $(NULL)
+
+clean-local :
+ rm -f *~
diff --git a/src/gnome-disk-image-mounter/main.c b/src/gnome-disk-image-mounter/main.c
new file mode 100644
index 0000000..94d8251
--- /dev/null
+++ b/src/gnome-disk-image-mounter/main.c
@@ -0,0 +1,324 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+#include <glib/gi18n.h>
+
+#include <glib-unix.h>
+#include <gio/gunixfdlist.h>
+
+#include <gtk/gtk.h>
+
+#include <udisks/udisks.h>
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean have_gtk = FALSE;
+static UDisksClient *udisks_client = NULL;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+usage (gint *argc, gchar **argv[], gboolean use_stdout)
+{
+ GOptionContext *o;
+ gchar *s;
+ gchar *program_name;
+
+ o = g_option_context_new (_("COMMAND"));
+ g_option_context_set_help_enabled (o, FALSE);
+ /* Ignore parsing result */
+ g_option_context_parse (o, argc, argv, NULL);
+ program_name = g_path_get_basename ((*argv)[0]);
+ s = g_strdup_printf (_("Commands:\n"
+ " help Shows this information\n"
+ " attach Attach and mount one or more disk image files\n"
+ "\n"
+ "Use \"%s COMMAND --help\" to get help on each command.\n"),
+ program_name);
+ g_free (program_name);
+ g_option_context_set_description (o, s);
+ g_free (s);
+ s = g_option_context_get_help (o, FALSE, NULL);
+ if (use_stdout)
+ g_print ("%s", s);
+ else
+ g_printerr ("%s", s);
+ g_free (s);
+ g_option_context_free (o);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+remove_arg (gint num, gint *argc, gchar **argv[])
+{
+ gint n;
+
+ g_assert (num <= (*argc));
+
+ for (n = num; (*argv)[n] != NULL; n++)
+ (*argv)[n] = (*argv)[n+1];
+ (*argv)[n] = NULL;
+ (*argc) = (*argc) - 1;
+}
+
+static void
+modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
+{
+ gchar *s;
+ gchar *program_name;
+
+ /* TODO:
+ * 1. get a g_set_prgname() ?; or
+ * 2. save old argv[0] and restore later
+ */
+
+ g_assert (g_strcmp0 ((*argv)[1], command) == 0);
+ remove_arg (1, argc, argv);
+
+ program_name = g_path_get_basename ((*argv)[0]);
+ s = g_strdup_printf ("%s %s", (*argv)[0], command);
+ (*argv)[0] = s;
+ g_free (program_name);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+show_error (const gchar *format, ...)
+{
+ va_list var_args;
+ gchar *s;
+
+ va_start (var_args, format);
+
+ s = g_strdup_vprintf (format, var_args);
+
+ if (have_gtk)
+ {
+ GtkWidget *dialog;
+ dialog = gtk_message_dialog_new_with_markup (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "<big><b>%s</b></big>",
+ _("An error occurred"));
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), s);
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Disk Image Mounter"));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
+ else
+ {
+ g_printerr ("%s\n", s);
+ }
+
+ g_free (s);
+ va_end (var_args);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean opt_attach_writable = FALSE;
+
+static const GOptionEntry attach_entries[] =
+{
+ { "writable", 'w', 0, G_OPTION_ARG_NONE, &opt_attach_writable, N_("Allow writing to the image"), NULL},
+ { NULL }
+};
+
+static gint
+handle_attach (gint *argc, gchar **argv[])
+{
+ guint n;
+ gint ret = 1;
+ gchar *s = NULL;
+ GOptionContext *o = NULL;
+
+ modify_argv0_for_command (argc, argv, "attach");
+
+ o = g_option_context_new (NULL);
+ g_option_context_set_help_enabled (o, FALSE);
+ g_option_context_set_summary (o, _("Attach and mount one or more disk image files."));
+ g_option_context_add_main_entries (o, attach_entries, GETTEXT_PACKAGE);
+
+ if (!g_option_context_parse (o, argc, argv, NULL) || *argc <= 1)
+ {
+ s = g_option_context_get_help (o, FALSE, NULL);
+ g_printerr ("%s", s);
+ g_free (s);
+ goto out;
+ }
+
+ /* Files to attach are positional arguments */
+ for (n = 1; n < *argc; n++)
+ {
+ const gchar *filename = (*argv)[n];
+ GUnixFDList *fd_list;
+ GVariantBuilder options_builder;
+ gint fd;
+ GError *error;
+ gchar *loop_object_path;
+ UDisksObject *object;
+ UDisksLoop *loop;
+ UDisksFilesystem *filesystem;
+
+ fd = open (filename, opt_attach_writable ? O_RDWR : O_RDONLY);
+ if (fd == -1)
+ {
+ show_error (_("Error opening file `%s': %m"), filename);
+ goto out;
+ }
+
+ g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
+ if (!opt_attach_writable)
+ g_variant_builder_add (&options_builder, "{sv}", "read-only", g_variant_new_boolean (TRUE));
+
+ fd_list = g_unix_fd_list_new_from_array (&fd, 1); /* adopts the fd */
+
+ /* first set up the disk image... */
+ error = NULL;
+ if (!udisks_manager_call_loop_setup_sync (udisks_client_get_manager (udisks_client),
+ g_variant_new_handle (0),
+ g_variant_builder_end (&options_builder),
+ fd_list,
+ &loop_object_path,
+ NULL, /* out_fd_list */
+ NULL, /* GCancellable */
+ &error))
+ {
+ 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);
+ goto out;
+ }
+ g_object_unref (fd_list);
+
+ udisks_client_settle (udisks_client);
+
+ /* ... and then mount 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)
+ {
+ show_error (_("The file `%s' does not appear to contain a mountable filesystem"), filename);
+ /* clean up */
+ error = NULL;
+ if (!udisks_loop_call_delete_sync (loop,
+ g_variant_new ("a{sv}", NULL), /* options */
+ NULL, /* cancellable */
+ &error))
+ {
+ show_error (_("Error cleaning up loop device: %s (%s, %d)"),
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_error_free (error);
+ }
+ goto out;
+ }
+
+ g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add (&options_builder, "{sv}", "loop.autoclear", g_variant_new_boolean (TRUE));
+ error = NULL;
+ if (!udisks_filesystem_call_mount_sync (filesystem,
+ g_variant_builder_end (&options_builder),
+ NULL, /* out_mount_path */
+ NULL, /* cancellable */
+ &error))
+ {
+ 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_delete_sync (loop,
+ g_variant_new ("a{sv}", NULL), /* options */
+ NULL, /* cancellable */
+ &error))
+ {
+ show_error (_("Error cleaning up loop device: %s (%s, %d)"),
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_error_free (error);
+ }
+ goto out;
+ }
+ }
+
+ ret = 0;
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+int
+main (int argc, char *argv[])
+{
+ gint ret = 1;
+ const gchar *command;
+ GError *error = NULL;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ g_type_init ();
+ have_gtk = gtk_init_check (&argc, &argv);
+
+ udisks_client = udisks_client_new_sync (NULL, &error);
+ if (udisks_client == NULL)
+ {
+ g_printerr (_("Error connecting to udisks daemon: %s (%s, %d)"),
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_error_free (error);
+ goto out;
+ }
+
+ command = argv[1];
+ if (g_strcmp0 (command, "help") == 0)
+ {
+ usage (&argc, &argv, TRUE);
+ ret = 0;
+ }
+ else if (g_strcmp0 (command, "attach") == 0)
+ {
+ ret = handle_attach (&argc, &argv);
+ goto out;
+ }
+ else
+ {
+ if (command != NULL)
+ g_printerr (_("Unknown command `%s'\n\n"), command);
+ usage (&argc, &argv, FALSE);
+ goto out;
+ }
+
+ out:
+ g_clear_object (&udisks_client);
+ return ret;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]