Merge branch '976-disable-assert-checks' into 'master'
[glib.git] / gio / gio-tool-mount.c
blobb5aaa1af2d341b3a4ba571e226320a443a1c409b
1 /*
2 * Copyright 2015 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 * Author: Matthias Clasen <mclasen@redhat.com>
20 #include "config.h"
22 #include <gio/gio.h>
23 #include <gi18n.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #ifdef HAVE_TERMIOS_H
27 #include <termios.h>
28 #endif
30 #include "gio-tool.h"
32 #define STDIN_FILENO 0
34 typedef enum {
35 MOUNT_OP_NONE,
36 MOUNT_OP_ASKED,
37 MOUNT_OP_ABORTED
38 } MountOpState;
40 static int outstanding_mounts = 0;
41 static GMainLoop *main_loop;
43 static gboolean mount_mountable = FALSE;
44 static gboolean mount_unmount = FALSE;
45 static gboolean mount_eject = FALSE;
46 static gboolean force = FALSE;
47 static gboolean anonymous = FALSE;
48 static gboolean mount_list = FALSE;
49 static gboolean extra_detail = FALSE;
50 static gboolean mount_monitor = FALSE;
51 static gboolean tcrypt_hidden = FALSE;
52 static gboolean tcrypt_system = FALSE;
53 static guint tcrypt_pim = 0;
54 static const char *unmount_scheme = NULL;
55 static const char *mount_device_file = NULL;
56 static const char *stop_device_file = NULL;
57 static gboolean success = TRUE;
60 static const GOptionEntry entries[] =
62 { "mountable", 'm', 0, G_OPTION_ARG_NONE, &mount_mountable, N_("Mount as mountable"), NULL },
63 { "device", 'd', 0, G_OPTION_ARG_STRING, &mount_device_file, N_("Mount volume with device file"), N_("DEVICE") },
64 { "unmount", 'u', 0, G_OPTION_ARG_NONE, &mount_unmount, N_("Unmount"), NULL},
65 { "eject", 'e', 0, G_OPTION_ARG_NONE, &mount_eject, N_("Eject"), NULL},
66 { "stop", 't', 0, G_OPTION_ARG_STRING, &stop_device_file, N_("Stop drive with device file"), N_("DEVICE") },
67 { "unmount-scheme", 's', 0, G_OPTION_ARG_STRING, &unmount_scheme, N_("Unmount all mounts with the given scheme"), N_("SCHEME") },
68 { "force", 'f', 0, G_OPTION_ARG_NONE, &force, N_("Ignore outstanding file operations when unmounting or ejecting"), NULL },
69 { "anonymous", 'a', 0, G_OPTION_ARG_NONE, &anonymous, N_("Use an anonymous user when authenticating"), NULL },
70 /* Translator: List here is a verb as in 'List all mounts' */
71 { "list", 'l', 0, G_OPTION_ARG_NONE, &mount_list, N_("List"), NULL},
72 { "monitor", 'o', 0, G_OPTION_ARG_NONE, &mount_monitor, N_("Monitor events"), NULL},
73 { "detail", 'i', 0, G_OPTION_ARG_NONE, &extra_detail, N_("Show extra information"), NULL},
74 { "tcrypt-pim", 0, 0, G_OPTION_ARG_INT, &tcrypt_pim, N_("The numeric PIM when unlocking a VeraCrypt volume"), N_("PIM")},
75 { "tcrypt-hidden", 0, 0, G_OPTION_ARG_NONE, &tcrypt_hidden, N_("Mount a TCRYPT hidden volume"), NULL},
76 { "tcrypt-system", 0, 0, G_OPTION_ARG_NONE, &tcrypt_system, N_("Mount a TCRYPT system volume"), NULL},
77 { NULL }
80 static char *
81 prompt_for (const char *prompt, const char *default_value, gboolean echo)
83 #ifdef HAVE_TERMIOS_H
84 struct termios term_attr;
85 int old_flags;
86 gboolean restore_flags;
87 #endif
88 char data[256];
89 int len;
91 if (default_value && *default_value != 0)
92 g_print ("%s [%s]: ", prompt, default_value);
93 else
94 g_print ("%s: ", prompt);
96 data[0] = 0;
98 #ifdef HAVE_TERMIOS_H
99 restore_flags = FALSE;
100 if (!echo && tcgetattr (STDIN_FILENO, &term_attr) == 0)
102 old_flags = term_attr.c_lflag;
103 term_attr.c_lflag &= ~ECHO;
104 restore_flags = TRUE;
106 if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &term_attr) != 0)
107 g_print ("Warning! Password will be echoed");
110 #endif
112 fgets(data, sizeof (data), stdin);
114 #ifdef HAVE_TERMIOS_H
115 if (restore_flags)
117 term_attr.c_lflag = old_flags;
118 tcsetattr (STDIN_FILENO, TCSAFLUSH, &term_attr);
120 #endif
122 len = strlen (data);
123 if (len == 0)
125 g_print ("\n");
126 return NULL;
128 if (data[len-1] == '\n')
129 data[len-1] = 0;
131 if (!echo)
132 g_print ("\n");
134 if (*data == 0 && default_value)
135 return g_strdup (default_value);
136 return g_strdup (data);
139 static void
140 ask_password_cb (GMountOperation *op,
141 const char *message,
142 const char *default_user,
143 const char *default_domain,
144 GAskPasswordFlags flags)
146 if ((flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED) && anonymous)
148 g_mount_operation_set_anonymous (op, TRUE);
150 else
152 char *s;
153 g_print ("%s\n", message);
155 if (flags & G_ASK_PASSWORD_NEED_USERNAME)
157 s = prompt_for ("User", default_user, TRUE);
158 if (!s)
159 goto error;
160 g_mount_operation_set_username (op, s);
161 g_free (s);
164 if (flags & G_ASK_PASSWORD_NEED_DOMAIN)
166 s = prompt_for ("Domain", default_domain, TRUE);
167 if (!s)
168 goto error;
169 g_mount_operation_set_domain (op, s);
170 g_free (s);
173 if (flags & G_ASK_PASSWORD_NEED_PASSWORD)
175 s = prompt_for ("Password", NULL, FALSE);
176 if (!s)
177 goto error;
178 g_mount_operation_set_password (op, s);
179 g_free (s);
183 if (flags & G_ASK_PASSWORD_TCRYPT)
185 if (tcrypt_pim)
186 g_mount_operation_set_pim (op, tcrypt_pim);
187 if (tcrypt_hidden)
188 g_mount_operation_set_is_tcrypt_hidden_volume (op, TRUE);
189 if (tcrypt_system)
190 g_mount_operation_set_is_tcrypt_system_volume (op, TRUE);
193 /* Only try anonymous access once. */
194 if (anonymous &&
195 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (op), "state")) == MOUNT_OP_ASKED)
197 g_object_set_data (G_OBJECT (op), "state", GINT_TO_POINTER (MOUNT_OP_ABORTED));
198 g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED);
200 else
202 g_object_set_data (G_OBJECT (op), "state", GINT_TO_POINTER (MOUNT_OP_ASKED));
203 g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
206 return;
208 error:
209 g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED);
212 static void
213 ask_question_cb (GMountOperation *op,
214 char *message,
215 char **choices,
216 gpointer user_data)
218 char **ptr = choices;
219 char *s;
220 int i, choice;
222 g_print ("%s\n", message);
224 i = 1;
225 while (*ptr)
227 g_print ("[%d] %s\n", i, *ptr++);
228 i++;
231 s = prompt_for ("Choice", NULL, TRUE);
232 if (!s)
233 goto error;
235 choice = atoi (s);
236 if (choice > 0 && choice < i)
238 g_mount_operation_set_choice (op, choice - 1);
239 g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
241 g_free (s);
243 return;
245 error:
246 g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED);
249 static void
250 mount_mountable_done_cb (GObject *object,
251 GAsyncResult *res,
252 gpointer user_data)
254 GFile *target;
255 GError *error = NULL;
256 GMountOperation *op = user_data;
258 target = g_file_mount_mountable_finish (G_FILE (object), res, &error);
260 if (target == NULL)
262 success = FALSE;
263 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (op), "state")) == MOUNT_OP_ABORTED)
264 print_file_error (G_FILE (object), _("Anonymous access denied"));
265 else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED))
266 print_file_error (G_FILE (object), error->message);
268 g_error_free (error);
270 else
271 g_object_unref (target);
273 g_object_unref (op);
275 outstanding_mounts--;
277 if (outstanding_mounts == 0)
278 g_main_loop_quit (main_loop);
281 static void
282 mount_done_cb (GObject *object,
283 GAsyncResult *res,
284 gpointer user_data)
286 gboolean succeeded;
287 GError *error = NULL;
288 GMountOperation *op = user_data;
290 succeeded = g_file_mount_enclosing_volume_finish (G_FILE (object), res, &error);
292 if (!succeeded)
294 success = FALSE;
295 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (op), "state")) == MOUNT_OP_ABORTED)
296 print_file_error (G_FILE (object), _("Anonymous access denied"));
297 else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED))
298 print_file_error (G_FILE (object), error->message);
300 g_error_free (error);
303 g_object_unref (op);
305 outstanding_mounts--;
307 if (outstanding_mounts == 0)
308 g_main_loop_quit (main_loop);
311 static GMountOperation *
312 new_mount_op (void)
314 GMountOperation *op;
316 op = g_mount_operation_new ();
318 g_object_set_data (G_OBJECT (op), "state", GINT_TO_POINTER (MOUNT_OP_NONE));
320 g_signal_connect (op, "ask_password", G_CALLBACK (ask_password_cb), NULL);
321 g_signal_connect (op, "ask_question", G_CALLBACK (ask_question_cb), NULL);
323 /* TODO: we *should* also connect to the "aborted" signal but since the
324 * main thread is blocked handling input we won't get that signal anyway...
327 return op;
331 static void
332 mount (GFile *file)
334 GMountOperation *op;
336 if (file == NULL)
337 return;
339 op = new_mount_op ();
341 if (mount_mountable)
342 g_file_mount_mountable (file, 0, op, NULL, mount_mountable_done_cb, op);
343 else
344 g_file_mount_enclosing_volume (file, 0, op, NULL, mount_done_cb, op);
346 outstanding_mounts++;
349 static void
350 unmount_done_cb (GObject *object,
351 GAsyncResult *res,
352 gpointer user_data)
354 gboolean succeeded;
355 GError *error = NULL;
356 GFile *file = G_FILE (user_data);
358 succeeded = g_mount_unmount_with_operation_finish (G_MOUNT (object), res, &error);
360 g_object_unref (G_MOUNT (object));
362 if (!succeeded)
364 print_file_error (file, error->message);
365 success = FALSE;
366 g_error_free (error);
369 g_object_unref (file);
371 outstanding_mounts--;
373 if (outstanding_mounts == 0)
374 g_main_loop_quit (main_loop);
377 static void
378 unmount (GFile *file)
380 GMount *mount;
381 GError *error = NULL;
382 GMountOperation *mount_op;
383 GMountUnmountFlags flags;
385 if (file == NULL)
386 return;
388 mount = g_file_find_enclosing_mount (file, NULL, &error);
389 if (mount == NULL)
391 print_file_error (file, error->message);
392 success = FALSE;
393 g_error_free (error);
394 return;
397 mount_op = new_mount_op ();
398 flags = force ? G_MOUNT_UNMOUNT_FORCE : G_MOUNT_UNMOUNT_NONE;
399 g_mount_unmount_with_operation (mount, flags, mount_op, NULL, unmount_done_cb, g_object_ref (file));
400 g_object_unref (mount_op);
402 outstanding_mounts++;
405 static void
406 eject_done_cb (GObject *object,
407 GAsyncResult *res,
408 gpointer user_data)
410 gboolean succeeded;
411 GError *error = NULL;
412 GFile *file = G_FILE (user_data);
414 succeeded = g_mount_eject_with_operation_finish (G_MOUNT (object), res, &error);
416 g_object_unref (G_MOUNT (object));
418 if (!succeeded)
420 print_file_error (file, error->message);
421 success = FALSE;
422 g_error_free (error);
425 g_object_unref (file);
427 outstanding_mounts--;
429 if (outstanding_mounts == 0)
430 g_main_loop_quit (main_loop);
433 static void
434 eject (GFile *file)
436 GMount *mount;
437 GError *error = NULL;
438 GMountOperation *mount_op;
439 GMountUnmountFlags flags;
441 if (file == NULL)
442 return;
444 mount = g_file_find_enclosing_mount (file, NULL, &error);
445 if (mount == NULL)
447 print_file_error (file, error->message);
448 success = FALSE;
449 g_error_free (error);
450 return;
453 mount_op = new_mount_op ();
454 flags = force ? G_MOUNT_UNMOUNT_FORCE : G_MOUNT_UNMOUNT_NONE;
455 g_mount_eject_with_operation (mount, flags, mount_op, NULL, eject_done_cb, g_object_ref (file));
456 g_object_unref (mount_op);
458 outstanding_mounts++;
461 static void
462 stop_with_device_file_cb (GObject *object,
463 GAsyncResult *res,
464 gpointer user_data)
466 GError *error = NULL;
467 gchar *device_path = user_data;
469 if (!g_drive_stop_finish (G_DRIVE (object), res, &error))
471 print_error ("%s: %s", device_path, error->message);
472 g_error_free (error);
473 success = FALSE;
476 g_free (device_path);
478 outstanding_mounts--;
480 if (outstanding_mounts == 0)
481 g_main_loop_quit (main_loop);
484 static void
485 stop_with_device_file (const char *device_file)
487 GVolumeMonitor *volume_monitor;
488 GList *drives;
489 GList *l;
491 volume_monitor = g_volume_monitor_get ();
493 drives = g_volume_monitor_get_connected_drives (volume_monitor);
494 for (l = drives; l != NULL; l = l->next)
496 GDrive *drive = G_DRIVE (l->data);
497 gchar *id;
499 id = g_drive_get_identifier (drive, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
500 if (g_strcmp0 (id, device_file) == 0)
502 GMountOperation *op;
503 GMountUnmountFlags flags;
505 op = new_mount_op ();
506 flags = force ? G_MOUNT_UNMOUNT_FORCE : G_MOUNT_UNMOUNT_NONE;
507 g_drive_stop (drive,
508 flags,
510 NULL,
511 stop_with_device_file_cb,
512 g_steal_pointer (&id));
513 g_object_unref (op);
515 outstanding_mounts++;
518 g_free (id);
520 g_list_free_full (drives, g_object_unref);
522 if (outstanding_mounts == 0)
524 print_error ("%s: %s", device_file, _("No drive for device file"));
525 success = FALSE;
528 g_object_unref (volume_monitor);
531 static gboolean
532 iterate_gmain_timeout_function (gpointer data)
534 g_main_loop_quit (main_loop);
535 return FALSE;
538 static void
539 iterate_gmain(void)
541 g_timeout_add (500, iterate_gmain_timeout_function, NULL);
542 g_main_loop_run (main_loop);
545 static void
546 show_themed_icon_names (GThemedIcon *icon, gboolean symbolic, int indent)
548 char **names;
549 char **iter;
551 g_print ("%*s%sthemed icons:", indent, " ", symbolic ? "symbolic " : "");
553 names = NULL;
555 g_object_get (icon, "names", &names, NULL);
557 for (iter = names; *iter; iter++)
558 g_print (" [%s]", *iter);
560 g_print ("\n");
561 g_strfreev (names);
564 /* don't copy-paste this code */
565 static char *
566 get_type_name (gpointer object)
568 const char *type_name;
569 char *ret;
571 type_name = g_type_name (G_TYPE_FROM_INSTANCE (object));
572 if (strcmp ("GProxyDrive", type_name) == 0)
574 ret = g_strdup_printf ("%s (%s)",
575 type_name,
576 (const char *) g_object_get_data (G_OBJECT (object),
577 "g-proxy-drive-volume-monitor-name"));
579 else if (strcmp ("GProxyVolume", type_name) == 0)
581 ret = g_strdup_printf ("%s (%s)",
582 type_name,
583 (const char *) g_object_get_data (G_OBJECT (object),
584 "g-proxy-volume-volume-monitor-name"));
586 else if (strcmp ("GProxyMount", type_name) == 0)
588 ret = g_strdup_printf ("%s (%s)",
589 type_name,
590 (const char *) g_object_get_data (G_OBJECT (object),
591 "g-proxy-mount-volume-monitor-name"));
593 else if (strcmp ("GProxyShadowMount", type_name) == 0)
595 ret = g_strdup_printf ("%s (%s)",
596 type_name,
597 (const char *) g_object_get_data (G_OBJECT (object),
598 "g-proxy-shadow-mount-volume-monitor-name"));
600 else
602 ret = g_strdup (type_name);
605 return ret;
608 static void
609 list_mounts (GList *mounts,
610 int indent,
611 gboolean only_with_no_volume)
613 GList *l;
614 int c;
615 GMount *mount;
616 GVolume *volume;
617 char *name, *uuid, *uri;
618 GFile *root, *default_location;
619 GIcon *icon;
620 char **x_content_types;
621 char *type_name;
622 const gchar *sort_key;
624 for (c = 0, l = mounts; l != NULL; l = l->next, c++)
626 mount = (GMount *) l->data;
628 if (only_with_no_volume)
630 volume = g_mount_get_volume (mount);
631 if (volume != NULL)
633 g_object_unref (volume);
634 continue;
638 name = g_mount_get_name (mount);
639 root = g_mount_get_root (mount);
640 uri = g_file_get_uri (root);
642 g_print ("%*sMount(%d): %s -> %s\n", indent, "", c, name, uri);
644 type_name = get_type_name (mount);
645 g_print ("%*sType: %s\n", indent+2, "", type_name);
646 g_free (type_name);
648 if (extra_detail)
650 uuid = g_mount_get_uuid (mount);
651 if (uuid)
652 g_print ("%*suuid=%s\n", indent + 2, "", uuid);
654 default_location = g_mount_get_default_location (mount);
655 if (default_location)
657 char *loc_uri = g_file_get_uri (default_location);
658 g_print ("%*sdefault_location=%s\n", indent + 2, "", loc_uri);
659 g_free (loc_uri);
660 g_object_unref (default_location);
663 icon = g_mount_get_icon (mount);
664 if (icon)
666 if (G_IS_THEMED_ICON (icon))
667 show_themed_icon_names (G_THEMED_ICON (icon), FALSE, indent + 2);
669 g_object_unref (icon);
672 icon = g_mount_get_symbolic_icon (mount);
673 if (icon)
675 if (G_IS_THEMED_ICON (icon))
676 show_themed_icon_names (G_THEMED_ICON (icon), TRUE, indent + 2);
678 g_object_unref (icon);
681 x_content_types = g_mount_guess_content_type_sync (mount, FALSE, NULL, NULL);
682 if (x_content_types != NULL && g_strv_length (x_content_types) > 0)
684 int n;
685 g_print ("%*sx_content_types:", indent + 2, "");
686 for (n = 0; x_content_types[n] != NULL; n++)
687 g_print (" %s", x_content_types[n]);
688 g_print ("\n");
690 g_strfreev (x_content_types);
692 g_print ("%*scan_unmount=%d\n", indent + 2, "", g_mount_can_unmount (mount));
693 g_print ("%*scan_eject=%d\n", indent + 2, "", g_mount_can_eject (mount));
694 g_print ("%*sis_shadowed=%d\n", indent + 2, "", g_mount_is_shadowed (mount));
695 sort_key = g_mount_get_sort_key (mount);
696 if (sort_key != NULL)
697 g_print ("%*ssort_key=%s\n", indent + 2, "", sort_key);
698 g_free (uuid);
701 g_object_unref (root);
702 g_free (name);
703 g_free (uri);
707 static void
708 list_volumes (GList *volumes,
709 int indent,
710 gboolean only_with_no_drive)
712 GList *l, *mounts;
713 int c, i;
714 GMount *mount;
715 GVolume *volume;
716 GDrive *drive;
717 char *name;
718 char *uuid;
719 GFile *activation_root;
720 char **ids;
721 GIcon *icon;
722 char *type_name;
723 const gchar *sort_key;
725 for (c = 0, l = volumes; l != NULL; l = l->next, c++)
727 volume = (GVolume *) l->data;
729 if (only_with_no_drive)
731 drive = g_volume_get_drive (volume);
732 if (drive != NULL)
734 g_object_unref (drive);
735 continue;
739 name = g_volume_get_name (volume);
741 g_print ("%*sVolume(%d): %s\n", indent, "", c, name);
742 g_free (name);
744 type_name = get_type_name (volume);
745 g_print ("%*sType: %s\n", indent+2, "", type_name);
746 g_free (type_name);
748 if (extra_detail)
750 ids = g_volume_enumerate_identifiers (volume);
751 if (ids && ids[0] != NULL)
753 g_print ("%*sids:\n", indent+2, "");
754 for (i = 0; ids[i] != NULL; i++)
756 char *id = g_volume_get_identifier (volume,
757 ids[i]);
758 g_print ("%*s %s: '%s'\n", indent+2, "", ids[i], id);
759 g_free (id);
762 g_strfreev (ids);
764 uuid = g_volume_get_uuid (volume);
765 if (uuid)
766 g_print ("%*suuid=%s\n", indent + 2, "", uuid);
767 activation_root = g_volume_get_activation_root (volume);
768 if (activation_root)
770 char *uri;
771 uri = g_file_get_uri (activation_root);
772 g_print ("%*sactivation_root=%s\n", indent + 2, "", uri);
773 g_free (uri);
774 g_object_unref (activation_root);
776 icon = g_volume_get_icon (volume);
777 if (icon)
779 if (G_IS_THEMED_ICON (icon))
780 show_themed_icon_names (G_THEMED_ICON (icon), FALSE, indent + 2);
782 g_object_unref (icon);
785 icon = g_volume_get_symbolic_icon (volume);
786 if (icon)
788 if (G_IS_THEMED_ICON (icon))
789 show_themed_icon_names (G_THEMED_ICON (icon), TRUE, indent + 2);
791 g_object_unref (icon);
794 g_print ("%*scan_mount=%d\n", indent + 2, "", g_volume_can_mount (volume));
795 g_print ("%*scan_eject=%d\n", indent + 2, "", g_volume_can_eject (volume));
796 g_print ("%*sshould_automount=%d\n", indent + 2, "", g_volume_should_automount (volume));
797 sort_key = g_volume_get_sort_key (volume);
798 if (sort_key != NULL)
799 g_print ("%*ssort_key=%s\n", indent + 2, "", sort_key);
800 g_free (uuid);
803 mount = g_volume_get_mount (volume);
804 if (mount)
806 mounts = g_list_prepend (NULL, mount);
807 list_mounts (mounts, indent + 2, FALSE);
808 g_list_free (mounts);
809 g_object_unref (mount);
814 static void
815 list_drives (GList *drives,
816 int indent)
818 GList *volumes, *l;
819 int c, i;
820 GDrive *drive;
821 char *name;
822 char **ids;
823 GIcon *icon;
824 char *type_name;
825 const gchar *sort_key;
827 for (c = 0, l = drives; l != NULL; l = l->next, c++)
829 drive = (GDrive *) l->data;
830 name = g_drive_get_name (drive);
832 g_print ("%*sDrive(%d): %s\n", indent, "", c, name);
833 g_free (name);
835 type_name = get_type_name (drive);
836 g_print ("%*sType: %s\n", indent+2, "", type_name);
837 g_free (type_name);
839 if (extra_detail)
841 GEnumValue *enum_value;
842 gpointer klass;
844 ids = g_drive_enumerate_identifiers (drive);
845 if (ids && ids[0] != NULL)
847 g_print ("%*sids:\n", indent+2, "");
848 for (i = 0; ids[i] != NULL; i++)
850 char *id = g_drive_get_identifier (drive,
851 ids[i]);
852 g_print ("%*s %s: '%s'\n", indent+2, "", ids[i], id);
853 g_free (id);
856 g_strfreev (ids);
858 icon = g_drive_get_icon (drive);
859 if (icon)
861 if (G_IS_THEMED_ICON (icon))
862 show_themed_icon_names (G_THEMED_ICON (icon), FALSE, indent + 2);
863 g_object_unref (icon);
866 icon = g_drive_get_symbolic_icon (drive);
867 if (icon)
869 if (G_IS_THEMED_ICON (icon))
870 show_themed_icon_names (G_THEMED_ICON (icon), TRUE, indent + 2);
872 g_object_unref (icon);
875 g_print ("%*sis_removable=%d\n", indent + 2, "", g_drive_is_removable (drive));
876 g_print ("%*sis_media_removable=%d\n", indent + 2, "", g_drive_is_media_removable (drive));
877 g_print ("%*shas_media=%d\n", indent + 2, "", g_drive_has_media (drive));
878 g_print ("%*sis_media_check_automatic=%d\n", indent + 2, "", g_drive_is_media_check_automatic (drive));
879 g_print ("%*scan_poll_for_media=%d\n", indent + 2, "", g_drive_can_poll_for_media (drive));
880 g_print ("%*scan_eject=%d\n", indent + 2, "", g_drive_can_eject (drive));
881 g_print ("%*scan_start=%d\n", indent + 2, "", g_drive_can_start (drive));
882 g_print ("%*scan_stop=%d\n", indent + 2, "", g_drive_can_stop (drive));
884 enum_value = NULL;
885 klass = g_type_class_ref (G_TYPE_DRIVE_START_STOP_TYPE);
886 if (klass != NULL)
888 enum_value = g_enum_get_value (klass, g_drive_get_start_stop_type (drive));
889 g_print ("%*sstart_stop_type=%s\n", indent + 2, "",
890 enum_value != NULL ? enum_value->value_nick : "UNKNOWN");
891 g_type_class_unref (klass);
894 sort_key = g_drive_get_sort_key (drive);
895 if (sort_key != NULL)
896 g_print ("%*ssort_key=%s\n", indent + 2, "", sort_key);
898 volumes = g_drive_get_volumes (drive);
899 list_volumes (volumes, indent + 2, FALSE);
900 g_list_free_full (volumes, g_object_unref);
905 static void
906 list_monitor_items (void)
908 GVolumeMonitor *volume_monitor;
909 GList *drives, *volumes, *mounts;
911 volume_monitor = g_volume_monitor_get();
913 /* populate gvfs network mounts */
914 iterate_gmain();
916 drives = g_volume_monitor_get_connected_drives (volume_monitor);
917 list_drives (drives, 0);
918 g_list_free_full (drives, g_object_unref);
920 volumes = g_volume_monitor_get_volumes (volume_monitor);
921 list_volumes (volumes, 0, TRUE);
922 g_list_free_full (volumes, g_object_unref);
924 mounts = g_volume_monitor_get_mounts (volume_monitor);
925 list_mounts (mounts, 0, TRUE);
926 g_list_free_full (mounts, g_object_unref);
928 g_object_unref (volume_monitor);
931 static void
932 unmount_all_with_scheme (const char *scheme)
934 GVolumeMonitor *volume_monitor;
935 GList *mounts;
936 GList *l;
938 volume_monitor = g_volume_monitor_get();
940 /* populate gvfs network mounts */
941 iterate_gmain();
943 mounts = g_volume_monitor_get_mounts (volume_monitor);
944 for (l = mounts; l != NULL; l = l->next) {
945 GMount *mount = G_MOUNT (l->data);
946 GFile *root;
948 root = g_mount_get_root (mount);
949 if (g_file_has_uri_scheme (root, scheme)) {
950 unmount (root);
952 g_object_unref (root);
954 g_list_free_full (mounts, g_object_unref);
956 g_object_unref (volume_monitor);
959 static void
960 mount_with_device_file_cb (GObject *object,
961 GAsyncResult *res,
962 gpointer user_data)
964 GVolume *volume;
965 gboolean succeeded;
966 GError *error = NULL;
967 gchar *device_path = (gchar *)user_data;
969 volume = G_VOLUME (object);
971 succeeded = g_volume_mount_finish (volume, res, &error);
973 if (!succeeded)
975 print_error ("%s: %s", device_path, error->message);
976 g_error_free (error);
977 success = FALSE;
979 else
981 GMount *mount;
982 GFile *root;
983 char *mount_path;
985 mount = g_volume_get_mount (volume);
986 root = g_mount_get_root (mount);
987 mount_path = g_file_get_path (root);
989 g_print (_("Mounted %s at %s\n"), device_path, mount_path);
991 g_object_unref (mount);
992 g_object_unref (root);
993 g_free (mount_path);
996 g_free (device_path);
998 outstanding_mounts--;
1000 if (outstanding_mounts == 0)
1001 g_main_loop_quit (main_loop);
1004 static void
1005 mount_with_device_file (const char *device_file)
1007 GVolumeMonitor *volume_monitor;
1008 GList *volumes;
1009 GList *l;
1011 volume_monitor = g_volume_monitor_get();
1013 volumes = g_volume_monitor_get_volumes (volume_monitor);
1014 for (l = volumes; l != NULL; l = l->next)
1016 GVolume *volume = G_VOLUME (l->data);
1017 gchar *id;
1019 id = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
1020 if (g_strcmp0 (id, device_file) == 0)
1022 GMountOperation *op;
1024 op = new_mount_op ();
1026 g_volume_mount (volume,
1027 G_MOUNT_MOUNT_NONE,
1029 NULL,
1030 mount_with_device_file_cb,
1031 id);
1033 g_object_unref (op);
1035 outstanding_mounts++;
1037 else
1038 g_free (id);
1040 g_list_free_full (volumes, g_object_unref);
1042 if (outstanding_mounts == 0)
1044 print_error ("%s: %s", device_file, _("No volume for device file"));
1045 success = FALSE;
1048 g_object_unref (volume_monitor);
1051 static void
1052 monitor_print_mount (GMount *mount)
1054 if (extra_detail)
1056 GList *l;
1057 l = g_list_prepend (NULL, mount);
1058 list_mounts (l, 2, FALSE);
1059 g_list_free (l);
1060 g_print ("\n");
1064 static void
1065 monitor_print_volume (GVolume *volume)
1067 if (extra_detail)
1069 GList *l;
1070 l = g_list_prepend (NULL, volume);
1071 list_volumes (l, 2, FALSE);
1072 g_list_free (l);
1073 g_print ("\n");
1077 static void
1078 monitor_print_drive (GDrive *drive)
1080 if (extra_detail)
1082 GList *l;
1083 l = g_list_prepend (NULL, drive);
1084 list_drives (l, 2);
1085 g_list_free (l);
1086 g_print ("\n");
1090 static void
1091 monitor_mount_added (GVolumeMonitor *volume_monitor, GMount *mount)
1093 char *name;
1094 name = g_mount_get_name (mount);
1095 g_print ("Mount added: '%s'\n", name);
1096 g_free (name);
1097 monitor_print_mount (mount);
1100 static void
1101 monitor_mount_removed (GVolumeMonitor *volume_monitor, GMount *mount)
1103 char *name;
1104 name = g_mount_get_name (mount);
1105 g_print ("Mount removed: '%s'\n", name);
1106 g_free (name);
1107 monitor_print_mount (mount);
1110 static void
1111 monitor_mount_changed (GVolumeMonitor *volume_monitor, GMount *mount)
1113 char *name;
1114 name = g_mount_get_name (mount);
1115 g_print ("Mount changed: '%s'\n", name);
1116 g_free (name);
1117 monitor_print_mount (mount);
1120 static void
1121 monitor_mount_pre_unmount (GVolumeMonitor *volume_monitor, GMount *mount)
1123 char *name;
1124 name = g_mount_get_name (mount);
1125 g_print ("Mount pre-unmount: '%s'\n", name);
1126 g_free (name);
1127 monitor_print_mount (mount);
1130 static void
1131 monitor_volume_added (GVolumeMonitor *volume_monitor, GVolume *volume)
1133 char *name;
1134 name = g_volume_get_name (volume);
1135 g_print ("Volume added: '%s'\n", name);
1136 g_free (name);
1137 monitor_print_volume (volume);
1140 static void
1141 monitor_volume_removed (GVolumeMonitor *volume_monitor, GVolume *volume)
1143 char *name;
1144 name = g_volume_get_name (volume);
1145 g_print ("Volume removed: '%s'\n", name);
1146 g_free (name);
1147 monitor_print_volume (volume);
1150 static void
1151 monitor_volume_changed (GVolumeMonitor *volume_monitor, GVolume *volume)
1153 char *name;
1154 name = g_volume_get_name (volume);
1155 g_print ("Volume changed: '%s'\n", name);
1156 g_free (name);
1157 monitor_print_volume (volume);
1160 static void
1161 monitor_drive_connected (GVolumeMonitor *volume_monitor, GDrive *drive)
1163 char *name;
1164 name = g_drive_get_name (drive);
1165 g_print ("Drive connected: '%s'\n", name);
1166 g_free (name);
1167 monitor_print_drive (drive);
1170 static void
1171 monitor_drive_disconnected (GVolumeMonitor *volume_monitor, GDrive *drive)
1173 char *name;
1174 name = g_drive_get_name (drive);
1175 g_print ("Drive disconnected: '%s'\n", name);
1176 g_free (name);
1177 monitor_print_drive (drive);
1180 static void
1181 monitor_drive_changed (GVolumeMonitor *volume_monitor, GDrive *drive)
1183 char *name;
1184 name = g_drive_get_name (drive);
1185 g_print ("Drive changed: '%s'\n", name);
1186 g_free (name);
1187 monitor_print_drive (drive);
1190 static void
1191 monitor_drive_eject_button (GVolumeMonitor *volume_monitor, GDrive *drive)
1193 char *name;
1194 name = g_drive_get_name (drive);
1195 g_print ("Drive eject button: '%s'\n", name);
1196 g_free (name);
1199 static void
1200 monitor (void)
1202 GVolumeMonitor *volume_monitor;
1204 volume_monitor = g_volume_monitor_get ();
1206 g_signal_connect (volume_monitor, "mount-added", (GCallback) monitor_mount_added, NULL);
1207 g_signal_connect (volume_monitor, "mount-removed", (GCallback) monitor_mount_removed, NULL);
1208 g_signal_connect (volume_monitor, "mount-changed", (GCallback) monitor_mount_changed, NULL);
1209 g_signal_connect (volume_monitor, "mount-pre-unmount", (GCallback) monitor_mount_pre_unmount, NULL);
1210 g_signal_connect (volume_monitor, "volume-added", (GCallback) monitor_volume_added, NULL);
1211 g_signal_connect (volume_monitor, "volume-removed", (GCallback) monitor_volume_removed, NULL);
1212 g_signal_connect (volume_monitor, "volume-changed", (GCallback) monitor_volume_changed, NULL);
1213 g_signal_connect (volume_monitor, "drive-connected", (GCallback) monitor_drive_connected, NULL);
1214 g_signal_connect (volume_monitor, "drive-disconnected", (GCallback) monitor_drive_disconnected, NULL);
1215 g_signal_connect (volume_monitor, "drive-changed", (GCallback) monitor_drive_changed, NULL);
1216 g_signal_connect (volume_monitor, "drive-eject-button", (GCallback) monitor_drive_eject_button, NULL);
1218 g_print ("Monitoring events. Press Ctrl+C to quit.\n");
1220 g_main_loop_run (main_loop);
1224 handle_mount (int argc, char *argv[], gboolean do_help)
1226 GOptionContext *context;
1227 gchar *param;
1228 GError *error = NULL;
1229 GFile *file;
1230 int i;
1232 g_set_prgname ("gio mount");
1234 /* Translators: commandline placeholder */
1235 param = g_strdup_printf ("[%s…]", _("LOCATION"));
1236 context = g_option_context_new (param);
1237 g_free (param);
1238 g_option_context_set_help_enabled (context, FALSE);
1239 g_option_context_set_summary (context, _("Mount or unmount the locations."));
1240 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
1242 if (do_help)
1244 show_help (context, NULL);
1245 g_option_context_free (context);
1246 return 0;
1249 if (!g_option_context_parse (context, &argc, &argv, &error))
1251 show_help (context, error->message);
1252 g_error_free (error);
1253 g_option_context_free (context);
1254 return 1;
1257 main_loop = g_main_loop_new (NULL, FALSE);
1259 if (mount_list)
1260 list_monitor_items ();
1261 else if (mount_device_file != NULL)
1262 mount_with_device_file (mount_device_file);
1263 else if (stop_device_file)
1264 stop_with_device_file (stop_device_file);
1265 else if (unmount_scheme != NULL)
1266 unmount_all_with_scheme (unmount_scheme);
1267 else if (mount_monitor)
1268 monitor ();
1269 else if (argc > 1)
1271 for (i = 1; i < argc; i++)
1273 file = g_file_new_for_commandline_arg (argv[i]);
1274 if (mount_unmount)
1275 unmount (file);
1276 else if (mount_eject)
1277 eject (file);
1278 else
1279 mount (file);
1280 g_object_unref (file);
1283 else
1285 show_help (context, _("No locations given"));
1286 g_option_context_free (context);
1287 return 1;
1290 g_option_context_free (context);
1292 if (outstanding_mounts > 0)
1293 g_main_loop_run (main_loop);
1295 return success ? 0 : 2;