1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
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.1 of the License, or (at your option) any later version.
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.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Alexander Larsson <alexl@redhat.com>
24 #include "glib-private.h"
25 #include "glocalvfs.h"
26 #include "gresourcefile.h"
27 #include "giomodule-priv.h"
33 * @short_description: Virtual File System
36 * Entry point for using GIO functionality.
40 static GRWLock additional_schemes_lock
;
42 typedef struct _GVfsPrivate
{
43 GHashTable
*additional_schemes
;
44 char const **supported_schemes
;
48 GVfsFileLookupFunc uri_func
;
50 GDestroyNotify uri_destroy
;
52 GVfsFileLookupFunc parse_name_func
;
53 gpointer parse_name_data
;
54 GDestroyNotify parse_name_destroy
;
57 G_DEFINE_TYPE_WITH_PRIVATE (GVfs
, g_vfs
, G_TYPE_OBJECT
)
60 g_vfs_dispose (GObject
*object
)
62 GVfs
*vfs
= G_VFS (object
);
63 GVfsPrivate
*priv
= g_vfs_get_instance_private (vfs
);
65 g_clear_pointer (&priv
->additional_schemes
, g_hash_table_destroy
);
66 g_clear_pointer (&priv
->supported_schemes
, g_free
);
68 G_OBJECT_CLASS (g_vfs_parent_class
)->dispose (object
);
72 g_vfs_class_init (GVfsClass
*klass
)
74 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
75 object_class
->dispose
= g_vfs_dispose
;
79 resource_parse_name (GVfs
*vfs
,
80 const char *parse_name
,
83 if (g_str_has_prefix (parse_name
, "resource:"))
84 return _g_resource_file_new (parse_name
);
90 resource_get_file_for_uri (GVfs
*vfs
,
94 return _g_resource_file_new (uri
);
98 g_vfs_uri_lookup_func_closure_free (gpointer data
)
100 GVfsURISchemeData
*closure
= data
;
102 if (closure
->uri_destroy
)
103 closure
->uri_destroy (closure
->uri_data
);
104 if (closure
->parse_name_destroy
)
105 closure
->parse_name_destroy (closure
->parse_name_data
);
111 g_vfs_init (GVfs
*vfs
)
113 GVfsPrivate
*priv
= g_vfs_get_instance_private (vfs
);
114 priv
->additional_schemes
=
115 g_hash_table_new_full (g_str_hash
, g_str_equal
,
116 g_free
, g_vfs_uri_lookup_func_closure_free
);
118 g_vfs_register_uri_scheme (vfs
, "resource",
119 resource_get_file_for_uri
, NULL
, NULL
,
120 resource_parse_name
, NULL
, NULL
);
127 * Checks if the VFS is active.
129 * Returns: %TRUE if construction of the @vfs was successful
130 * and it is now active.
133 g_vfs_is_active (GVfs
*vfs
)
137 g_return_val_if_fail (G_IS_VFS (vfs
), FALSE
);
139 class = G_VFS_GET_CLASS (vfs
);
141 return (* class->is_active
) (vfs
);
146 * g_vfs_get_file_for_path:
148 * @path: a string containing a VFS path.
150 * Gets a #GFile for @path.
152 * Returns: (transfer full): a #GFile.
153 * Free the returned object with g_object_unref().
156 g_vfs_get_file_for_path (GVfs
*vfs
,
161 g_return_val_if_fail (G_IS_VFS (vfs
), NULL
);
162 g_return_val_if_fail (path
!= NULL
, NULL
);
164 class = G_VFS_GET_CLASS (vfs
);
166 return (* class->get_file_for_path
) (vfs
, path
);
170 parse_name_internal (GVfs
*vfs
,
171 const char *parse_name
)
173 GVfsPrivate
*priv
= g_vfs_get_instance_private (vfs
);
175 GVfsURISchemeData
*closure
;
178 g_rw_lock_reader_lock (&additional_schemes_lock
);
179 g_hash_table_iter_init (&iter
, priv
->additional_schemes
);
181 while (g_hash_table_iter_next (&iter
, NULL
, (gpointer
*) &closure
))
183 ret
= closure
->parse_name_func (vfs
, parse_name
,
184 closure
->parse_name_data
);
190 g_rw_lock_reader_unlock (&additional_schemes_lock
);
196 get_file_for_uri_internal (GVfs
*vfs
,
199 GVfsPrivate
*priv
= g_vfs_get_instance_private (vfs
);
202 GVfsURISchemeData
*closure
;
204 scheme
= g_uri_parse_scheme (uri
);
208 g_rw_lock_reader_lock (&additional_schemes_lock
);
209 closure
= g_hash_table_lookup (priv
->additional_schemes
, scheme
);
212 ret
= closure
->uri_func (vfs
, uri
, closure
->uri_data
);
214 g_rw_lock_reader_unlock (&additional_schemes_lock
);
221 * g_vfs_get_file_for_uri:
223 * @uri: a string containing a URI
225 * Gets a #GFile for @uri.
227 * This operation never fails, but the returned object
228 * might not support any I/O operation if the URI
229 * is malformed or if the URI scheme is not supported.
231 * Returns: (transfer full): a #GFile.
232 * Free the returned object with g_object_unref().
235 g_vfs_get_file_for_uri (GVfs
*vfs
,
241 g_return_val_if_fail (G_IS_VFS (vfs
), NULL
);
242 g_return_val_if_fail (uri
!= NULL
, NULL
);
244 class = G_VFS_GET_CLASS (vfs
);
246 ret
= get_file_for_uri_internal (vfs
, uri
);
250 return (* class->get_file_for_uri
) (vfs
, uri
);
254 * g_vfs_get_supported_uri_schemes:
257 * Gets a list of URI schemes supported by @vfs.
259 * Returns: (transfer none): a %NULL-terminated array of strings.
260 * The returned array belongs to GIO and must
261 * not be freed or modified.
263 const gchar
* const *
264 g_vfs_get_supported_uri_schemes (GVfs
*vfs
)
268 g_return_val_if_fail (G_IS_VFS (vfs
), NULL
);
270 priv
= g_vfs_get_instance_private (vfs
);
272 if (!priv
->supported_schemes
)
275 const char * const *default_schemes
;
276 const char *additional_scheme
;
277 GPtrArray
*supported_schemes
;
280 class = G_VFS_GET_CLASS (vfs
);
282 default_schemes
= (* class->get_supported_uri_schemes
) (vfs
);
283 supported_schemes
= g_ptr_array_new ();
285 for (; default_schemes
&& *default_schemes
; default_schemes
++)
286 g_ptr_array_add (supported_schemes
, (gpointer
) *default_schemes
);
288 g_rw_lock_reader_lock (&additional_schemes_lock
);
289 g_hash_table_iter_init (&iter
, priv
->additional_schemes
);
291 while (g_hash_table_iter_next
292 (&iter
, (gpointer
*) &additional_scheme
, NULL
))
293 g_ptr_array_add (supported_schemes
, (gpointer
) additional_scheme
);
295 g_rw_lock_reader_unlock (&additional_schemes_lock
);
297 g_ptr_array_add (supported_schemes
, NULL
);
299 g_free (priv
->supported_schemes
);
300 priv
->supported_schemes
=
301 (char const **) g_ptr_array_free (supported_schemes
, FALSE
);
304 return priv
->supported_schemes
;
310 * @parse_name: a string to be parsed by the VFS module.
312 * This operation never fails, but the returned object might
313 * not support any I/O operations if the @parse_name cannot
314 * be parsed by the #GVfs module.
316 * Returns: (transfer full): a #GFile for the given @parse_name.
317 * Free the returned object with g_object_unref().
320 g_vfs_parse_name (GVfs
*vfs
,
321 const char *parse_name
)
326 g_return_val_if_fail (G_IS_VFS (vfs
), NULL
);
327 g_return_val_if_fail (parse_name
!= NULL
, NULL
);
329 class = G_VFS_GET_CLASS (vfs
);
331 ret
= parse_name_internal (vfs
, parse_name
);
335 return (* class->parse_name
) (vfs
, parse_name
);
341 * Gets the default #GVfs for the system.
343 * Returns: (transfer none): a #GVfs.
346 g_vfs_get_default (void)
348 if (GLIB_PRIVATE_CALL (g_check_setuid
) ())
349 return g_vfs_get_local ();
350 return _g_io_module_get_default (G_VFS_EXTENSION_POINT_NAME
,
352 (GIOModuleVerifyFunc
)g_vfs_is_active
);
358 * Gets the local #GVfs for the system.
360 * Returns: (transfer none): a #GVfs.
363 g_vfs_get_local (void)
365 static gsize vfs
= 0;
367 if (g_once_init_enter (&vfs
))
368 g_once_init_leave (&vfs
, (gsize
)_g_local_vfs_new ());
374 * g_vfs_register_uri_scheme:
376 * @scheme: an URI scheme, e.g. "http"
377 * @uri_func: (scope notified) (nullable): a #GVfsFileLookupFunc
378 * @uri_data: (nullable): custom data passed to be passed to @uri_func, or %NULL
379 * @uri_destroy: (nullable): function to be called when unregistering the
380 * URI scheme, or when @vfs is disposed, to free the resources used
381 * by the URI lookup function
382 * @parse_name_func: (scope notified) (nullable): a #GVfsFileLookupFunc
383 * @parse_name_data: (nullable): custom data passed to be passed to
384 * @parse_name_func, or %NULL
385 * @parse_name_destroy: (nullable): function to be called when unregistering the
386 * URI scheme, or when @vfs is disposed, to free the resources used
387 * by the parse name lookup function
389 * Registers @uri_func and @parse_name_func as the #GFile URI and parse name
390 * lookup functions for URIs with a scheme matching @scheme.
391 * Note that @scheme is registered only within the running application, as
392 * opposed to desktop-wide as it happens with GVfs backends.
394 * When a #GFile is requested with an URI containing @scheme (e.g. through
395 * g_file_new_for_uri()), @uri_func will be called to allow a custom
396 * constructor. The implementation of @uri_func should not be blocking, and
397 * must not call g_vfs_register_uri_scheme() or g_vfs_unregister_uri_scheme().
399 * When g_file_parse_name() is called with a parse name obtained from such file,
400 * @parse_name_func will be called to allow the #GFile to be created again. In
401 * that case, it's responsibility of @parse_name_func to make sure the parse
402 * name matches what the custom #GFile implementation returned when
403 * g_file_get_parse_name() was previously called. The implementation of
404 * @parse_name_func should not be blocking, and must not call
405 * g_vfs_register_uri_scheme() or g_vfs_unregister_uri_scheme().
407 * It's an error to call this function twice with the same scheme. To unregister
408 * a custom URI scheme, use g_vfs_unregister_uri_scheme().
410 * Returns: %TRUE if @scheme was successfully registered, or %FALSE if a handler
411 * for @scheme already exists.
416 g_vfs_register_uri_scheme (GVfs
*vfs
,
418 GVfsFileLookupFunc uri_func
,
420 GDestroyNotify uri_destroy
,
421 GVfsFileLookupFunc parse_name_func
,
422 gpointer parse_name_data
,
423 GDestroyNotify parse_name_destroy
)
426 GVfsURISchemeData
*closure
;
428 g_return_val_if_fail (G_IS_VFS (vfs
), FALSE
);
429 g_return_val_if_fail (scheme
!= NULL
, FALSE
);
431 priv
= g_vfs_get_instance_private (vfs
);
433 g_rw_lock_reader_lock (&additional_schemes_lock
);
434 closure
= g_hash_table_lookup (priv
->additional_schemes
, scheme
);
435 g_rw_lock_reader_unlock (&additional_schemes_lock
);
440 closure
= g_new0 (GVfsURISchemeData
, 1);
441 closure
->uri_func
= uri_func
;
442 closure
->uri_data
= uri_data
;
443 closure
->uri_destroy
= uri_destroy
;
444 closure
->parse_name_func
= parse_name_func
;
445 closure
->parse_name_data
= parse_name_data
;
446 closure
->parse_name_destroy
= parse_name_destroy
;
448 g_rw_lock_writer_lock (&additional_schemes_lock
);
449 g_hash_table_insert (priv
->additional_schemes
, g_strdup (scheme
), closure
);
450 g_rw_lock_writer_unlock (&additional_schemes_lock
);
452 /* Invalidate supported schemes */
453 g_clear_pointer (&priv
->supported_schemes
, g_free
);
459 * g_vfs_unregister_uri_scheme:
461 * @scheme: an URI scheme, e.g. "http"
463 * Unregisters the URI handler for @scheme previously registered with
464 * g_vfs_register_uri_scheme().
466 * Returns: %TRUE if @scheme was successfully unregistered, or %FALSE if a
467 * handler for @scheme does not exist.
472 g_vfs_unregister_uri_scheme (GVfs
*vfs
,
478 g_return_val_if_fail (G_IS_VFS (vfs
), FALSE
);
479 g_return_val_if_fail (scheme
!= NULL
, FALSE
);
481 priv
= g_vfs_get_instance_private (vfs
);
483 g_rw_lock_writer_lock (&additional_schemes_lock
);
484 res
= g_hash_table_remove (priv
->additional_schemes
, scheme
);
485 g_rw_lock_writer_unlock (&additional_schemes_lock
);
489 /* Invalidate supported schemes */
490 g_clear_pointer (&priv
->supported_schemes
, g_free
);