Blame gio/gresourcefile.c

Packit 84794d
/* GIO - GLib Input, Output and Streaming Library
Packit 84794d
 *
Packit 84794d
 * Copyright (C) 2006-2007 Red Hat, Inc.
Packit 84794d
 *
Packit 84794d
 * This library is free software; you can redistribute it and/or
Packit 84794d
 * modify it under the terms of the GNU Lesser General Public
Packit 84794d
 * License as published by the Free Software Foundation; either
Packit 84794d
 * version 2.1 of the License, or (at your option) any later version.
Packit 84794d
 *
Packit 84794d
 * This library is distributed in the hope that it will be useful,
Packit 84794d
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 84794d
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 84794d
 * Lesser General Public License for more details.
Packit 84794d
 *
Packit 84794d
 * You should have received a copy of the GNU Lesser General
Packit 84794d
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit 84794d
 *
Packit 84794d
 * Author: Alexander Larsson <alexl@redhat.com>
Packit 84794d
 */
Packit 84794d
Packit 84794d
#include "config.h"
Packit 84794d
Packit 84794d
#include <string.h>
Packit 84794d
Packit 84794d
#include "gresource.h"
Packit 84794d
#include "gresourcefile.h"
Packit 84794d
#include "gfileattribute.h"
Packit 84794d
#include <gfileattribute-priv.h>
Packit 84794d
#include <gfileinfo-priv.h>
Packit 84794d
#include "gfile.h"
Packit 84794d
#include "gfilemonitor.h"
Packit 84794d
#include "gseekable.h"
Packit 84794d
#include "gfileinputstream.h"
Packit 84794d
#include "gfileinfo.h"
Packit 84794d
#include "gfileenumerator.h"
Packit 84794d
#include "gcontenttype.h"
Packit 84794d
#include "gioerror.h"
Packit 84794d
#include <glib/gstdio.h>
Packit 84794d
#include "glibintl.h"
Packit 84794d
Packit 84794d
struct _GResourceFile
Packit 84794d
{
Packit 84794d
  GObject parent_instance;
Packit 84794d
Packit 84794d
  char *path;
Packit 84794d
};
Packit 84794d
Packit 84794d
struct _GResourceFileEnumerator
Packit 84794d
{
Packit 84794d
  GFileEnumerator parent;
Packit 84794d
Packit 84794d
  GFileAttributeMatcher *matcher;
Packit 84794d
  char *path;
Packit 84794d
  char *attributes;
Packit 84794d
  GFileQueryInfoFlags flags;
Packit 84794d
  int index;
Packit 84794d
Packit 84794d
  char **children;
Packit 84794d
};
Packit 84794d
Packit 84794d
struct _GResourceFileEnumeratorClass
Packit 84794d
{
Packit 84794d
  GFileEnumeratorClass parent_class;
Packit 84794d
};
Packit 84794d
Packit 84794d
typedef struct _GResourceFileEnumerator        GResourceFileEnumerator;
Packit 84794d
typedef struct _GResourceFileEnumeratorClass   GResourceFileEnumeratorClass;
Packit 84794d
Packit 84794d
static void g_resource_file_file_iface_init (GFileIface *iface);
Packit 84794d
Packit 84794d
static GFileAttributeInfoList *resource_writable_attributes = NULL;
Packit 84794d
static GFileAttributeInfoList *resource_writable_namespaces = NULL;
Packit 84794d
Packit 84794d
static GType _g_resource_file_enumerator_get_type (void);
Packit 84794d
Packit 84794d
#define G_TYPE_RESOURCE_FILE_ENUMERATOR         (_g_resource_file_enumerator_get_type ())
Packit 84794d
#define G_RESOURCE_FILE_ENUMERATOR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumerator))
Packit 84794d
#define G_RESOURCE_FILE_ENUMERATOR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
Packit 84794d
#define G_IS_RESOURCE_FILE_ENUMERATOR(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR))
Packit 84794d
#define G_IS_RESOURCE_FILE_ENUMERATOR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_ENUMERATOR))
Packit 84794d
#define G_RESOURCE_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
Packit 84794d
Packit 84794d
#define G_TYPE_RESOURCE_FILE_INPUT_STREAM         (_g_resource_file_input_stream_get_type ())
Packit 84794d
#define G_RESOURCE_FILE_INPUT_STREAM(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStream))
Packit 84794d
#define G_RESOURCE_FILE_INPUT_STREAM_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
Packit 84794d
#define G_IS_RESOURCE_FILE_INPUT_STREAM(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
Packit 84794d
#define G_IS_RESOURCE_FILE_INPUT_STREAM_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
Packit 84794d
#define G_RESOURCE_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
Packit 84794d
Packit 84794d
typedef struct _GResourceFileInputStream         GResourceFileInputStream;
Packit 84794d
typedef struct _GResourceFileInputStreamClass    GResourceFileInputStreamClass;
Packit 84794d
Packit 84794d
#define g_resource_file_get_type _g_resource_file_get_type
Packit 84794d
G_DEFINE_TYPE_WITH_CODE (GResourceFile, g_resource_file, G_TYPE_OBJECT,
Packit 84794d
			 G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
Packit 84794d
						g_resource_file_file_iface_init))
