From 4f7ce74534361431949197af9711a8ce1e3307ca Mon Sep 17 00:00:00 2001 From: rbuj Date: Wed, 18 Sep 2019 06:57:05 +0200 Subject: Add MATE Disk Image Mounter utility Based on https://github.com/GNOME/gnome-disk-utility/commit/2794ee121829d656d460da58c0ecaa84271e6fe7 --- .travis.yml | 4 + Makefile.am | 11 +- configure.ac | 29 +++ mate-disk-image-mounter/Makefile.am | 1 + mate-disk-image-mounter/data/Makefile.am | 14 + .../data/mate-disk-image-mounter.desktop.in | 13 + mate-disk-image-mounter/src/Makefile.am | 27 ++ mate-disk-image-mounter/src/main.c | 283 +++++++++++++++++++++ po/POTFILES.in | 2 + 9 files changed, 381 insertions(+), 3 deletions(-) create mode 100644 mate-disk-image-mounter/Makefile.am create mode 100644 mate-disk-image-mounter/data/Makefile.am create mode 100644 mate-disk-image-mounter/data/mate-disk-image-mounter.desktop.in create mode 100644 mate-disk-image-mounter/src/Makefile.am create mode 100644 mate-disk-image-mounter/src/main.c diff --git a/.travis.yml b/.travis.yml index 29ceec84..face6f5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,6 +76,7 @@ requires: - mate-common - mate-panel - python + - udisks2 - which - yelp-tools @@ -96,6 +97,7 @@ requires: - libgtk-3-dev - libgtop2-dev - libmate-panel-applet-dev + - libudisks2-dev - libx11-dev - libxext-dev - libxt-dev @@ -122,6 +124,7 @@ requires: - libXmu-devel - libcanberra-devel - libgtop2-devel + - libudisks2-devel - make - mate-common - mate-panel-devel @@ -144,6 +147,7 @@ requires: - libgtk-3-dev - libgtop2-dev - libmate-panel-applet-dev + - libudisks2-dev - libx11-dev - libxext-dev - libxt-dev diff --git a/Makefile.am b/Makefile.am index ab0f3d6e..f88cb1d0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,15 +5,20 @@ distcleancheck_listfiles = find . -type f -print | grep -v 'omf\.out' | grep -v ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} -SUBDIRS = \ +SUBDIRS = \ po \ baobab \ - mate-dictionary \ - mate-screenshot \ + mate-dictionary \ + mate-screenshot \ gsearchtool \ logview \ $(NULL) +if BUILD_DISK_IMAGE_MOUNTER +SUBDIRS += \ + mate-disk-image-mounter +endif + EXTRA_DIST = \ autogen.sh \ omf.make \ diff --git a/configure.ac b/configure.ac index b6bd45a5..56e2335d 100644 --- a/configure.ac +++ b/configure.ac @@ -73,6 +73,7 @@ GTK_REQUIRED=3.22.0 LIBMATE_PANEL_APPLET_REQUIRED=1.17.0 LIBGTOP_REQUIRED=2.12.0 LIBCANBERRA_GTK_REQUIRED=0.4 +UDISKS2_REQUIRED=1.90.0 AC_SUBST(GTK_REQUIRED) @@ -97,6 +98,27 @@ PKG_CHECK_MODULES(GTK, gtk+-3.0 >= $GTK_REQUIRED) AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) +AC_ARG_ENABLE([disk-image-mounter], + [AC_HELP_STRING([--enable-disk-image-mounter=@<:@yes/no@:>@], + [Whether to build the Disk Image Mounter utility])], + [], + [enable_disk_image_mounter=yes]) + +AS_CASE([$enable_disk_image_mounter], + [yes], + [ + PKG_CHECK_MODULES(UDISKS2, [udisks2 >= $UDISKS2_REQUIRED]) + AC_SUBST(UDISKS2_CFLAGS) + AC_SUBST(UDISKS2_LIBS) + ], + + [no], [], + + [*], [AC_MSG_ERROR([Invalid value for --enable-disk-image-mounter])] +) + +AM_CONDITIONAL([BUILD_DISK_IMAGE_MOUNTER], [test "x$enable_disk_image_mounter" = "xyes"]) + # libeggsmclient PKG_CHECK_MODULES(LIBEGGSMCLIENT, gtk+-3.0 >= $GTK_REQUIRED) AC_SUBST(LIBEGGSMCLIENT_CFLAGS) @@ -354,6 +376,13 @@ mate-screenshot/data/org.mate.screenshot.gschema.xml mate-screenshot/src/Makefile ]) +AM_COND_IF([BUILD_DISK_IMAGE_MOUNTER], + [AC_CONFIG_FILES([mate-disk-image-mounter/Makefile + mate-disk-image-mounter/data/Makefile + mate-disk-image-mounter/src/Makefile]) + ] +) + AC_OUTPUT dnl <= Configuration summary => diff --git a/mate-disk-image-mounter/Makefile.am b/mate-disk-image-mounter/Makefile.am new file mode 100644 index 00000000..9768a98a --- /dev/null +++ b/mate-disk-image-mounter/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src data diff --git a/mate-disk-image-mounter/data/Makefile.am b/mate-disk-image-mounter/data/Makefile.am new file mode 100644 index 00000000..1ec524e5 --- /dev/null +++ b/mate-disk-image-mounter/data/Makefile.am @@ -0,0 +1,14 @@ +NULL = + +diskimagemounterdir = $(datadir)/applications +diskimagemounter_in_files = mate-disk-image-mounter.desktop.in +diskimagemounter_DATA = $(diskimagemounter_in_files:.desktop.in=.desktop) +@INTLTOOL_DESKTOP_RULE@ + +EXTRA_DIST = \ + $(diskimagemounter_in_files) \ + $(NULL) + +CLEANFILES = \ + $(diskimagemounter_DATA) \ + $(NULL) diff --git a/mate-disk-image-mounter/data/mate-disk-image-mounter.desktop.in b/mate-disk-image-mounter/data/mate-disk-image-mounter.desktop.in new file mode 100644 index 00000000..f728a506 --- /dev/null +++ b/mate-disk-image-mounter/data/mate-disk-image-mounter.desktop.in @@ -0,0 +1,13 @@ +[Desktop Entry] +_Name=MATE Disk Image Mounter +_Comment=Attach and mount one or more disk image files +TryExec=mate-disk-image-mounter +Exec=mate-disk-image-mounter %U +# Translators: Do NOT translate or transliterate this text (this is an icon file name)! +Icon=drive-removable-media +MimeType=application/x-cd-image;application/x-raw-disk-image; +Terminal=false +StartupNotify=false +Type=Application +Categories=GTK;System; +OnlyShowIn=MATE; diff --git a/mate-disk-image-mounter/src/Makefile.am b/mate-disk-image-mounter/src/Makefile.am new file mode 100644 index 00000000..49d62803 --- /dev/null +++ b/mate-disk-image-mounter/src/Makefile.am @@ -0,0 +1,27 @@ +NULL = + +bin_PROGRAMS = mate-disk-image-mounter + +mate_disk_image_mounter_SOURCES = \ + main.c \ + $(NULL) + +mate_disk_image_mounter_CPPFLAGS = \ + -I. \ + -I$(srcdir) \ + -DG_LOG_DOMAIN=\"mate-disk-image-mounter\" \ + -DMATELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + $(NULL) + +mate_disk_image_mounter_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(UDISKS2_CFLAGS) \ + $(GTK_CFLAGS) \ + $(WARN_CFLAGS) \ + $(NULL) + +mate_disk_image_mounter_LDADD = \ + $(GLIB_LIBS) \ + $(UDISKS2_LIBS) \ + $(GTK_LIBS) \ + $(NULL) diff --git a/mate-disk-image-mounter/src/main.c b/mate-disk-image-mounter/src/main.c new file mode 100644 index 00000000..5dea5a41 --- /dev/null +++ b/mate-disk-image-mounter/src/main.c @@ -0,0 +1,283 @@ +/* -*- 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 + */ + +#include "config.h" +#include + +#include +#include + +#include + +#include + +static gboolean have_gtk = FALSE; +static UDisksClient *udisks_client = NULL; +static GMainLoop *main_loop = NULL; + +/* ---------------------------------------------------------------------------------------------------- */ + +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, + "%s", + _("An error occurred")); + gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", s); + gtk_window_set_title (GTK_WINDOW (dialog), _("MATE 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_writable = FALSE; + +static const GOptionEntry opt_entries[] = +{ + { "writable", 'w', 0, G_OPTION_ARG_NONE, &opt_writable, N_("Allow writing to the image"), NULL}, + { NULL } +}; + +/* ---------------------------------------------------------------------------------------------------- */ + +/* TODO: keep in sync with src/disks/gduutils.c (ideally in shared lib) */ +static void +_gdu_utils_configure_file_chooser_for_disk_images (GtkFileChooser *file_chooser) +{ + GtkFileFilter *filter; + const gchar *folder; + + /* Default to the "Documents" folder since that's where we save such images */ + folder = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); + if (folder != NULL) + gtk_file_chooser_set_current_folder (file_chooser, folder); + + /* TODO: define proper mime-types */ + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (file_chooser, filter); /* adopts filter */ + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Disk Images (*.img, *.iso)")); + gtk_file_filter_add_pattern (filter, "*.img"); + gtk_file_filter_add_pattern (filter, "*.iso"); + gtk_file_chooser_add_filter (file_chooser, filter); /* adopts filter */ + gtk_file_chooser_set_filter (file_chooser, filter); +} + +static GSList * +do_filechooser (void) +{ + GSList *ret = NULL; + GtkWidget *dialog; + GtkWidget *ro_checkbutton; + + ret = NULL; + + dialog = gtk_file_chooser_dialog_new (_("Select Disk Image(s) to Mount"), + NULL, /* parent window */ + GTK_FILE_CHOOSER_ACTION_OPEN, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Mount"), GTK_RESPONSE_ACCEPT, + NULL); + _gdu_utils_configure_file_chooser_for_disk_images (GTK_FILE_CHOOSER (dialog)); + gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE); + + /* Add a RO check button that defaults to RO */ + ro_checkbutton = gtk_check_button_new_with_mnemonic (_("Set up _read-only mount")); + gtk_widget_set_tooltip_markup (ro_checkbutton, _("If checked, the mount will be read-only. This is useful if you don't want the underlying disk image to be modified")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ro_checkbutton), !opt_writable); + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE); + gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), ro_checkbutton); + + //gtk_widget_show_all (dialog); + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT) + goto out; + + ret = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog)); + opt_writable = ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ro_checkbutton)); + + out: + gtk_widget_destroy (dialog); + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + +int +main (int argc, char *argv[]) +{ + gint ret = 1; + GError *error = NULL; + gchar *s = NULL; + GOptionContext *o = NULL; + gint n; + GSList *uris = NULL; + GSList *l; + + bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + have_gtk = gtk_init_check (&argc, &argv); + + if (have_gtk) + gtk_window_set_default_icon_name ("drive-removable-media"); + + main_loop = g_main_loop_new (NULL, FALSE); + + 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; + } + + 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, opt_entries, GETTEXT_PACKAGE); + + if (!g_option_context_parse (o, &argc, &argv, NULL)) + { + s = g_option_context_get_help (o, FALSE, NULL); + g_printerr ("%s", s); + g_free (s); + goto out; + } + + if (argc > 1) + { + for (n = 1; n < argc; n++) + uris = g_slist_prepend (uris, g_strdup (argv[n])); + uris = g_slist_reverse (uris); + } + else + { + if (!have_gtk) + { + show_error ("No files given and GTK+ not available"); + goto out; + } + else + { + uris = do_filechooser (); + } + } + + /* Files to attach are positional arguments */ + for (l = uris; l != NULL; l = l->next) + { + const gchar *uri; + gchar *filename; + GUnixFDList *fd_list = NULL; + GVariantBuilder options_builder; + gint fd; + gchar *loop_object_path = NULL; + GFile *file; + + uri = l->data; + file = g_file_new_for_commandline_arg (uri); + filename = g_file_get_path (file); + g_object_unref (file); + + if (filename == NULL) + { + show_error (_("Cannot open `%s' - maybe the volume isn't mounted?"), uri); + goto done_with_image; + } + + fd = open (filename, opt_writable ? O_RDWR : O_RDONLY); + if (fd == -1) + { + show_error (_("Error opening `%s': %m"), filename); + goto done_with_image; + } + + g_variant_builder_init (&options_builder, G_VARIANT_TYPE ("a{sv}")); + if (!opt_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 */ + + /* 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_clear_error (&error); + goto done_with_image; + } + + /* Note that the desktop automounter is responsible for mounting, + * unlocking etc. partitions etc. inside the image... + */ + + done_with_image: + + g_clear_object (&fd_list); + g_free (filename); + g_free (loop_object_path); + + } /* for each image */ + + ret = 0; + + out: + if (main_loop != NULL) + g_main_loop_unref (main_loop); + g_slist_free_full (uris, g_free); + g_clear_object (&udisks_client); + return ret; +} diff --git a/po/POTFILES.in b/po/POTFILES.in index 481a6179..d69629f9 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -63,6 +63,8 @@ mate-dictionary/src/gdict-window.c mate-dictionary/src/main.c [type: gettext/glade]mate-dictionary/data/mate-dictionary-preferences.ui [type: gettext/glade]mate-dictionary/data/mate-dictionary-source.ui +[type: gettext/ini]mate-disk-image-mounter/data/mate-disk-image-mounter.desktop.in +mate-disk-image-mounter/src/main.c mate-screenshot/data/mate-screenshot.appdata.xml.in mate-screenshot/data/mate-screenshot.desktop.in [type: gettext/glade]mate-screenshot/data/mate-screenshot.ui -- cgit v1.2.1