diff options
Diffstat (limited to 'mate-disk-image-mounter/src/main.c')
-rw-r--r-- | mate-disk-image-mounter/src/main.c | 283 |
1 files changed, 283 insertions, 0 deletions
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 <[email protected]> + */ + +#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 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, + "<big><b>%s</b></big>", + _("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; +} |