Packit 84794d
Packit 84794d
#define g_resource_file_enumerator_get_type _g_resource_file_enumerator_get_type
Packit 84794d
G_DEFINE_TYPE (GResourceFileEnumerator, g_resource_file_enumerator, G_TYPE_FILE_ENUMERATOR)
Packit 84794d
Packit 84794d
static GFileEnumerator *_g_resource_file_enumerator_new (GResourceFile *file,
Packit 84794d
							 const char           *attributes,
Packit 84794d
							 GFileQueryInfoFlags   flags,
Packit 84794d
							 GCancellable         *cancellable,
Packit 84794d
							 GError              **error);
Packit 84794d
Packit 84794d
Packit 84794d
static GType              _g_resource_file_input_stream_get_type (void) G_GNUC_CONST;
Packit 84794d
Packit 84794d
static GFileInputStream *_g_resource_file_input_stream_new (GInputStream *stream, GFile *file);
Packit 84794d
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_finalize (GObject *object)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource;
Packit 84794d
Packit 84794d
  resource = G_RESOURCE_FILE (object);
Packit 84794d
Packit 84794d
  g_free (resource->path);
Packit 84794d
Packit 84794d
  G_OBJECT_CLASS (g_resource_file_parent_class)->finalize (object);
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_class_init (GResourceFileClass *klass)
Packit 84794d
{
Packit 84794d
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit 84794d
Packit 84794d
  gobject_class->finalize = g_resource_file_finalize;
Packit 84794d
Packit 84794d
  resource_writable_attributes = g_file_attribute_info_list_new ();
Packit 84794d
  resource_writable_namespaces = g_file_attribute_info_list_new ();
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_init (GResourceFile *resource)
Packit 84794d
{
Packit 84794d
}
Packit 84794d
Packit 84794d
static inline gchar *
Packit 84794d
scan_backwards (const gchar *begin,
Packit 84794d
                const gchar *end,
Packit 84794d
                gchar        c)
Packit 84794d
{
Packit 84794d
  while (end >= begin)
Packit 84794d
    {
Packit 84794d
      if (*end == c)
Packit 84794d
        return (gchar *)end;
Packit 84794d
      end--;
Packit 84794d
    }
Packit 84794d
Packit 84794d
  return NULL;
Packit 84794d
}
Packit 84794d
Packit 84794d
static inline void
Packit 84794d
pop_to_previous_part (const gchar  *begin,
Packit 84794d
                      gchar       **out)
Packit 84794d
{
Packit 84794d
  if (*out > begin)
Packit 84794d
    *out = scan_backwards (begin, *out - 1, '/');
Packit 84794d
}
Packit 84794d
Packit 84794d
/*
Packit 84794d
 * canonicalize_filename:
Packit 84794d
 * @in: the path to be canonicalized
Packit 84794d
 *
Packit 84794d
 * The path @in may contain non-canonical path pieces such as "../"
Packit 84794d
 * or duplicated "/". This will resolve those into a form that only
Packit 84794d
 * contains a single / at a time and resolves all "../". The resulting
Packit 84794d
 * path must also start with a /.
Packit 84794d
 *
Packit 84794d
 * Returns: the canonical form of the path
Packit 84794d
 */
Packit 84794d
static char *
Packit 84794d
canonicalize_filename (const char *in)
Packit 84794d
{
Packit 84794d
  gchar *bptr;
Packit 84794d
  char *out;
Packit 84794d
Packit 84794d
  bptr = out = g_malloc (strlen (in) + 2);
Packit 84794d
  *out = '/';
Packit 84794d
Packit 84794d
  while (*in != 0)
Packit 84794d
    {
Packit 84794d
      g_assert (*out == '/');
Packit 84794d
Packit 84794d
      /* move past slashes */
Packit 84794d
      while (*in == '/')
Packit 84794d
        in++;
Packit 84794d
Packit 84794d
      /* Handle ./ ../ .\0 ..\0 */
Packit 84794d
      if (*in == '.')
Packit 84794d
        {
Packit 84794d
          /* If this is ../ or ..\0 move up */
Packit 84794d
          if (in[1] == '.' && (in[2] == '/' || in[2] == 0))
Packit 84794d
            {
Packit 84794d
              pop_to_previous_part (bptr, &out;;
Packit 84794d
              in += 2;
Packit 84794d
              continue;
Packit 84794d
            }
Packit 84794d
Packit 84794d
          /* If this is ./ skip past it */
Packit 84794d
          if (in[1] == '/' || in[1] == 0)
Packit 84794d
            {
Packit 84794d
              in += 1;
Packit 84794d
              continue;
Packit 84794d
            }
Packit 84794d
        }
Packit 84794d
Packit 84794d
      /* Scan to the next path piece */
Packit 84794d
      while (*in != 0 && *in != '/')
Packit 84794d
        *(++out) = *(in++);
Packit 84794d
Packit 84794d
      /* Add trailing /, compress the rest on the next go round. */
Packit 84794d
      if (*in == '/')
Packit 84794d
        *(++out) = *(in++);
Packit 84794d
    }
Packit 84794d
Packit 84794d
  /* Trim trailing / from path */
Packit 84794d
  if (out > bptr && *out == '/')
Packit 84794d
    *out = 0;
Packit 84794d
  else
Packit 84794d
    *(++out) = 0;
Packit 84794d
Packit 84794d
  return bptr;
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFile *
Packit 84794d
g_resource_file_new_for_path (const char *path)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource = g_object_new (G_TYPE_RESOURCE_FILE, NULL);
Packit 84794d
Packit 84794d
  resource->path = canonicalize_filename (path);
Packit 84794d
Packit 84794d
  return G_FILE (resource);
Packit 84794d
}
Packit 84794d
Packit 84794d
GFile *
Packit 84794d
_g_resource_file_new (const char *uri)
Packit 84794d
{
Packit 84794d
  GFile *resource;
Packit 84794d
  char *path;
Packit 84794d
Packit 84794d
  path = g_uri_unescape_string (uri + strlen ("resource:"), NULL);
Packit 84794d
  resource = g_resource_file_new_for_path (path);
Packit 84794d
  g_free (path);
Packit 84794d
Packit 84794d
  return G_FILE (resource);
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_is_native (GFile *file)
Packit 84794d
{
Packit 84794d
  return FALSE;
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_has_uri_scheme (GFile      *file,
Packit 84794d
				const char *uri_scheme)
Packit 84794d
{
Packit 84794d
  return g_ascii_strcasecmp (uri_scheme, "resource") == 0;
Packit 84794d
}
Packit 84794d
Packit 84794d
static char *
Packit 84794d
g_resource_file_get_uri_scheme (GFile *file)
Packit 84794d
{
Packit 84794d
  return g_strdup ("resource");
Packit 84794d
}
Packit 84794d
Packit 84794d
static char *
Packit 84794d
g_resource_file_get_basename (GFile *file)
Packit 84794d
{
Packit 84794d
  gchar *base;
Packit 84794d
Packit 84794d
  base = strrchr (G_RESOURCE_FILE (file)->path, '/');
Packit 84794d
  return g_strdup (base + 1);
Packit 84794d
}
Packit 84794d
Packit 84794d
static char *
Packit 84794d
g_resource_file_get_path (GFile *file)
Packit 84794d
{
Packit 84794d
  return NULL;
Packit 84794d
}
Packit 84794d
Packit 84794d
static char *
Packit 84794d
g_resource_file_get_uri (GFile *file)
Packit 84794d
{
Packit 84794d
  char *escaped, *res;
Packit 84794d
  escaped = g_uri_escape_string (G_RESOURCE_FILE (file)->path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
Packit 84794d
  res = g_strconcat ("resource://", escaped, NULL);
Packit 84794d
  g_free (escaped);
Packit 84794d
  return res;
Packit 84794d
}
Packit 84794d
Packit 84794d
static char *
Packit 84794d
g_resource_file_get_parse_name (GFile *file)
Packit 84794d
{
Packit 84794d
  return g_resource_file_get_uri (file);
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFile *
Packit 84794d
g_resource_file_get_parent (GFile *file)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource = G_RESOURCE_FILE (file);
Packit 84794d
  GResourceFile *parent;
Packit 84794d
  gchar *end;
Packit 84794d
Packit 84794d
  end = strrchr (resource->path, '/');
Packit 84794d
Packit 84794d
  if (end == G_RESOURCE_FILE (file)->path)
Packit 84794d
    return NULL;
Packit 84794d
Packit 84794d
  parent = g_object_new (G_TYPE_RESOURCE_FILE, NULL);
Packit 84794d
  parent->path = g_strndup (resource->path,
Packit 84794d
			    end - resource->path);
Packit 84794d
Packit 84794d
  return G_FILE (parent);
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFile *
Packit 84794d
g_resource_file_dup (GFile *file)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource = G_RESOURCE_FILE (file);
Packit 84794d
Packit 84794d
  return g_resource_file_new_for_path (resource->path);
Packit 84794d
}
Packit 84794d
Packit 84794d
static guint
Packit 84794d
g_resource_file_hash (GFile *file)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource = G_RESOURCE_FILE (file);
Packit 84794d
Packit 84794d
  return g_str_hash (resource->path);
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_equal (GFile *file1,
Packit 84794d
		       GFile *file2)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource1 = G_RESOURCE_FILE (file1);
Packit 84794d
  GResourceFile *resource2 = G_RESOURCE_FILE (file2);
Packit 84794d
Packit 84794d
  return g_str_equal (resource1->path, resource2->path);
Packit 84794d
}
Packit 84794d
Packit 84794d
static const char *
Packit 84794d
match_prefix (const char *path,
Packit 84794d
	      const char *prefix)
Packit 84794d
{
Packit 84794d
  int prefix_len;
Packit 84794d
Packit 84794d
  prefix_len = strlen (prefix);
Packit 84794d
  if (strncmp (path, prefix, prefix_len) != 0)
Packit 84794d
    return NULL;
Packit 84794d
Packit 84794d
  /* Handle the case where prefix is the root, so that
Packit 84794d
   * the IS_DIR_SEPRARATOR check below works */
Packit 84794d
  if (prefix_len > 0 &&
Packit 84794d
      prefix[prefix_len-1] == '/')
Packit 84794d
    prefix_len--;
Packit 84794d
Packit 84794d
  return path + prefix_len;
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_prefix_matches (GFile *parent,
Packit 84794d
				GFile *descendant)
Packit 84794d
{
Packit 84794d
  GResourceFile *parent_resource = G_RESOURCE_FILE (parent);
Packit 84794d
  GResourceFile *descendant_resource = G_RESOURCE_FILE (descendant);
Packit 84794d
  const char *remainder;
Packit 84794d
Packit 84794d
  remainder = match_prefix (descendant_resource->path, parent_resource->path);
Packit 84794d
  if (remainder != NULL && *remainder == '/')
Packit 84794d
    return TRUE;
Packit 84794d
  return FALSE;
Packit 84794d
}
Packit 84794d
Packit 84794d
static char *
Packit 84794d
g_resource_file_get_relative_path (GFile *parent,
Packit 84794d
				   GFile *descendant)
Packit 84794d
{
Packit 84794d
  GResourceFile *parent_resource = G_RESOURCE_FILE (parent);
Packit 84794d
  GResourceFile *descendant_resource = G_RESOURCE_FILE (descendant);
Packit 84794d
  const char *remainder;
Packit 84794d
Packit 84794d
  remainder = match_prefix (descendant_resource->path, parent_resource->path);
Packit 84794d
Packit 84794d
  if (remainder != NULL && *remainder == '/')
Packit 84794d
    return g_strdup (remainder + 1);
Packit 84794d
  return NULL;
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFile *
Packit 84794d
g_resource_file_resolve_relative_path (GFile      *file,
Packit 84794d
				       const char *relative_path)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource = G_RESOURCE_FILE (file);
Packit 84794d
  char *filename;
Packit 84794d
  GFile *child;
Packit 84794d
Packit 84794d
  if (relative_path[0] == '/')
Packit 84794d
    return g_resource_file_new_for_path (relative_path);
Packit 84794d
Packit 84794d
  filename = g_build_path ("/", resource->path, relative_path, NULL);
Packit 84794d
  child = g_resource_file_new_for_path (filename);
Packit 84794d
  g_free (filename);
Packit 84794d
Packit 84794d
  return child;
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileEnumerator *
Packit 84794d
g_resource_file_enumerate_children (GFile                *file,
Packit 84794d
				    const char           *attributes,
Packit 84794d
				    GFileQueryInfoFlags   flags,
Packit 84794d
				    GCancellable         *cancellable,
Packit 84794d
				    GError              **error)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource = G_RESOURCE_FILE (file);
Packit 84794d
  return _g_resource_file_enumerator_new (resource,
Packit 84794d
					  attributes, flags,
Packit 84794d
					  cancellable, error);
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFile *
Packit 84794d
g_resource_file_get_child_for_display_name (GFile        *file,
Packit 84794d
					    const char   *display_name,
Packit 84794d
					    GError      **error)
Packit 84794d
{
Packit 84794d
  GFile *new_file;
Packit 84794d
Packit 84794d
  new_file = g_file_get_child (file, display_name);
Packit 84794d
Packit 84794d
  return new_file;
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileInfo *
Packit 84794d
g_resource_file_query_info (GFile                *file,
Packit 84794d
			    const char           *attributes,
Packit 84794d
			    GFileQueryInfoFlags   flags,
Packit 84794d
			    GCancellable         *cancellable,
Packit 84794d
			    GError              **error)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource = G_RESOURCE_FILE (file);
Packit 84794d
  GError *my_error = NULL;
Packit 84794d
  GFileInfo *info;
Packit 84794d
  GFileAttributeMatcher *matcher;
Packit 84794d
  gboolean res;
Packit 84794d
  gsize size;
Packit 84794d
  guint32 resource_flags;
Packit 84794d
  char **children;
Packit 84794d
  gboolean is_dir;
Packit 84794d
  char *base;
Packit 84794d
Packit 84794d
  is_dir = FALSE;
Packit 84794d
  children = g_resources_enumerate_children (resource->path, 0, NULL);
Packit 84794d
  if (children != NULL)
Packit 84794d
    {
Packit 84794d
      g_strfreev (children);
Packit 84794d
      is_dir = TRUE;
Packit 84794d
    }
Packit 84794d
Packit 84794d
  /* root is always there */
Packit 84794d
  if (strcmp ("/", resource->path) == 0)
Packit 84794d
    is_dir = TRUE;
Packit 84794d
Packit 84794d
  if (!is_dir)
Packit 84794d
    {
Packit 84794d
      res = g_resources_get_info (resource->path, 0, &size, &resource_flags, &my_error);
Packit 84794d
      if (!res)
Packit 84794d
	{
Packit 84794d
	  if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
Packit 84794d
	    {
Packit 84794d
	      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
Packit 84794d
			   _("The resource at “%s” does not exist"),
Packit 84794d
			   resource->path);
Packit 84794d
	    }
Packit 84794d
	  else
Packit 84794d
	    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
Packit 84794d
                                 my_error->message);
Packit 84794d
	  g_clear_error (&my_error);
Packit 84794d
	  return FALSE;
Packit 84794d
	}
Packit 84794d
    }
Packit 84794d
Packit 84794d
  matcher = g_file_attribute_matcher_new (attributes);
Packit 84794d
Packit 84794d
  info = g_file_info_new ();
Packit 84794d
  base = g_resource_file_get_basename (file);
Packit 84794d
  g_file_info_set_name (info, base);
Packit 84794d
  g_file_info_set_display_name (info, base);
Packit 84794d
Packit 84794d
  _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ, TRUE);
Packit 84794d
  _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE, FALSE);
Packit 84794d
  _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE, FALSE);
Packit 84794d
  _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME, FALSE);
Packit 84794d
  _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE, FALSE);
