543504 – crash in Epiphany Web Browser: Opening local file
[platform/upstream/glib.git] / gio / gvolume.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  *         David Zeuthen <davidz@redhat.com>
22  */
23
24 #include "config.h"
25 #include "gmount.h"
26 #include "gvolume.h"
27 #include "gasyncresult.h"
28 #include "gsimpleasyncresult.h"
29 #include "gioerror.h"
30 #include "glibintl.h"
31
32 #include "gioalias.h"
33
34 /**
35  * SECTION:gvolume
36  * @short_description: Volume management
37  * @include: gio/gio.h
38  * 
39  * The #GVolume interface represents user-visible objects that can be
40  * mounted. Note, when porting from GnomeVFS, #GVolume is the moral
41  * equivalent of #GnomeVFSDrive.
42  *
43  * Mounting a #GVolume instance is an asynchronous operation. For more
44  * information about asynchronous operations, see #GAsyncReady and
45  * #GSimpleAsyncReady. To mount a #GVolume, first call
46  * g_volume_mount() with (at least) the #GVolume instance, optionally
47  * a #GMountOperation object and a #GAsyncReadyCallback. 
48  *
49  * Typically, one will only want to pass %NULL for the
50  * #GMountOperation if automounting all volumes when a desktop session
51  * starts since it's not desirable to put up a lot of dialogs asking
52  * for credentials.
53  *
54  * The callback will be fired when the operation has resolved (either
55  * with success or failure), and a #GAsyncReady structure will be
56  * passed to the callback.  That callback should then call
57  * g_volume_mount_finish() with the #GVolume instance and the
58  * #GAsyncReady data to see if the operation was completed
59  * successfully.  If an @error is present when g_volume_mount_finish()
60  * is called, then it will be filled with any error information.
61  *
62  * <para id="volume-identifier">
63  * It is sometimes necessary to directly access the underlying 
64  * operating system object behind a volume (e.g. for passing a volume
65  * to an application via the commandline). For this purpose, GIO
66  * allows to obtain an 'identifier' for the volume. There can be
67  * different kinds of identifiers, such as Hal UDIs, filesystem labels,
68  * traditional Unix devices (e.g. <filename>/dev/sda2</filename>),
69  * uuids. GIO uses predefind strings as names for the different kinds
70  * of identifiers: #G_VOLUME_IDENTIFIER_KIND_HAL_UDI, 
71  * #G_VOLUME_IDENTIFIER_KIND_LABEL, etc. Use g_volume_get_identifier() 
72  * to obtain an identifier for a volume.
73  * </para>
74  **/
75
76 static void g_volume_base_init (gpointer g_class);
77 static void g_volume_class_init (gpointer g_class,
78                                  gpointer class_data);
79
80 GType
81 g_volume_get_type (void)
82 {
83   static volatile gsize g_define_type_id__volatile = 0;
84
85   if (g_once_init_enter (&g_define_type_id__volatile))
86     {
87       const GTypeInfo volume_info =
88       {
89         sizeof (GVolumeIface), /* class_size */
90         g_volume_base_init,   /* base_init */
91         NULL,           /* base_finalize */
92         g_volume_class_init,
93         NULL,           /* class_finalize */
94         NULL,           /* class_data */
95         0,
96         0,              /* n_preallocs */
97         NULL
98       };
99       GType g_define_type_id =
100         g_type_register_static (G_TYPE_INTERFACE, I_("GVolume"),
101                                 &volume_info, 0);
102
103       g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
104
105       g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
106     }
107
108   return g_define_type_id__volatile;
109 }
110
111 static void
112 g_volume_class_init (gpointer g_class,
113                      gpointer class_data)
114 {
115 }
116
117 static void
118 g_volume_base_init (gpointer g_class)
119 {
120   static gboolean initialized = FALSE;
121
122   if (! initialized)
123     {
124      /**
125       * GVolume::changed:
126       * 
127       * Emitted when the volume has been changed.
128       **/
129       g_signal_new (I_("changed"),
130                     G_TYPE_VOLUME,
131                     G_SIGNAL_RUN_LAST,
132                     G_STRUCT_OFFSET (GVolumeIface, changed),
133                     NULL, NULL,
134                     g_cclosure_marshal_VOID__VOID,
135                     G_TYPE_NONE, 0);
136
137      /**
138       * GVolume::removed:
139       * 
140       * This signal is emitted when the #GVolume have been removed. If
141       * the recipient is holding references to the object they should
142       * release them so the object can be finalized.
143       **/
144       g_signal_new (I_("removed"),
145                     G_TYPE_VOLUME,
146                     G_SIGNAL_RUN_LAST,
147                     G_STRUCT_OFFSET (GVolumeIface, removed),
148                     NULL, NULL,
149                     g_cclosure_marshal_VOID__VOID,
150                     G_TYPE_NONE, 0);
151
152       initialized = TRUE;
153     }
154 }
155
156 /**
157  * g_volume_get_name:
158  * @volume: a #GVolume.
159  * 
160  * Gets the name of @volume.
161  * 
162  * Returns: the name for the given @volume. The returned string should 
163  * be freed with g_free() when no longer needed.
164  **/
165 char *
166 g_volume_get_name (GVolume *volume)
167 {
168   GVolumeIface *iface;
169
170   g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
171
172   iface = G_VOLUME_GET_IFACE (volume);
173
174   return (* iface->get_name) (volume);
175 }
176
177 /**
178  * g_volume_get_icon:
179  * @volume: a #GVolume.
180  * 
181  * Gets the icon for @volume.
182  * 
183  * Returns: a #GIcon.
184  *     The returned object should be unreffed with g_object_unref()
185  *     when no longer needed.
186  **/
187 GIcon *
188 g_volume_get_icon (GVolume *volume)
189 {
190   GVolumeIface *iface;
191
192   g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
193
194   iface = G_VOLUME_GET_IFACE (volume);
195
196   return (* iface->get_icon) (volume);
197 }
198
199 /**
200  * g_volume_get_uuid:
201  * @volume: a #GVolume.
202  * 
203  * Gets the UUID for the @volume. The reference is typically based on
204  * the file system UUID for the volume in question and should be
205  * considered an opaque string. Returns %NULL if there is no UUID
206  * available.
207  * 
208  * Returns: the UUID for @volume or %NULL if no UUID can be computed.
209  *     The returned string should be freed with g_free() 
210  *     when no longer needed.
211  **/
212 char *
213 g_volume_get_uuid (GVolume *volume)
214 {
215   GVolumeIface *iface;
216
217   g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
218
219   iface = G_VOLUME_GET_IFACE (volume);
220
221   return (* iface->get_uuid) (volume);
222 }
223   
224 /**
225  * g_volume_get_drive:
226  * @volume: a #GVolume.
227  * 
228  * Gets the drive for the @volume.
229  * 
230  * Returns: a #GDrive or %NULL if @volume is not associated with a drive.
231  *     The returned object should be unreffed with g_object_unref()
232  *     when no longer needed.
233  **/
234 GDrive *
235 g_volume_get_drive (GVolume *volume)
236 {
237   GVolumeIface *iface;
238
239   g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
240
241   iface = G_VOLUME_GET_IFACE (volume);
242
243   return (* iface->get_drive) (volume);
244 }
245
246 /**
247  * g_volume_get_mount:
248  * @volume: a #GVolume.
249  * 
250  * Gets the mount for the @volume.
251  * 
252  * Returns: a #GMount or %NULL if @volume isn't mounted.
253  *     The returned object should be unreffed with g_object_unref()
254  *     when no longer needed.
255  **/
256 GMount *
257 g_volume_get_mount (GVolume *volume)
258 {
259   GVolumeIface *iface;
260
261   g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
262
263   iface = G_VOLUME_GET_IFACE (volume);
264
265   return (* iface->get_mount) (volume);
266 }
267
268
269 /**
270  * g_volume_can_mount:
271  * @volume: a #GVolume.
272  * 
273  * Checks if a volume can be mounted.
274  * 
275  * Returns: %TRUE if the @volume can be mounted. %FALSE otherwise.
276  **/
277 gboolean
278 g_volume_can_mount (GVolume *volume)
279 {
280   GVolumeIface *iface;
281
282   g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
283
284   iface = G_VOLUME_GET_IFACE (volume);
285
286   if (iface->can_mount == NULL)
287     return FALSE;
288
289   return (* iface->can_mount) (volume);
290 }
291
292 /**
293  * g_volume_can_eject:
294  * @volume: a #GVolume.
295  * 
296  * Checks if a volume can be ejected.
297  * 
298  * Returns: %TRUE if the @volume can be ejected. %FALSE otherwise.
299  **/
300 gboolean
301 g_volume_can_eject (GVolume *volume)
302 {
303   GVolumeIface *iface;
304
305   g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
306
307   iface = G_VOLUME_GET_IFACE (volume);
308
309   if (iface->can_eject == NULL)
310     return FALSE;
311
312   return (* iface->can_eject) (volume);
313 }
314
315 /**
316  * g_volume_should_automount:
317  * @volume: a #GVolume
318  *
319  * Returns whether the volume should be automatically mounted.
320  * 
321  * Returns: %TRUE if the volume should be automatically mounted.
322  */
323 gboolean
324 g_volume_should_automount (GVolume *volume)
325 {
326   GVolumeIface *iface;
327
328   g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
329
330   iface = G_VOLUME_GET_IFACE (volume);
331
332   if (iface->should_automount == NULL)
333     return FALSE;
334
335   return (* iface->should_automount) (volume);
336 }
337
338
339 /**
340  * g_volume_mount:
341  * @volume: a #GVolume.
342  * @flags: flags affecting the operation
343  * @mount_operation: a #GMountOperation or %NULL to avoid user interaction.
344  * @cancellable: optional #GCancellable object, %NULL to ignore.
345  * @callback: a #GAsyncReadyCallback, or %NULL.
346  * @user_data: user data that gets passed to @callback
347  * 
348  * Mounts a volume. This is an asynchronous operation, and is
349  * finished by calling g_volume_mount_finish() with the @volume
350  * and #GAsyncResult returned in the @callback.
351  **/
352 void
353 g_volume_mount (GVolume             *volume,
354                 GMountMountFlags     flags,
355                 GMountOperation     *mount_operation,
356                 GCancellable        *cancellable,
357                 GAsyncReadyCallback  callback,
358                 gpointer             user_data)
359 {
360   GVolumeIface *iface;
361
362   g_return_if_fail (G_IS_VOLUME (volume));
363
364   iface = G_VOLUME_GET_IFACE (volume);
365
366   if (iface->mount_fn == NULL)
367     {
368       g_simple_async_report_error_in_idle (G_OBJECT (volume), callback, user_data,
369                                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
370                                            _("volume doesn't implement mount"));
371       
372       return;
373     }
374   
375   (* iface->mount_fn) (volume, flags, mount_operation, cancellable, callback, user_data);
376 }
377
378 /**
379  * g_volume_mount_finish:
380  * @volume: a #GVolume
381  * @result: a #GAsyncResult
382  * @error: a #GError location to store an error, or %NULL to ignore
383  * 
384  * Finishes mounting a volume. If any errors occured during the operation,
385  * @error will be set to contain the errors and %FALSE will be returned.
386  * 
387  * Returns: %TRUE, %FALSE if operation failed.
388  **/
389 gboolean
390 g_volume_mount_finish (GVolume       *volume,
391                        GAsyncResult  *result,
392                        GError       **error)
393 {
394   GVolumeIface *iface;
395
396   g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
397   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
398
399   if (G_IS_SIMPLE_ASYNC_RESULT (result))
400     {
401       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
402       if (g_simple_async_result_propagate_error (simple, error))
403         return FALSE;
404     }
405   
406   iface = G_VOLUME_GET_IFACE (volume);
407   return (* iface->mount_finish) (volume, result, error);
408 }
409
410 /**
411  * g_volume_eject:
412  * @volume: a #GVolume.
413  * @flags: flags affecting the unmount if required for eject
414  * @cancellable: optional #GCancellable object, %NULL to ignore.
415  * @callback: a #GAsyncReadyCallback, or %NULL.
416  * @user_data: user data that gets passed to @callback
417  * 
418  * Ejects a volume. This is an asynchronous operation, and is
419  * finished by calling g_volume_eject_finish() with the @volume
420  * and #GAsyncResult returned in the @callback.
421  **/
422 void
423 g_volume_eject (GVolume             *volume,
424                 GMountUnmountFlags   flags,
425                 GCancellable        *cancellable,
426                 GAsyncReadyCallback  callback,
427                 gpointer             user_data)
428 {
429   GVolumeIface *iface;
430
431   g_return_if_fail (G_IS_VOLUME (volume));
432
433   iface = G_VOLUME_GET_IFACE (volume);
434
435   if (iface->eject == NULL)
436     {
437       g_simple_async_report_error_in_idle (G_OBJECT (volume), callback, user_data,
438                                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
439                                            _("volume doesn't implement eject"));
440       
441       return;
442     }
443   
444   (* iface->eject) (volume, flags, cancellable, callback, user_data);
445 }
446
447 /**
448  * g_volume_eject_finish:
449  * @volume: pointer to a #GVolume.
450  * @result: a #GAsyncResult.
451  * @error: a #GError location to store an error, or %NULL to ignore
452  * 
453  * Finishes ejecting a volume. If any errors occured during the operation,
454  * @error will be set to contain the errors and %FALSE will be returned.
455  * 
456  * Returns: %TRUE, %FALSE if operation failed.
457  **/
458 gboolean
459 g_volume_eject_finish (GVolume       *volume,
460                        GAsyncResult  *result,
461                        GError       **error)
462 {
463   GVolumeIface *iface;
464
465   g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
466   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
467
468   if (G_IS_SIMPLE_ASYNC_RESULT (result))
469     {
470       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
471       if (g_simple_async_result_propagate_error (simple, error))
472         return FALSE;
473     }
474   
475   iface = G_VOLUME_GET_IFACE (volume);
476   return (* iface->eject_finish) (volume, result, error);
477 }
478
479 /**
480  * g_volume_get_identifier:
481  * @volume: a #GVolume
482  * @kind: the kind of identifier to return
483  *
484  * Gets the identifier of the given kind for @volume. 
485  * See the <link linkend="volume-identifier">introduction</link>
486  * for more information about volume identifiers.
487  *
488  * Returns: a newly allocated string containing the
489  *   requested identfier, or %NULL if the #GVolume
490  *   doesn't have this kind of identifier
491  */
492 char *
493 g_volume_get_identifier (GVolume    *volume,
494                          const char *kind)
495 {
496   GVolumeIface *iface;
497
498   g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
499   g_return_val_if_fail (kind != NULL, NULL);
500
501   iface = G_VOLUME_GET_IFACE (volume);
502
503   if (iface->get_identifier == NULL)
504     return NULL;
505   
506   return (* iface->get_identifier) (volume, kind);
507 }
508
509 /**
510  * g_volume_enumerate_identifiers:
511  * @volume: a #GVolume
512  * 
513  * Gets the kinds of <link linkend="volume-identifier">identifiers</link>
514  * that @volume has. Use g_volume_get_identifer() to obtain 
515  * the identifiers themselves.
516  *
517  * Returns: a %NULL-terminated array of strings containing
518  *   kinds of identifiers. Use g_strfreev() to free.
519  */
520 char **
521 g_volume_enumerate_identifiers (GVolume *volume)
522 {
523   GVolumeIface *iface;
524
525   g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
526   iface = G_VOLUME_GET_IFACE (volume);
527
528   if (iface->enumerate_identifiers == NULL)
529     return NULL;
530   
531   return (* iface->enumerate_identifiers) (volume);
532 }
533
534 /**
535  * g_volume_get_activation_root:
536  * @volume: a #GVolume
537  *
538  * Gets the activation root for a #GVolume if it is known ahead of
539  * mount time. Returns %NULL otherwise. If not %NULL and if @volume
540  * is mounted, then the result of g_mount_get_root() on the
541  * #GMount object obtained from g_volume_get_mount() will always
542  * either be equal or a prefix of what this function returns. In
543  * other words, in code
544  *
545  * <programlisting>
546  *   GMount *mount;
547  *   GFile *mount_root
548  *   GFile *volume_activation_root;
549  *
550  *   mount = g_volume_get_mount (volume); /&ast; mounted, so never NULL &ast;/
551  *   mount_root = g_mount_get_root (mount);
552  *   volume_activation_root = g_volume_get_activation_root(volume); /&ast; assume not NULL &ast;/
553  * </programlisting>
554  *
555  * then the expression
556  *
557  * <programlisting>
558  *   (g_file_has_prefix (volume_activation_root, mount_root) ||
559       g_file_equal (volume_activation_root, mount_root))
560  * </programlisting>
561  *
562  * will always be %TRUE.
563  *
564  * There is a number of possible uses of this function.
565  *
566  * First, implementations of #GVolumeMonitor can use this method to
567  * determine if a #GMount should be adopted in the implementation of
568  * g_volume_monitor_adopt_orphan_mount() by testing if the result of
569  * this function equals (or has as prefix) the root of the given
570  * #GMount. In particular this is useful in the in-process proxy part
571  * of an out-of-process volume monitor implementation.
572  *
573  * Second, applications such as a file manager can use this to
574  * navigate to the correct root in response to the user navigating to
575  * a server. Now suppose there is a volume monitor for networked
576  * servers that creates #GVolume objects corresponding to the
577  * "favorite servers" (e.g. set up by the user via some "Connect to
578  * Server" dialog). Suppose also that one of the favorite servers is
579  * named "public_html @ fd.o" and the URI is
580  * <literal>sftp://people.freedesktop.org/home/david/public_html</literal>.
581  *
582  * Now, due to the way GIO works, when the corresponding #GVolume is
583  * mounted then a #GMount (typically adopted by the volume monitor)
584  * will appear with the mount root (e.g. the result of
585  * g_mount_get_root())
586  * <literal>sftp://people.freedesktop.org</literal>. However, this
587  * function (g_volume_get_activation_root()) can return a #GFile for
588  * the URI
589  * <literal>sftp://people.freedesktop.org/home/david/public_html</literal>.
590  *
591  * All this means that a file manager can use the latter URI for
592  * navigating when the user clicks an icon representing the #GVolume
593  * (e.g. clicking an icon with the name "public_html @ fd.o" or
594  * similar).
595  *
596  * Returns: the activation root of @volume or %NULL. Use
597  * g_object_unref() to free.
598  *
599  * Since: 2.18
600  **/
601 GFile *
602 g_volume_get_activation_root (GVolume *volume)
603 {
604   GVolumeIface *iface;
605
606   g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
607   iface = G_VOLUME_GET_IFACE (volume);
608
609   if (iface->get_activation_root == NULL)
610     return NULL;
611
612   return (* iface->get_activation_root) (volume);
613 }
614
615
616
617 #define __G_VOLUME_C__
618 #include "gioaliasdef.c"