[glib/resources: 6/6] Support resource:/// uris
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/resources: 6/6] Support resource:/// uris
- Date: Wed, 21 Dec 2011 22:44:09 +0000 (UTC)
commit 2b70d664aad3760e611a988de34acf8524c54da6
Author: Alexander Larsson <alexl redhat com>
Date: Wed Dec 21 23:37:56 2011 +0100
Support resource:/// uris
gio/Makefile.am | 2 +
gio/gresourcefile.c | 655 +++++++++++++++++++++++++++++++++++++++++++++++++++
gio/gresourcefile.h | 51 ++++
gio/gvfs.c | 11 +
4 files changed, 719 insertions(+), 0 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 36b6c30..1ce2cb2 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -378,6 +378,8 @@ libgio_2_0_la_SOURCES = \
gproxyresolver.c \
gresolver.c \
gresource.c \
+ gresourcefile.c \
+ gresourcefile.h \
gseekable.c \
gsimpleasyncresult.c \
gsimplepermission.c \
diff --git a/gio/gresourcefile.c b/gio/gresourcefile.c
new file mode 100644
index 0000000..f6e7277
--- /dev/null
+++ b/gio/gresourcefile.c
@@ -0,0 +1,655 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 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: Alexander Larsson <alexl redhat com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "gresource.h"
+#include "gresourcefile.h"
+#include "gfileattribute.h"
+#include <gfileattribute-priv.h>
+#include <gfileinfo-priv.h>
+#include "gfile.h"
+#include "gfileinfo.h"
+#include "gfileenumerator.h"
+#include "gioerror.h"
+#include <glib/gstdio.h>
+#include "glibintl.h"
+
+struct _GResourceFile
+{
+ GObject parent_instance;
+
+ char *path;
+};
+
+struct _GResourceFileEnumerator
+{
+ GFileEnumerator parent;
+
+ GFileAttributeMatcher *matcher;
+ char *path;
+ char *attributes;
+ GFileQueryInfoFlags flags;
+ int index;
+
+ char **children;
+};
+
+struct _GResourceFileEnumeratorClass
+{
+ GFileEnumeratorClass parent_class;
+};
+
+typedef struct _GResourceFileEnumerator GResourceFileEnumerator;
+typedef struct _GResourceFileEnumeratorClass GResourceFileEnumeratorClass;
+
+static void g_resource_file_file_iface_init (GFileIface *iface);
+
+static GFileAttributeInfoList *resource_writable_attributes = NULL;
+static GFileAttributeInfoList *resource_writable_namespaces = NULL;
+
+#define G_TYPE_RESOURCE_FILE_ENUMERATOR (_g_resource_file_enumerator_get_type ())
+#define G_RESOURCE_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumerator))
+#define G_RESOURCE_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
+#define G_IS_RESOURCE_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR))
+#define G_IS_RESOURCE_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_ENUMERATOR))
+#define G_RESOURCE_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
+
+
+
+#define g_resource_file_get_type _g_resource_file_get_type
+G_DEFINE_TYPE_WITH_CODE (GResourceFile, g_resource_file, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
+ g_resource_file_file_iface_init))
+
+#define g_resource_file_enumerator_get_type _g_resource_file_enumerator_get_type
+G_DEFINE_TYPE (GResourceFileEnumerator, g_resource_file_enumerator, G_TYPE_FILE_ENUMERATOR);
+
+static GFileEnumerator *_g_resource_file_enumerator_new (GResourceFile *file,
+ const char *attributes,
+ GFileQueryInfoFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+static void
+g_resource_file_finalize (GObject *object)
+{
+ GResourceFile *resource;
+
+ resource = G_RESOURCE_FILE (object);
+
+ g_free (resource->path);
+
+ G_OBJECT_CLASS (g_resource_file_parent_class)->finalize (object);
+}
+
+static void
+g_resource_file_class_init (GResourceFileClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_resource_file_finalize;
+
+ resource_writable_attributes = g_file_attribute_info_list_new ();
+ resource_writable_namespaces = g_file_attribute_info_list_new ();
+}
+
+static void
+g_resource_file_init (GResourceFile *resource)
+{
+}
+
+static char *
+canonicalize_filename (const char *filename)
+{
+ char *canon, *start, *p, *q;
+
+ /* Skip multiple inital slashes */
+ while (filename[0] == '/' && filename[1] == '/')
+ filename++;
+
+ if (*filename != '/')
+ canon = g_strconcat ("/", filename, NULL);
+ else
+ canon = g_strdup (filename);
+
+ start = canon + 1;
+
+ p = start;
+ while (*p != 0)
+ {
+ if (p[0] == '.' && (p[1] == 0 || p[1] == '/'))
+ {
+ memmove (p, p+1, strlen (p+1)+1);
+ }
+ else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || p[2] == '/'))
+ {
+ q = p + 2;
+ /* Skip previous separator */
+ p = p - 2;
+ if (p < start)
+ p = start;
+ while (p > start && *p != '/')
+ p--;
+ if (*p == '/')
+ *p++ = '/';
+ memmove (p, q, strlen (q)+1);
+ }
+ else
+ {
+ /* Skip until next separator */
+ while (*p != 0 && *p != '/')
+ p++;
+
+ if (*p != 0)
+ {
+ /* Canonicalize one separator */
+ *p++ = '/';
+ }
+ }
+
+ /* Remove additional separators */
+ q = p;
+ while (*q && *q == '/')
+ q++;
+
+ if (p != q)
+ memmove (p, q, strlen (q)+1);
+ }
+
+ /* Remove trailing slashes */
+ if (p > start && *(p-1) == '/')
+ *(p-1) = 0;
+
+ return canon;
+}
+
+static GFile *
+g_resource_file_new_for_path (const char *path)
+{
+ GResourceFile *resource = g_object_new (G_TYPE_RESOURCE_FILE, NULL);
+
+ resource->path = canonicalize_filename (path);
+
+ return G_FILE (resource);
+}
+
+GFile *
+_g_resource_file_new (const char *uri)
+{
+ GFile *resource;
+ char *path;
+
+ path = g_uri_unescape_string (uri + strlen ("resource:"), NULL);
+ resource = g_resource_file_new_for_path (path);
+ g_free (path);
+
+ return G_FILE (resource);
+}
+
+static gboolean
+g_resource_file_is_native (GFile *file)
+{
+ return FALSE;
+}
+
+static gboolean
+g_resource_file_has_uri_scheme (GFile *file,
+ const char *uri_scheme)
+{
+ return g_ascii_strcasecmp (uri_scheme, "resource") == 0;
+}
+
+static char *
+g_resource_file_get_uri_scheme (GFile *file)
+{
+ return g_strdup ("resource");
+}
+
+static char *
+g_resource_file_get_basename (GFile *file)
+{
+ gchar *base;
+
+ base = strrchr (G_RESOURCE_FILE (file)->path, '/');
+ return g_strdup (base + 1);
+}
+
+static char *
+g_resource_file_get_path (GFile *file)
+{
+ return NULL;
+}
+
+static char *
+g_resource_file_get_uri (GFile *file)
+{
+ char *escaped, *res;
+ escaped = g_uri_escape_string (G_RESOURCE_FILE (file)->path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
+ res = g_strconcat ("resource://", escaped, NULL);
+ g_free (escaped);
+ return res;
+}
+
+static char *
+g_resource_file_get_parse_name (GFile *file)
+{
+ return g_resource_file_get_uri (file);
+}
+
+static GFile *
+g_resource_file_get_parent (GFile *file)
+{
+ GResourceFile *resource = G_RESOURCE_FILE (file);
+ GResourceFile *parent;
+ gchar *end;
+
+ end = strrchr (resource->path, '/');
+
+ if (end == G_RESOURCE_FILE (file)->path)
+ return NULL;
+
+ parent = g_object_new (G_TYPE_RESOURCE_FILE, NULL);
+ parent->path = g_strndup (resource->path,
+ end - resource->path - 1);
+
+ return G_FILE (parent);
+}
+
+static GFile *
+g_resource_file_dup (GFile *file)
+{
+ GResourceFile *resource = G_RESOURCE_FILE (file);
+
+ return g_resource_file_new_for_path (resource->path);
+}
+
+static guint
+g_resource_file_hash (GFile *file)
+{
+ GResourceFile *resource = G_RESOURCE_FILE (file);
+
+ return g_str_hash (resource->path);
+}
+
+static gboolean
+g_resource_file_equal (GFile *file1,
+ GFile *file2)
+{
+ GResourceFile *resource1 = G_RESOURCE_FILE (file1);
+ GResourceFile *resource2 = G_RESOURCE_FILE (file2);
+
+ return g_str_equal (resource1->path, resource2->path);
+}
+
+static const char *
+match_prefix (const char *path,
+ const char *prefix)
+{
+ int prefix_len;
+
+ prefix_len = strlen (prefix);
+ if (strncmp (path, prefix, prefix_len) != 0)
+ return NULL;
+
+ /* Handle the case where prefix is the root, so that
+ * the IS_DIR_SEPRARATOR check below works */
+ if (prefix_len > 0 &&
+ prefix[prefix_len-1] == '/')
+ prefix_len--;
+
+ return path + prefix_len;
+}
+
+static gboolean
+g_resource_file_prefix_matches (GFile *parent,
+ GFile *descendant)
+{
+ GResourceFile *parent_resource = G_RESOURCE_FILE (parent);
+ GResourceFile *descendant_resource = G_RESOURCE_FILE (descendant);
+ const char *remainder;
+
+ remainder = match_prefix (descendant_resource->path, parent_resource->path);
+ if (remainder != NULL && *remainder == '/')
+ return TRUE;
+ return FALSE;
+}
+
+static char *
+g_resource_file_get_relative_path (GFile *parent,
+ GFile *descendant)
+{
+ GResourceFile *parent_resource = G_RESOURCE_FILE (parent);
+ GResourceFile *descendant_resource = G_RESOURCE_FILE (descendant);
+ const char *remainder;
+
+ remainder = match_prefix (descendant_resource->path, parent_resource->path);
+
+ if (remainder != NULL && *remainder == '/')
+ return g_strdup (remainder + 1);
+ return NULL;
+}
+
+static GFile *
+g_resource_file_resolve_relative_path (GFile *file,
+ const char *relative_path)
+{
+ GResourceFile *resource = G_RESOURCE_FILE (file);
+ char *filename;
+ GFile *child;
+
+ if (relative_path[0] == '/')
+ return g_resource_file_new_for_path (relative_path);
+
+ filename = g_build_path ("/", resource->path, relative_path, NULL);
+ child = g_resource_file_new_for_path (filename);
+ g_free (filename);
+
+ return child;
+}
+
+static GFileEnumerator *
+g_resource_file_enumerate_children (GFile *file,
+ const char *attributes,
+ GFileQueryInfoFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GResourceFile *resource = G_RESOURCE_FILE (file);
+ return _g_resource_file_enumerator_new (resource,
+ attributes, flags,
+ cancellable, error);
+}
+
+static GFile *
+g_resource_file_get_child_for_display_name (GFile *file,
+ const char *display_name,
+ GError **error)
+{
+ GFile *new_file;
+
+ new_file = g_file_get_child (file, display_name);
+
+ return new_file;
+}
+
+static GFileInfo *
+g_resource_file_query_info (GFile *file,
+ const char *attributes,
+ GFileQueryInfoFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GResourceFile *resource = G_RESOURCE_FILE (file);
+ GError *my_error = NULL;
+ GFileInfo *info;
+ gboolean res;
+ gsize size;
+ guint32 resource_flags;
+ char **children;
+ gboolean is_dir;
+ char *base;
+
+ is_dir = FALSE;
+ children = g_resources_enumerate_children (resource->path, NULL);
+ if (children != NULL)
+ {
+ g_strfreev (children);
+ is_dir = TRUE;
+ }
+
+ /* root is always there */
+ if (strcmp ("/", resource->path) == 0)
+ is_dir = TRUE;
+
+ if (!is_dir)
+ {
+ res = g_resources_get_info (resource->path, &size, &resource_flags, &my_error);
+ if (!res)
+ {
+ if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("The resource at '%s' does not exist"),
+ resource->path);
+ }
+ else
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ my_error->message);
+ g_clear_error (&my_error);
+ return FALSE;
+ }
+ }
+
+
+ info = g_file_info_new ();
+ base = g_resource_file_get_basename (file);
+ g_file_info_set_name (info, base);
+
+ _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ, TRUE);
+ _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE, FALSE);
+ _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE, FALSE);
+ _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME, FALSE);
+ _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE, FALSE);
+ _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH, FALSE);
+
+ if (is_dir)
+ {
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ }
+ else
+ {
+ g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
+ g_file_info_set_size (info, size);
+ }
+
+ return info;
+}
+
+static GFileAttributeInfoList *
+g_resource_file_query_settable_attributes (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_file_attribute_info_list_ref (resource_writable_attributes);
+}
+
+static GFileAttributeInfoList *
+g_resource_file_query_writable_namespaces (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_file_attribute_info_list_ref (resource_writable_namespaces);
+}
+
+static GFileInputStream *
+g_resource_file_read (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GResourceFile *resource = G_RESOURCE_FILE (file);
+ GError *my_error = NULL;
+ GInputStream *stream;
+
+ stream = g_resources_open_stream (resource->path, &my_error);
+
+ if (stream == NULL)
+ {
+ if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("The resource at '%s' does not exist"),
+ resource->path);
+ }
+ else
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ my_error->message);
+ g_clear_error (&my_error);
+ return NULL;
+ }
+
+ /* TODO: This isn't right, we need to wrap the stream */
+ return (GFileInputStream *)stream;
+}
+
+static void
+g_resource_file_file_iface_init (GFileIface *iface)
+{
+ iface->dup = g_resource_file_dup;
+ iface->hash = g_resource_file_hash;
+ iface->equal = g_resource_file_equal;
+ iface->is_native = g_resource_file_is_native;
+ iface->has_uri_scheme = g_resource_file_has_uri_scheme;
+ iface->get_uri_scheme = g_resource_file_get_uri_scheme;
+ iface->get_basename = g_resource_file_get_basename;
+ iface->get_path = g_resource_file_get_path;
+ iface->get_uri = g_resource_file_get_uri;
+ iface->get_parse_name = g_resource_file_get_parse_name;
+ iface->get_parent = g_resource_file_get_parent;
+ iface->prefix_matches = g_resource_file_prefix_matches;
+ iface->get_relative_path = g_resource_file_get_relative_path;
+ iface->resolve_relative_path = g_resource_file_resolve_relative_path;
+ iface->get_child_for_display_name = g_resource_file_get_child_for_display_name;
+ iface->enumerate_children = g_resource_file_enumerate_children;
+ iface->query_info = g_resource_file_query_info;
+ iface->query_settable_attributes = g_resource_file_query_settable_attributes;
+ iface->query_writable_namespaces = g_resource_file_query_writable_namespaces;
+ iface->read_fn = g_resource_file_read;
+
+ iface->supports_thread_contexts = TRUE;
+}
+
+static GFileInfo *g_resource_file_enumerator_next_file (GFileEnumerator *enumerator,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean g_resource_file_enumerator_close (GFileEnumerator *enumerator,
+ GCancellable *cancellable,
+ GError **error);
+
+static void
+g_resource_file_enumerator_finalize (GObject *object)
+{
+ GResourceFileEnumerator *resource;
+
+ resource = G_RESOURCE_FILE_ENUMERATOR (object);
+
+ g_strfreev (resource->children);
+ g_free (resource->path);
+ g_free (resource->attributes);
+
+ G_OBJECT_CLASS (g_resource_file_enumerator_parent_class)->finalize (object);
+}
+
+static void
+g_resource_file_enumerator_class_init (GResourceFileEnumeratorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
+
+ gobject_class->finalize = g_resource_file_enumerator_finalize;
+
+ enumerator_class->next_file = g_resource_file_enumerator_next_file;
+ enumerator_class->close_fn = g_resource_file_enumerator_close;
+}
+
+static void
+g_resource_file_enumerator_init (GResourceFileEnumerator *resource)
+{
+}
+
+static GFileEnumerator *
+_g_resource_file_enumerator_new (GResourceFile *file,
+ const char *attributes,
+ GFileQueryInfoFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GResourceFileEnumerator *resource;
+ char **children;
+ gboolean res;
+
+ children = g_resources_enumerate_children (file->path, NULL);
+ if (children == NULL &&
+ strcmp ("/", file->path) != 0)
+ {
+ res = g_resources_get_info (file->path, NULL, NULL, NULL);
+ if (res)
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
+ _("The resource at '%s' is not a directory"),
+ file->path);
+ else
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("The resource at '%s' does not exist"),
+ file->path);
+ return NULL;
+ }
+
+ resource = g_object_new (G_TYPE_RESOURCE_FILE_ENUMERATOR,
+ "container", file,
+ NULL);
+
+ resource->children = children;
+ resource->path = g_strdup (file->path);
+ resource->attributes = g_strdup (attributes);
+ resource->flags = flags;
+
+ return G_FILE_ENUMERATOR (resource);
+}
+
+static GFileInfo *
+g_resource_file_enumerator_next_file (GFileEnumerator *enumerator,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GResourceFileEnumerator *resource = G_RESOURCE_FILE_ENUMERATOR (enumerator);
+ char *path;
+ GFileInfo *info;
+ GFile *file;
+
+ if (resource->children == NULL ||
+ resource->children[resource->index] == NULL)
+ return NULL;
+
+ path = g_build_path ("/", resource->path, resource->children[resource->index++], NULL);
+ file = g_resource_file_new_for_path (path);
+ g_free (path);
+
+ info = g_file_query_info (file,
+ resource->attributes,
+ resource->flags,
+ cancellable,
+ error);
+
+ g_object_unref (file);
+
+ return info;
+}
+
+static gboolean
+g_resource_file_enumerator_close (GFileEnumerator *enumerator,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return TRUE;
+}
diff --git a/gio/gresourcefile.h b/gio/gresourcefile.h
new file mode 100644
index 0000000..2c792b0
--- /dev/null
+++ b/gio/gresourcefile.h
@@ -0,0 +1,51 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2011 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: Alexander Larsson <alexl redhat com>
+ */
+
+#ifndef __G_RESOURCE_FILE_H__
+#define __G_RESOURCE_FILE_H__
+
+#include <gio/giotypes.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_RESOURCE_FILE (_g_resource_file_get_type ())
+#define G_RESOURCE_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE, GResourceFile))
+#define G_RESOURCE_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE, GResourceFileClass))
+#define G_IS_RESOURCE_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE))
+#define G_IS_RESOURCE_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE))
+#define G_RESOURCE_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE, GResourceFileClass))
+
+typedef struct _GResourceFile GResourceFile;
+typedef struct _GResourceFileClass GResourceFileClass;
+
+struct _GResourceFileClass
+{
+ GObjectClass parent_class;
+};
+
+GType _g_resource_file_get_type (void) G_GNUC_CONST;
+
+GFile * _g_resource_file_new (const char *uri);
+
+G_END_DECLS
+
+#endif /* __G_RESOURCE_FILE_H__ */
diff --git a/gio/gvfs.c b/gio/gvfs.c
index cbe7f2f..dda8afb 100644
--- a/gio/gvfs.c
+++ b/gio/gvfs.c
@@ -24,6 +24,7 @@
#include <string.h>
#include "gvfs.h"
#include "glocalvfs.h"
+#include "gresourcefile.h"
#include "giomodule-priv.h"
#include "glibintl.h"
@@ -119,6 +120,13 @@ g_vfs_get_file_for_uri (GVfs *vfs,
class = G_VFS_GET_CLASS (vfs);
+ /* This is an unfortunate placement, but we really
+ need to check this before chaining to the vfs,
+ because we want to support resource uris for
+ all vfs:es, even those that predate resources. */
+ if (g_str_has_prefix (uri, "resource:"))
+ return _g_resource_file_new (uri);
+
return (* class->get_file_for_uri) (vfs, uri);
}
@@ -167,6 +175,9 @@ g_vfs_parse_name (GVfs *vfs,
class = G_VFS_GET_CLASS (vfs);
+ if (g_str_has_prefix (parse_name, "resource:"))
+ return _g_resource_file_new (parse_name);
+
return (* class->parse_name) (vfs, parse_name);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]