Packit 84794d
  _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH, FALSE);
Packit 84794d
Packit 84794d
  if (is_dir)
Packit 84794d
    {
Packit 84794d
      g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
Packit 84794d
    }
Packit 84794d
  else
Packit 84794d
    {
Packit 84794d
      GBytes *bytes;
Packit 84794d
      char *content_type;
Packit 84794d
Packit 84794d
      g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
Packit 84794d
      g_file_info_set_size (info, size);
Packit 84794d
Packit 84794d
      if ((_g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE) ||
Packit 84794d
           ((~resource_flags & G_RESOURCE_FLAGS_COMPRESSED) && 
Packit 84794d
            _g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE))) &&
Packit 84794d
          (bytes = g_resources_lookup_data (resource->path, 0, NULL)))
Packit 84794d
        {
Packit 84794d
          const guchar *data;
Packit 84794d
          gsize data_size;
Packit 84794d
Packit 84794d
          data = g_bytes_get_data (bytes, &data_size);
Packit 84794d
          content_type = g_content_type_guess (base, data, data_size, NULL);
Packit 84794d
Packit 84794d
          g_bytes_unref (bytes);
Packit 84794d
        }
Packit 84794d
      else
Packit 84794d
        content_type = NULL;
Packit 84794d
Packit 84794d
      if (content_type)
Packit 84794d
        {
Packit 84794d
          _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE, content_type);
Packit 84794d
          _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE, content_type);
Packit 84794d
Packit 84794d
          g_free (content_type);
Packit 84794d
        }
Packit 84794d
    }
Packit 84794d
Packit 84794d
  g_free (base);
Packit 84794d
  g_file_attribute_matcher_unref (matcher);
Packit 84794d
Packit 84794d
  return info;
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileInfo *
Packit 84794d
g_resource_file_query_filesystem_info (GFile         *file,
Packit 84794d
                                       const char    *attributes,
Packit 84794d
                                       GCancellable  *cancellable,
Packit 84794d
                                       GError       **error)
Packit 84794d
{
Packit 84794d
  GFileInfo *info;
Packit 84794d
  GFileAttributeMatcher *matcher;
Packit 84794d
Packit 84794d
  info = g_file_info_new ();
Packit 84794d
Packit 84794d
  matcher = g_file_attribute_matcher_new (attributes);
Packit 84794d
  if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE))
Packit 84794d
    g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "resource");
Packit 84794d
Packit 84794d
  if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY))    g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
Packit 84794d
Packit 84794d
  g_file_attribute_matcher_unref (matcher);
Packit 84794d
Packit 84794d
  return info;
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileAttributeInfoList *
Packit 84794d
g_resource_file_query_settable_attributes (GFile         *file,
Packit 84794d
					   GCancellable  *cancellable,
Packit 84794d
					   GError       **error)
Packit 84794d
{
Packit 84794d
  return g_file_attribute_info_list_ref (resource_writable_attributes);
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileAttributeInfoList *
Packit 84794d
g_resource_file_query_writable_namespaces (GFile         *file,
Packit 84794d
					   GCancellable  *cancellable,
Packit 84794d
					   GError       **error)
Packit 84794d
{
Packit 84794d
  return g_file_attribute_info_list_ref (resource_writable_namespaces);
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileInputStream *
Packit 84794d
g_resource_file_read (GFile         *file,
Packit 84794d
		      GCancellable  *cancellable,
Packit 84794d
		      GError       **error)
Packit 84794d
{
Packit 84794d
  GResourceFile *resource = G_RESOURCE_FILE (file);
Packit 84794d
  GError *my_error = NULL;
Packit 84794d
  GInputStream *stream;
Packit 84794d
  GFileInputStream *res;
Packit 84794d
Packit 84794d
  stream = g_resources_open_stream (resource->path, 0, &my_error);
Packit 84794d
Packit 84794d
  if (stream == NULL)
Packit 84794d
    {
Packit 84794d
      if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
Packit 84794d
	{
Packit 84794d
	  g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
Packit 84794d
		       _("The resource at “%s” does not exist"),
Packit 84794d
		       resource->path);
Packit 84794d
	}
Packit 84794d
      else
Packit 84794d
	g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
Packit 84794d
                             my_error->message);
Packit 84794d
      g_clear_error (&my_error);
Packit 84794d
      return NULL;
Packit 84794d
    }
Packit 84794d
Packit 84794d
  res = _g_resource_file_input_stream_new (stream, file);
Packit 84794d
  g_object_unref (stream);
Packit 84794d
  return res;
Packit 84794d
}
Packit 84794d
Packit 84794d
typedef GFileMonitor GResourceFileMonitor;
Packit 84794d
typedef GFileMonitorClass GResourceFileMonitorClass;
Packit 84794d
Packit 84794d
GType g_resource_file_monitor_get_type (void);
Packit 84794d
Packit 84794d
G_DEFINE_TYPE (GResourceFileMonitor, g_resource_file_monitor, G_TYPE_FILE_MONITOR)
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_monitor_cancel (GFileMonitor *monitor)
Packit 84794d
{
Packit 84794d
  return TRUE;
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_monitor_init (GResourceFileMonitor *monitor)
Packit 84794d
{
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_monitor_class_init (GResourceFileMonitorClass *class)
Packit 84794d
{
Packit 84794d
  class->cancel = g_resource_file_monitor_cancel;
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileMonitor *
Packit 84794d
g_resource_file_monitor_file (GFile              *file,
Packit 84794d
                              GFileMonitorFlags   flags,
Packit 84794d
                              GCancellable       *cancellable,
Packit 84794d
                              GError            **error)
Packit 84794d
{
Packit 84794d
  return g_object_new (g_resource_file_monitor_get_type (), NULL);
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_file_iface_init (GFileIface *iface)
Packit 84794d
{
Packit 84794d
  iface->dup = g_resource_file_dup;
Packit 84794d
  iface->hash = g_resource_file_hash;
Packit 84794d
  iface->equal = g_resource_file_equal;
Packit 84794d
  iface->is_native = g_resource_file_is_native;
Packit 84794d
  iface->has_uri_scheme = g_resource_file_has_uri_scheme;
Packit 84794d
  iface->get_uri_scheme = g_resource_file_get_uri_scheme;
Packit 84794d
  iface->get_basename = g_resource_file_get_basename;
Packit 84794d
  iface->get_path = g_resource_file_get_path;
Packit 84794d
  iface->get_uri = g_resource_file_get_uri;
Packit 84794d
  iface->get_parse_name = g_resource_file_get_parse_name;
Packit 84794d
  iface->get_parent = g_resource_file_get_parent;
Packit 84794d
  iface->prefix_matches = g_resource_file_prefix_matches;
Packit 84794d
  iface->get_relative_path = g_resource_file_get_relative_path;
Packit 84794d
  iface->resolve_relative_path = g_resource_file_resolve_relative_path;
Packit 84794d
  iface->get_child_for_display_name = g_resource_file_get_child_for_display_name;
Packit 84794d
  iface->enumerate_children = g_resource_file_enumerate_children;
Packit 84794d
  iface->query_info = g_resource_file_query_info;
Packit 84794d
  iface->query_filesystem_info = g_resource_file_query_filesystem_info;
Packit 84794d
  iface->query_settable_attributes = g_resource_file_query_settable_attributes;
Packit 84794d
  iface->query_writable_namespaces = g_resource_file_query_writable_namespaces;
Packit 84794d
  iface->read_fn = g_resource_file_read;
Packit 84794d
  iface->monitor_file = g_resource_file_monitor_file;
Packit 84794d
Packit 84794d
  iface->supports_thread_contexts = TRUE;
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileInfo *g_resource_file_enumerator_next_file (GFileEnumerator  *enumerator,
Packit 84794d
							GCancellable     *cancellable,
Packit 84794d
							GError          **error);
Packit 84794d
static gboolean   g_resource_file_enumerator_close     (GFileEnumerator  *enumerator,
Packit 84794d
							GCancellable     *cancellable,
Packit 84794d
							GError          **error);
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_enumerator_finalize (GObject *object)
Packit 84794d
{
Packit 84794d
  GResourceFileEnumerator *resource;
Packit 84794d
Packit 84794d
  resource = G_RESOURCE_FILE_ENUMERATOR (object);
Packit 84794d
Packit 84794d
  g_strfreev (resource->children);
Packit 84794d
  g_free (resource->path);
Packit 84794d
  g_free (resource->attributes);
Packit 84794d
Packit 84794d
  G_OBJECT_CLASS (g_resource_file_enumerator_parent_class)->finalize (object);
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_enumerator_class_init (GResourceFileEnumeratorClass *klass)
Packit 84794d
{
Packit 84794d
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit 84794d
  GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
Packit 84794d
Packit 84794d
  gobject_class->finalize = g_resource_file_enumerator_finalize;
Packit 84794d
Packit 84794d
  enumerator_class->next_file = g_resource_file_enumerator_next_file;
Packit 84794d
  enumerator_class->close_fn = g_resource_file_enumerator_close;
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_enumerator_init (GResourceFileEnumerator *resource)
Packit 84794d
{
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileEnumerator *
Packit 84794d
_g_resource_file_enumerator_new (GResourceFile *file,
Packit 84794d
				 const char           *attributes,
Packit 84794d
				 GFileQueryInfoFlags   flags,
Packit 84794d
				 GCancellable         *cancellable,
Packit 84794d
				 GError              **error)
Packit 84794d
{
Packit 84794d
  GResourceFileEnumerator *resource;
Packit 84794d
  char **children;
Packit 84794d
  gboolean res;
Packit 84794d
Packit 84794d
  children = g_resources_enumerate_children (file->path, 0, NULL);
Packit 84794d
  if (children == NULL &&
Packit 84794d
      strcmp ("/", file->path) != 0)
Packit 84794d
    {
Packit 84794d
      res = g_resources_get_info (file->path, 0, NULL, NULL, NULL);
Packit 84794d
      if (res)
Packit 84794d
	g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
Packit 84794d
		     _("The resource at “%s” is not a directory"),
Packit 84794d
		     file->path);
Packit 84794d
      else
Packit 84794d
	g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
Packit 84794d
		     _("The resource at “%s” does not exist"),
Packit 84794d
		     file->path);
Packit 84794d
      return NULL;
Packit 84794d
    }
Packit 84794d
Packit 84794d
  resource = g_object_new (G_TYPE_RESOURCE_FILE_ENUMERATOR,
Packit 84794d
			   "container", file,
Packit 84794d
			   NULL);
Packit 84794d
Packit 84794d
  resource->children = children;
Packit 84794d
  resource->path = g_strdup (file->path);
Packit 84794d
  resource->attributes = g_strdup (attributes);
Packit 84794d
  resource->flags = flags;
Packit 84794d
Packit 84794d
  return G_FILE_ENUMERATOR (resource);
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileInfo *
Packit 84794d
g_resource_file_enumerator_next_file (GFileEnumerator  *enumerator,
Packit 84794d
				      GCancellable     *cancellable,
Packit 84794d
				      GError          **error)
Packit 84794d
{
Packit 84794d
  GResourceFileEnumerator *resource = G_RESOURCE_FILE_ENUMERATOR (enumerator);
Packit 84794d
  char *path;
Packit 84794d
  GFileInfo *info;
Packit 84794d
  GFile *file;
Packit 84794d
Packit 84794d
  if (resource->children == NULL ||
Packit 84794d
      resource->children[resource->index] == NULL)
Packit 84794d
    return NULL;
Packit 84794d
Packit 84794d
  path = g_build_path ("/", resource->path, resource->children[resource->index++], NULL);
Packit 84794d
  file = g_resource_file_new_for_path (path);
Packit 84794d
  g_free (path);
Packit 84794d
Packit 84794d
  info = g_file_query_info (file,
Packit 84794d
			    resource->attributes,
Packit 84794d
			    resource->flags,
Packit 84794d
			    cancellable,
Packit 84794d
			    error);
Packit 84794d
Packit 84794d
  g_object_unref (file);
Packit 84794d
Packit 84794d
  return info;
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_enumerator_close (GFileEnumerator  *enumerator,
Packit 84794d
			       GCancellable     *cancellable,
Packit 84794d
			       GError          **error)
Packit 84794d
{
Packit 84794d
  return TRUE;
Packit 84794d
}
Packit 84794d
Packit 84794d
Packit 84794d
struct _GResourceFileInputStream
Packit 84794d
{
Packit 84794d
  GFileInputStream parent_instance;
Packit 84794d
  GInputStream *stream;
Packit 84794d
  GFile *file;
Packit 84794d
};
Packit 84794d
Packit 84794d
struct _GResourceFileInputStreamClass
Packit 84794d
{
Packit 84794d
  GFileInputStreamClass parent_class;
Packit 84794d
};
Packit 84794d
Packit 84794d
#define g_resource_file_input_stream_get_type _g_resource_file_input_stream_get_type
Packit 84794d
G_DEFINE_TYPE (GResourceFileInputStream, g_resource_file_input_stream, G_TYPE_FILE_INPUT_STREAM)
Packit 84794d
Packit 84794d
static gssize     g_resource_file_input_stream_read       (GInputStream      *stream,
Packit 84794d
							   void              *buffer,
Packit 84794d
							   gsize              count,
Packit 84794d
							   GCancellable      *cancellable,
Packit 84794d
							   GError           **error);
Packit 84794d
static gssize     g_resource_file_input_stream_skip       (GInputStream      *stream,
Packit 84794d
							   gsize              count,
Packit 84794d
							   GCancellable      *cancellable,
Packit 84794d
							   GError           **error);
Packit 84794d
static gboolean   g_resource_file_input_stream_close      (GInputStream      *stream,
Packit 84794d
							   GCancellable      *cancellable,
Packit 84794d
							   GError           **error);
Packit 84794d
static goffset    g_resource_file_input_stream_tell       (GFileInputStream  *stream);
Packit 84794d
static gboolean   g_resource_file_input_stream_can_seek   (GFileInputStream  *stream);
Packit 84794d
static gboolean   g_resource_file_input_stream_seek       (GFileInputStream  *stream,
Packit 84794d
							   goffset            offset,
Packit 84794d
							   GSeekType          type,
Packit 84794d
							   GCancellable      *cancellable,
Packit 84794d
							   GError           **error);
Packit 84794d
static GFileInfo *g_resource_file_input_stream_query_info (GFileInputStream  *stream,
Packit 84794d
							   const char        *attributes,
Packit 84794d
							   GCancellable      *cancellable,
Packit 84794d
							   GError           **error);
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_input_stream_finalize (GObject *object)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (object);
Packit 84794d
Packit 84794d
  g_object_unref (file->stream);
Packit 84794d
  g_object_unref (file->file);
Packit 84794d
  G_OBJECT_CLASS (g_resource_file_input_stream_parent_class)->finalize (object);
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_input_stream_class_init (GResourceFileInputStreamClass *klass)
Packit 84794d
{
Packit 84794d
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit 84794d
  GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
Packit 84794d
  GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
Packit 84794d
Packit 84794d
  gobject_class->finalize = g_resource_file_input_stream_finalize;
Packit 84794d
Packit 84794d
  stream_class->read_fn = g_resource_file_input_stream_read;
Packit 84794d
  stream_class->skip = g_resource_file_input_stream_skip;
Packit 84794d
  stream_class->close_fn = g_resource_file_input_stream_close;
Packit 84794d
  file_stream_class->tell = g_resource_file_input_stream_tell;
Packit 84794d
  file_stream_class->can_seek = g_resource_file_input_stream_can_seek;
Packit 84794d
  file_stream_class->seek = g_resource_file_input_stream_seek;
Packit 84794d
  file_stream_class->query_info = g_resource_file_input_stream_query_info;
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
g_resource_file_input_stream_init (GResourceFileInputStream *info)
Packit 84794d
{
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileInputStream *
Packit 84794d
_g_resource_file_input_stream_new (GInputStream *in_stream, GFile *file)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *stream;
Packit 84794d
Packit 84794d
  stream = g_object_new (G_TYPE_RESOURCE_FILE_INPUT_STREAM, NULL);
Packit 84794d
  stream->stream = g_object_ref (in_stream);
Packit 84794d
  stream->file = g_object_ref (file);
Packit 84794d
Packit 84794d
  return G_FILE_INPUT_STREAM (stream);
Packit 84794d
}
Packit 84794d
Packit 84794d
static gssize
Packit 84794d
g_resource_file_input_stream_read (GInputStream  *stream,
Packit 84794d
				   void          *buffer,
Packit 84794d
				   gsize          count,
Packit 84794d
				   GCancellable  *cancellable,
Packit 84794d
				   GError       **error)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
Packit 84794d
  return g_input_stream_read (file->stream,
Packit 84794d
			      buffer, count, cancellable, error);
Packit 84794d
}
Packit 84794d
Packit 84794d
static gssize
Packit 84794d
g_resource_file_input_stream_skip (GInputStream  *stream,
Packit 84794d
				   gsize          count,
Packit 84794d
				   GCancellable  *cancellable,
Packit 84794d
				   GError       **error)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
Packit 84794d
  return g_input_stream_skip (file->stream,
Packit 84794d
			      count, cancellable, error);
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_input_stream_close (GInputStream  *stream,
Packit 84794d
				    GCancellable  *cancellable,
Packit 84794d
				    GError       **error)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
Packit 84794d
  return g_input_stream_close (file->stream,
Packit 84794d
			       cancellable, error);
Packit 84794d
}
Packit 84794d
Packit 84794d
Packit 84794d
static goffset
Packit 84794d
g_resource_file_input_stream_tell (GFileInputStream *stream)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
Packit 84794d
Packit 84794d
  if (!G_IS_SEEKABLE (file->stream))
Packit 84794d
      return 0;
Packit 84794d
Packit 84794d
  return g_seekable_tell (G_SEEKABLE (file->stream));
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_input_stream_can_seek (GFileInputStream *stream)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
Packit 84794d
Packit 84794d
  return G_IS_SEEKABLE (file->stream) && g_seekable_can_seek (G_SEEKABLE (file->stream));
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
g_resource_file_input_stream_seek (GFileInputStream  *stream,
Packit 84794d
				   goffset            offset,
Packit 84794d
				   GSeekType          type,
Packit 84794d
				   GCancellable      *cancellable,
Packit 84794d
				   GError           **error)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
Packit 84794d
Packit 84794d
  if (!G_IS_SEEKABLE (file->stream))
Packit 84794d
    {
Packit 84794d
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
Packit 84794d
			   _("Input stream doesn’t implement seek"));
Packit 84794d
      return FALSE;
Packit 84794d
    }
Packit 84794d
Packit 84794d
  return g_seekable_seek (G_SEEKABLE (file->stream),
Packit 84794d
			  offset, type, cancellable, error);
Packit 84794d
}
Packit 84794d
Packit 84794d
static GFileInfo *
Packit 84794d
g_resource_file_input_stream_query_info (GFileInputStream  *stream,
Packit 84794d
					 const char        *attributes,
Packit 84794d
					 GCancellable      *cancellable,
Packit 84794d
					 GError           **error)
Packit 84794d
{
Packit 84794d
  GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
Packit 84794d
Packit 84794d
  return g_file_query_info (file->file, attributes, 0, cancellable, error);
Packit 84794d
}