LCOV - code coverage report
Current view: top level - gio - gresourcefile.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 86.8 % 348 302
Test Date: 2024-11-26 05:23:01 Functions: 86.4 % 66 57
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* GIO - GLib Input, Output and Streaming Library
       2                 :             :  *
       3                 :             :  * Copyright (C) 2006-2007 Red Hat, Inc.
       4                 :             :  *
       5                 :             :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :             :  *
       7                 :             :  * This library is free software; you can redistribute it and/or
       8                 :             :  * modify it under the terms of the GNU Lesser General Public
       9                 :             :  * License as published by the Free Software Foundation; either
      10                 :             :  * version 2.1 of the License, or (at your option) any later version.
      11                 :             :  *
      12                 :             :  * This library is distributed in the hope that it will be useful,
      13                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :             :  * Lesser General Public License for more details.
      16                 :             :  *
      17                 :             :  * You should have received a copy of the GNU Lesser General
      18                 :             :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19                 :             :  *
      20                 :             :  * Author: Alexander Larsson <alexl@redhat.com>
      21                 :             :  */
      22                 :             : 
      23                 :             : #include "config.h"
      24                 :             : 
      25                 :             : #include <string.h>
      26                 :             : 
      27                 :             : #include "gresource.h"
      28                 :             : #include "gresourcefile.h"
      29                 :             : #include "gfileattribute.h"
      30                 :             : #include <gfileattribute-priv.h>
      31                 :             : #include <gfileinfo-priv.h>
      32                 :             : #include "gfile.h"
      33                 :             : #include "gfilemonitor.h"
      34                 :             : #include "gseekable.h"
      35                 :             : #include "gfileinputstream.h"
      36                 :             : #include "gfileinfo.h"
      37                 :             : #include "gfileenumerator.h"
      38                 :             : #include "gcontenttype.h"
      39                 :             : #include "gioerror.h"
      40                 :             : #include <glib/gstdio.h>
      41                 :             : #include "glibintl.h"
      42                 :             : 
      43                 :             : struct _GResourceFile
      44                 :             : {
      45                 :             :   GObject parent_instance;
      46                 :             : 
      47                 :             :   char *path;
      48                 :             : };
      49                 :             : 
      50                 :             : struct _GResourceFileEnumerator
      51                 :             : {
      52                 :             :   GFileEnumerator parent;
      53                 :             : 
      54                 :             :   GFileAttributeMatcher *matcher;
      55                 :             :   char *path;
      56                 :             :   char *attributes;
      57                 :             :   GFileQueryInfoFlags flags;
      58                 :             :   int index;
      59                 :             : 
      60                 :             :   char **children;
      61                 :             : };
      62                 :             : 
      63                 :             : struct _GResourceFileEnumeratorClass
      64                 :             : {
      65                 :             :   GFileEnumeratorClass parent_class;
      66                 :             : };
      67                 :             : 
      68                 :             : typedef struct _GResourceFileEnumerator        GResourceFileEnumerator;
      69                 :             : typedef struct _GResourceFileEnumeratorClass   GResourceFileEnumeratorClass;
      70                 :             : 
      71                 :             : static void g_resource_file_file_iface_init (GFileIface *iface);
      72                 :             : 
      73                 :             : static GFileAttributeInfoList *resource_writable_attributes = NULL;
      74                 :             : static GFileAttributeInfoList *resource_writable_namespaces = NULL;
      75                 :             : 
      76                 :             : static GType _g_resource_file_enumerator_get_type (void);
      77                 :             : 
      78                 :             : #define G_TYPE_RESOURCE_FILE_ENUMERATOR         (_g_resource_file_enumerator_get_type ())
      79                 :             : #define G_RESOURCE_FILE_ENUMERATOR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumerator))
      80                 :             : #define G_RESOURCE_FILE_ENUMERATOR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
      81                 :             : #define G_IS_RESOURCE_FILE_ENUMERATOR(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR))
      82                 :             : #define G_IS_RESOURCE_FILE_ENUMERATOR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_ENUMERATOR))
      83                 :             : #define G_RESOURCE_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
      84                 :             : 
      85                 :             : #define G_TYPE_RESOURCE_FILE_INPUT_STREAM         (_g_resource_file_input_stream_get_type ())
      86                 :             : #define G_RESOURCE_FILE_INPUT_STREAM(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStream))
      87                 :             : #define G_RESOURCE_FILE_INPUT_STREAM_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
      88                 :             : #define G_IS_RESOURCE_FILE_INPUT_STREAM(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
      89                 :             : #define G_IS_RESOURCE_FILE_INPUT_STREAM_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
      90                 :             : #define G_RESOURCE_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
      91                 :             : 
      92                 :             : typedef struct _GResourceFileInputStream         GResourceFileInputStream;
      93                 :             : typedef struct _GResourceFileInputStreamClass    GResourceFileInputStreamClass;
      94                 :             : 
      95                 :             : #define g_resource_file_get_type _g_resource_file_get_type
      96                 :          90 : G_DEFINE_TYPE_WITH_CODE (GResourceFile, g_resource_file, G_TYPE_OBJECT,
      97                 :             :                          G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
      98                 :             :                                                 g_resource_file_file_iface_init))
      99                 :             : 
     100                 :             : #define g_resource_file_enumerator_get_type _g_resource_file_enumerator_get_type
     101                 :           7 : G_DEFINE_TYPE (GResourceFileEnumerator, g_resource_file_enumerator, G_TYPE_FILE_ENUMERATOR)
     102                 :             : 
     103                 :             : static GFileEnumerator *_g_resource_file_enumerator_new (GResourceFile *file,
     104                 :             :                                                          const char           *attributes,
     105                 :             :                                                          GFileQueryInfoFlags   flags,
     106                 :             :                                                          GCancellable         *cancellable,
     107                 :             :                                                          GError              **error);
     108                 :             : 
     109                 :             : 
     110                 :             : static GType              _g_resource_file_input_stream_get_type (void) G_GNUC_CONST;
     111                 :             : 
     112                 :             : static GFileInputStream *_g_resource_file_input_stream_new (GInputStream *stream, GFile *file);
     113                 :             : 
     114                 :             : 
     115                 :             : static void
     116                 :          23 : g_resource_file_finalize (GObject *object)
     117                 :             : {
     118                 :             :   GResourceFile *resource;
     119                 :             : 
     120                 :          23 :   resource = G_RESOURCE_FILE (object);
     121                 :             : 
     122                 :          23 :   g_free (resource->path);
     123                 :             : 
     124                 :          23 :   G_OBJECT_CLASS (g_resource_file_parent_class)->finalize (object);
     125                 :          23 : }
     126                 :             : 
     127                 :             : static void
     128                 :           1 : g_resource_file_class_init (GResourceFileClass *klass)
     129                 :             : {
     130                 :           1 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     131                 :             : 
     132                 :           1 :   gobject_class->finalize = g_resource_file_finalize;
     133                 :             : 
     134                 :           1 :   resource_writable_attributes = g_file_attribute_info_list_new ();
     135                 :           1 :   resource_writable_namespaces = g_file_attribute_info_list_new ();
     136                 :           1 : }
     137                 :             : 
     138                 :             : static void
     139                 :          23 : g_resource_file_init (GResourceFile *resource)
     140                 :             : {
     141                 :          23 : }
     142                 :             : 
     143                 :             : static inline gchar *
     144                 :           4 : scan_backwards (const gchar *begin,
     145                 :             :                 const gchar *end,
     146                 :             :                 gchar        c)
     147                 :             : {
     148                 :          15 :   while (end >= begin)
     149                 :             :     {
     150                 :          15 :       if (*end == c)
     151                 :           4 :         return (gchar *)end;
     152                 :          11 :       end--;
     153                 :             :     }
     154                 :             : 
     155                 :           0 :   return NULL;
     156                 :             : }
     157                 :             : 
     158                 :             : static inline void
     159                 :          12 : pop_to_previous_part (const gchar  *begin,
     160                 :             :                       gchar       **out)
     161                 :             : {
     162                 :          12 :   if (*out > begin)
     163                 :           4 :     *out = scan_backwards (begin, *out - 1, '/');
     164                 :          12 : }
     165                 :             : 
     166                 :             : /*
     167                 :             :  * canonicalize_filename:
     168                 :             :  * @in: the path to be canonicalized
     169                 :             :  *
     170                 :             :  * The path @in may contain non-canonical path pieces such as "../"
     171                 :             :  * or duplicated "/". This will resolve those into a form that only
     172                 :             :  * contains a single / at a time and resolves all "../". The resulting
     173                 :             :  * path must also start with a /.
     174                 :             :  *
     175                 :             :  * Returns: the canonical form of the path
     176                 :             :  */
     177                 :             : static char *
     178                 :          22 : canonicalize_filename (const char *in)
     179                 :             : {
     180                 :             :   gchar *bptr;
     181                 :             :   char *out;
     182                 :             : 
     183                 :          22 :   bptr = out = g_malloc (strlen (in) + 2);
     184                 :          22 :   *out = '/';
     185                 :             : 
     186                 :          91 :   while (*in != 0)
     187                 :             :     {
     188                 :          69 :       g_assert (*out == '/');
     189                 :             : 
     190                 :             :       /* move past slashes */
     191                 :         143 :       while (*in == '/')
     192                 :          74 :         in++;
     193                 :             : 
     194                 :             :       /* Handle ./ ../ .\0 ..\0 */
     195                 :          69 :       if (*in == '.')
     196                 :             :         {
     197                 :             :           /* If this is ../ or ..\0 move up */
     198                 :          22 :           if (in[1] == '.' && (in[2] == '/' || in[2] == 0))
     199                 :             :             {
     200                 :          12 :               pop_to_previous_part (bptr, &out);
     201                 :          12 :               in += 2;
     202                 :          12 :               continue;
     203                 :             :             }
     204                 :             : 
     205                 :             :           /* If this is ./ skip past it */
     206                 :          10 :           if (in[1] == '/' || in[1] == 0)
     207                 :             :             {
     208                 :           9 :               in += 1;
     209                 :           9 :               continue;
     210                 :             :             }
     211                 :             :         }
     212                 :             : 
     213                 :             :       /* Scan to the next path piece */
     214                 :         252 :       while (*in != 0 && *in != '/')
     215                 :         204 :         *(++out) = *(in++);
     216                 :             : 
     217                 :             :       /* Add trailing /, compress the rest on the next go round. */
     218                 :          48 :       if (*in == '/')
     219                 :          29 :         *(++out) = *(in++);
     220                 :             :     }
     221                 :             : 
     222                 :             :   /* Trim trailing / from path */
     223                 :          22 :   if (out > bptr && *out == '/')
     224                 :           4 :     *out = 0;
     225                 :             :   else
     226                 :          18 :     *(++out) = 0;
     227                 :             : 
     228                 :          22 :   return bptr;
     229                 :             : }
     230                 :             : 
     231                 :             : static GFile *
     232                 :          22 : g_resource_file_new_for_path (const char *path)
     233                 :             : {
     234                 :          22 :   GResourceFile *resource = g_object_new (G_TYPE_RESOURCE_FILE, NULL);
     235                 :             : 
     236                 :          22 :   resource->path = canonicalize_filename (path);
     237                 :             : 
     238                 :          22 :   return G_FILE (resource);
     239                 :             : }
     240                 :             : 
     241                 :             : /* Will return %NULL if @uri is malformed */
     242                 :             : GFile *
     243                 :          19 : _g_resource_file_new (const char *uri)
     244                 :             : {
     245                 :             :   GFile *resource;
     246                 :             :   char *path;
     247                 :             : 
     248                 :          19 :   path = g_uri_unescape_string (uri + strlen ("resource:"), NULL);
     249                 :          19 :   if (path == NULL)
     250                 :           1 :     return NULL;
     251                 :             : 
     252                 :          18 :   resource = g_resource_file_new_for_path (path);
     253                 :          18 :   g_free (path);
     254                 :             : 
     255                 :          18 :   return G_FILE (resource);
     256                 :             : }
     257                 :             : 
     258                 :             : static gboolean
     259                 :           1 : g_resource_file_is_native (GFile *file)
     260                 :             : {
     261                 :           1 :   return FALSE;
     262                 :             : }
     263                 :             : 
     264                 :             : static gboolean
     265                 :           2 : g_resource_file_has_uri_scheme (GFile      *file,
     266                 :             :                                 const char *uri_scheme)
     267                 :             : {
     268                 :           2 :   return g_ascii_strcasecmp (uri_scheme, "resource") == 0;
     269                 :             : }
     270                 :             : 
     271                 :             : static char *
     272                 :           1 : g_resource_file_get_uri_scheme (GFile *file)
     273                 :             : {
     274                 :           1 :   return g_strdup ("resource");
     275                 :             : }
     276                 :             : 
     277                 :             : static char *
     278                 :           4 : g_resource_file_get_basename (GFile *file)
     279                 :             : {
     280                 :             :   gchar *base;
     281                 :             : 
     282                 :           4 :   base = strrchr (G_RESOURCE_FILE (file)->path, '/');
     283                 :           8 :   return g_strdup (base + 1);
     284                 :             : }
     285                 :             : 
     286                 :             : static char *
     287                 :           1 : g_resource_file_get_path (GFile *file)
     288                 :             : {
     289                 :           1 :   return NULL;
     290                 :             : }
     291                 :             : 
     292                 :             : static char *
     293                 :          17 : g_resource_file_get_uri (GFile *file)
     294                 :             : {
     295                 :             :   char *escaped, *res;
     296                 :          17 :   escaped = g_uri_escape_string (G_RESOURCE_FILE (file)->path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
     297                 :          17 :   res = g_strconcat ("resource://", escaped, NULL);
     298                 :          17 :   g_free (escaped);
     299                 :          17 :   return res;
     300                 :             : }
     301                 :             : 
     302                 :             : static char *
     303                 :           1 : g_resource_file_get_parse_name (GFile *file)
     304                 :             : {
     305                 :           1 :   return g_resource_file_get_uri (file);
     306                 :             : }
     307                 :             : 
     308                 :             : static GFile *
     309                 :           1 : g_resource_file_get_parent (GFile *file)
     310                 :             : {
     311                 :           1 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     312                 :             :   GResourceFile *parent;
     313                 :             :   gchar *end;
     314                 :             : 
     315                 :           1 :   end = strrchr (resource->path, '/');
     316                 :             : 
     317                 :           1 :   if (end == G_RESOURCE_FILE (file)->path)
     318                 :           0 :     return NULL;
     319                 :             : 
     320                 :           1 :   parent = g_object_new (G_TYPE_RESOURCE_FILE, NULL);
     321                 :           2 :   parent->path = g_strndup (resource->path,
     322                 :           1 :                             end - resource->path);
     323                 :             : 
     324                 :           1 :   return G_FILE (parent);
     325                 :             : }
     326                 :             : 
     327                 :             : static GFile *
     328                 :           1 : g_resource_file_dup (GFile *file)
     329                 :             : {
     330                 :           1 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     331                 :             : 
     332                 :           1 :   return g_resource_file_new_for_path (resource->path);
     333                 :             : }
     334                 :             : 
     335                 :             : static guint
     336                 :           1 : g_resource_file_hash (GFile *file)
     337                 :             : {
     338                 :           1 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     339                 :             : 
     340                 :           1 :   return g_str_hash (resource->path);
     341                 :             : }
     342                 :             : 
     343                 :             : static gboolean
     344                 :           3 : g_resource_file_equal (GFile *file1,
     345                 :             :                        GFile *file2)
     346                 :             : {
     347                 :           3 :   GResourceFile *resource1 = G_RESOURCE_FILE (file1);
     348                 :           3 :   GResourceFile *resource2 = G_RESOURCE_FILE (file2);
     349                 :             : 
     350                 :           3 :   return g_str_equal (resource1->path, resource2->path);
     351                 :             : }
     352                 :             : 
     353                 :             : static const char *
     354                 :           2 : match_prefix (const char *path,
     355                 :             :               const char *prefix)
     356                 :             : {
     357                 :             :   size_t prefix_len;
     358                 :             : 
     359                 :           2 :   prefix_len = strlen (prefix);
     360                 :           2 :   if (strncmp (path, prefix, prefix_len) != 0)
     361                 :           0 :     return NULL;
     362                 :             : 
     363                 :             :   /* Handle the case where prefix is the root, so that
     364                 :             :    * the IS_DIR_SEPRARATOR check below works */
     365                 :           2 :   if (prefix_len > 0 &&
     366                 :           2 :       prefix[prefix_len-1] == '/')
     367                 :           0 :     prefix_len--;
     368                 :             : 
     369                 :           2 :   return path + prefix_len;
     370                 :             : }
     371                 :             : 
     372                 :             : static gboolean
     373                 :           1 : g_resource_file_prefix_matches (GFile *parent,
     374                 :             :                                 GFile *descendant)
     375                 :             : {
     376                 :           1 :   GResourceFile *parent_resource = G_RESOURCE_FILE (parent);
     377                 :           1 :   GResourceFile *descendant_resource = G_RESOURCE_FILE (descendant);
     378                 :             :   const char *remainder;
     379                 :             : 
     380                 :           1 :   remainder = match_prefix (descendant_resource->path, parent_resource->path);
     381                 :           1 :   if (remainder != NULL && *remainder == '/')
     382                 :           1 :     return TRUE;
     383                 :           0 :   return FALSE;
     384                 :             : }
     385                 :             : 
     386                 :             : static char *
     387                 :           1 : g_resource_file_get_relative_path (GFile *parent,
     388                 :             :                                    GFile *descendant)
     389                 :             : {
     390                 :           1 :   GResourceFile *parent_resource = G_RESOURCE_FILE (parent);
     391                 :           1 :   GResourceFile *descendant_resource = G_RESOURCE_FILE (descendant);
     392                 :             :   const char *remainder;
     393                 :             : 
     394                 :           1 :   remainder = match_prefix (descendant_resource->path, parent_resource->path);
     395                 :             : 
     396                 :           1 :   if (remainder != NULL && *remainder == '/')
     397                 :           2 :     return g_strdup (remainder + 1);
     398                 :           0 :   return NULL;
     399                 :             : }
     400                 :             : 
     401                 :             : static GFile *
     402                 :           1 : g_resource_file_resolve_relative_path (GFile      *file,
     403                 :             :                                        const char *relative_path)
     404                 :             : {
     405                 :           1 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     406                 :             :   char *filename;
     407                 :             :   GFile *child;
     408                 :             : 
     409                 :           1 :   if (relative_path[0] == '/')
     410                 :           0 :     return g_resource_file_new_for_path (relative_path);
     411                 :             : 
     412                 :           1 :   filename = g_build_path ("/", resource->path, relative_path, NULL);
     413                 :           1 :   child = g_resource_file_new_for_path (filename);
     414                 :           1 :   g_free (filename);
     415                 :             : 
     416                 :           1 :   return child;
     417                 :             : }
     418                 :             : 
     419                 :             : static GFileEnumerator *
     420                 :           1 : g_resource_file_enumerate_children (GFile                *file,
     421                 :             :                                     const char           *attributes,
     422                 :             :                                     GFileQueryInfoFlags   flags,
     423                 :             :                                     GCancellable         *cancellable,
     424                 :             :                                     GError              **error)
     425                 :             : {
     426                 :           1 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     427                 :           1 :   return _g_resource_file_enumerator_new (resource,
     428                 :             :                                           attributes, flags,
     429                 :             :                                           cancellable, error);
     430                 :             : }
     431                 :             : 
     432                 :             : static GFile *
     433                 :           1 : g_resource_file_get_child_for_display_name (GFile        *file,
     434                 :             :                                             const char   *display_name,
     435                 :             :                                             GError      **error)
     436                 :             : {
     437                 :             :   GFile *new_file;
     438                 :             : 
     439                 :           1 :   new_file = g_file_get_child (file, display_name);
     440                 :             : 
     441                 :           1 :   return new_file;
     442                 :             : }
     443                 :             : 
     444                 :             : static GFileInfo *
     445                 :           4 : g_resource_file_query_info (GFile                *file,
     446                 :             :                             const char           *attributes,
     447                 :             :                             GFileQueryInfoFlags   flags,
     448                 :             :                             GCancellable         *cancellable,
     449                 :             :                             GError              **error)
     450                 :             : {
     451                 :           4 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     452                 :           4 :   GError *my_error = NULL;
     453                 :             :   GFileInfo *info;
     454                 :             :   GFileAttributeMatcher *matcher;
     455                 :             :   gboolean res;
     456                 :           4 :   gsize size = 0;
     457                 :           4 :   guint32 resource_flags = 0;
     458                 :             :   gboolean is_dir;
     459                 :             :   char *base;
     460                 :             : 
     461                 :             :   /* root is always there */
     462                 :           4 :   if (strcmp ("/", resource->path) == 0)
     463                 :           0 :     is_dir = TRUE;
     464                 :             :   else
     465                 :           4 :     is_dir = g_resources_has_children (resource->path);
     466                 :             : 
     467                 :           4 :   if (!is_dir)
     468                 :             :     {
     469                 :           4 :       res = g_resources_get_info (resource->path, 0, &size, &resource_flags, &my_error);
     470                 :           4 :       if (!res)
     471                 :             :         {
     472                 :           0 :           if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
     473                 :             :             {
     474                 :           0 :               g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
     475                 :             :                            _("The resource at “%s” does not exist"),
     476                 :             :                            resource->path);
     477                 :             :             }
     478                 :             :           else
     479                 :           0 :             g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
     480                 :           0 :                                  my_error->message);
     481                 :           0 :           g_clear_error (&my_error);
     482                 :           0 :           return FALSE;
     483                 :             :         }
     484                 :             :     }
     485                 :             : 
     486                 :           4 :   matcher = g_file_attribute_matcher_new (attributes);
     487                 :             : 
     488                 :           4 :   info = g_file_info_new ();
     489                 :           4 :   base = g_resource_file_get_basename (file);
     490                 :           4 :   g_file_info_set_name (info, base);
     491                 :           4 :   g_file_info_set_display_name (info, base);
     492                 :             : 
     493                 :           4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ, TRUE);
     494                 :           4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE, FALSE);
     495                 :           4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE, FALSE);
     496                 :           4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME, FALSE);
     497                 :           4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE, FALSE);
     498                 :           4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH, FALSE);
     499                 :             : 
     500                 :           4 :   if (is_dir)
     501                 :             :     {
     502                 :           0 :       g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
     503                 :             :     }
     504                 :             :   else
     505                 :             :     {
     506                 :             :       GBytes *bytes;
     507                 :             :       char *content_type;
     508                 :             : 
     509                 :           4 :       g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
     510                 :           4 :       g_file_info_set_size (info, size);
     511                 :             : 
     512                 :           4 :       if ((_g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE) ||
     513                 :           6 :            ((~resource_flags & G_RESOURCE_FLAGS_COMPRESSED) && 
     514                 :           4 :             _g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE))) &&
     515                 :           1 :           (bytes = g_resources_lookup_data (resource->path, 0, NULL)))
     516                 :           1 :         {
     517                 :             :           const guchar *data;
     518                 :             :           gsize data_size;
     519                 :             : 
     520                 :           1 :           data = g_bytes_get_data (bytes, &data_size);
     521                 :           1 :           content_type = g_content_type_guess (base, data, data_size, NULL);
     522                 :             : 
     523                 :           1 :           g_bytes_unref (bytes);
     524                 :             :         }
     525                 :             :       else
     526                 :           3 :         content_type = NULL;
     527                 :             : 
     528                 :           4 :       if (content_type)
     529                 :             :         {
     530                 :           1 :           _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE, content_type);
     531                 :           1 :           _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE, content_type);
     532                 :             : 
     533                 :           1 :           g_free (content_type);
     534                 :             :         }
     535                 :             :     }
     536                 :             : 
     537                 :           4 :   g_free (base);
     538                 :           4 :   g_file_attribute_matcher_unref (matcher);
     539                 :             : 
     540                 :           4 :   return info;
     541                 :             : }
     542                 :             : 
     543                 :             : static GFileInfo *
     544                 :           1 : g_resource_file_query_filesystem_info (GFile         *file,
     545                 :             :                                        const char    *attributes,
     546                 :             :                                        GCancellable  *cancellable,
     547                 :             :                                        GError       **error)
     548                 :             : {
     549                 :             :   GFileInfo *info;
     550                 :             :   GFileAttributeMatcher *matcher;
     551                 :             : 
     552                 :           1 :   info = g_file_info_new ();
     553                 :             : 
     554                 :           1 :   matcher = g_file_attribute_matcher_new (attributes);
     555                 :           1 :   if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE))
     556                 :           1 :     g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "resource");
     557                 :             : 
     558                 :           1 :   if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY))
     559                 :           1 :     g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
     560                 :             : 
     561                 :           1 :   g_file_attribute_matcher_unref (matcher);
     562                 :             : 
     563                 :           1 :   return info;
     564                 :             : }
     565                 :             : 
     566                 :             : static GFileAttributeInfoList *
     567                 :           1 : g_resource_file_query_settable_attributes (GFile         *file,
     568                 :             :                                            GCancellable  *cancellable,
     569                 :             :                                            GError       **error)
     570                 :             : {
     571                 :           1 :   return g_file_attribute_info_list_ref (resource_writable_attributes);
     572                 :             : }
     573                 :             : 
     574                 :             : static GFileAttributeInfoList *
     575                 :           1 : g_resource_file_query_writable_namespaces (GFile         *file,
     576                 :             :                                            GCancellable  *cancellable,
     577                 :             :                                            GError       **error)
     578                 :             : {
     579                 :           1 :   return g_file_attribute_info_list_ref (resource_writable_namespaces);
     580                 :             : }
     581                 :             : 
     582                 :             : static GFileInputStream *
     583                 :           1 : g_resource_file_read (GFile         *file,
     584                 :             :                       GCancellable  *cancellable,
     585                 :             :                       GError       **error)
     586                 :             : {
     587                 :           1 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     588                 :           1 :   GError *my_error = NULL;
     589                 :             :   GInputStream *stream;
     590                 :             :   GFileInputStream *res;
     591                 :             : 
     592                 :           1 :   stream = g_resources_open_stream (resource->path, 0, &my_error);
     593                 :             : 
     594                 :           1 :   if (stream == NULL)
     595                 :             :     {
     596                 :           0 :       if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
     597                 :             :         {
     598                 :           0 :           g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
     599                 :             :                        _("The resource at “%s” does not exist"),
     600                 :             :                        resource->path);
     601                 :             :         }
     602                 :             :       else
     603                 :           0 :         g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
     604                 :           0 :                              my_error->message);
     605                 :           0 :       g_clear_error (&my_error);
     606                 :           0 :       return NULL;
     607                 :             :     }
     608                 :             : 
     609                 :           1 :   res = _g_resource_file_input_stream_new (stream, file);
     610                 :           1 :   g_object_unref (stream);
     611                 :           1 :   return res;
     612                 :             : }
     613                 :             : 
     614                 :             : typedef GFileMonitor GResourceFileMonitor;
     615                 :             : typedef GFileMonitorClass GResourceFileMonitorClass;
     616                 :             : 
     617                 :             : GType g_resource_file_monitor_get_type (void);
     618                 :             : 
     619                 :           0 : G_DEFINE_TYPE (GResourceFileMonitor, g_resource_file_monitor, G_TYPE_FILE_MONITOR)
     620                 :             : 
     621                 :             : static gboolean
     622                 :           0 : g_resource_file_monitor_cancel (GFileMonitor *monitor)
     623                 :             : {
     624                 :           0 :   return TRUE;
     625                 :             : }
     626                 :             : 
     627                 :             : static void
     628                 :           0 : g_resource_file_monitor_init (GResourceFileMonitor *monitor)
     629                 :             : {
     630                 :           0 : }
     631                 :             : 
     632                 :             : static void
     633                 :           0 : g_resource_file_monitor_class_init (GResourceFileMonitorClass *class)
     634                 :             : {
     635                 :           0 :   class->cancel = g_resource_file_monitor_cancel;
     636                 :           0 : }
     637                 :             : 
     638                 :             : static GFileMonitor *
     639                 :           0 : g_resource_file_monitor_file (GFile              *file,
     640                 :             :                               GFileMonitorFlags   flags,
     641                 :             :                               GCancellable       *cancellable,
     642                 :             :                               GError            **error)
     643                 :             : {
     644                 :           0 :   return g_object_new (g_resource_file_monitor_get_type (), NULL);
     645                 :             : }
     646                 :             : 
     647                 :             : static GFile *
     648                 :           0 : g_resource_file_set_display_name (GFile         *file,
     649                 :             :                                   const char    *display_name,
     650                 :             :                                   GCancellable  *cancellable,
     651                 :             :                                   GError       **error)
     652                 :             : {
     653                 :           0 :   g_set_error_literal (error,
     654                 :             :                        G_IO_ERROR,
     655                 :             :                        G_IO_ERROR_NOT_SUPPORTED,
     656                 :             :                        _("Resource files cannot be renamed"));
     657                 :           0 :   return NULL;
     658                 :             : }
     659                 :             : 
     660                 :             : static gboolean
     661                 :           0 : g_resource_file_query_exists (GFile        *file,
     662                 :             :                               GCancellable *cancellable)
     663                 :             : {
     664                 :           0 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     665                 :             : 
     666                 :           0 :   return g_resources_get_info (resource->path, 0, NULL, NULL, NULL);
     667                 :             : }
     668                 :             : 
     669                 :             : static void
     670                 :           1 : g_resource_file_file_iface_init (GFileIface *iface)
     671                 :             : {
     672                 :           1 :   iface->dup = g_resource_file_dup;
     673                 :           1 :   iface->hash = g_resource_file_hash;
     674                 :           1 :   iface->equal = g_resource_file_equal;
     675                 :           1 :   iface->is_native = g_resource_file_is_native;
     676                 :           1 :   iface->has_uri_scheme = g_resource_file_has_uri_scheme;
     677                 :           1 :   iface->get_uri_scheme = g_resource_file_get_uri_scheme;
     678                 :           1 :   iface->get_basename = g_resource_file_get_basename;
     679                 :           1 :   iface->get_path = g_resource_file_get_path;
     680                 :           1 :   iface->get_uri = g_resource_file_get_uri;
     681                 :           1 :   iface->get_parse_name = g_resource_file_get_parse_name;
     682                 :           1 :   iface->get_parent = g_resource_file_get_parent;
     683                 :           1 :   iface->prefix_matches = g_resource_file_prefix_matches;
     684                 :           1 :   iface->get_relative_path = g_resource_file_get_relative_path;
     685                 :           1 :   iface->resolve_relative_path = g_resource_file_resolve_relative_path;
     686                 :           1 :   iface->get_child_for_display_name = g_resource_file_get_child_for_display_name;
     687                 :           1 :   iface->set_display_name = g_resource_file_set_display_name;
     688                 :           1 :   iface->enumerate_children = g_resource_file_enumerate_children;
     689                 :           1 :   iface->query_info = g_resource_file_query_info;
     690                 :           1 :   iface->query_filesystem_info = g_resource_file_query_filesystem_info;
     691                 :           1 :   iface->query_settable_attributes = g_resource_file_query_settable_attributes;
     692                 :           1 :   iface->query_writable_namespaces = g_resource_file_query_writable_namespaces;
     693                 :           1 :   iface->read_fn = g_resource_file_read;
     694                 :           1 :   iface->monitor_file = g_resource_file_monitor_file;
     695                 :           1 :   iface->query_exists = g_resource_file_query_exists;
     696                 :             : 
     697                 :           1 :   iface->supports_thread_contexts = TRUE;
     698                 :           1 : }
     699                 :             : 
     700                 :             : static GFileInfo *g_resource_file_enumerator_next_file (GFileEnumerator  *enumerator,
     701                 :             :                                                         GCancellable     *cancellable,
     702                 :             :                                                         GError          **error);
     703                 :             : static gboolean   g_resource_file_enumerator_close     (GFileEnumerator  *enumerator,
     704                 :             :                                                         GCancellable     *cancellable,
     705                 :             :                                                         GError          **error);
     706                 :             : 
     707                 :             : static void
     708                 :           1 : g_resource_file_enumerator_finalize (GObject *object)
     709                 :             : {
     710                 :             :   GResourceFileEnumerator *resource;
     711                 :             : 
     712                 :           1 :   resource = G_RESOURCE_FILE_ENUMERATOR (object);
     713                 :             : 
     714                 :           1 :   g_strfreev (resource->children);
     715                 :           1 :   g_free (resource->path);
     716                 :           1 :   g_free (resource->attributes);
     717                 :             : 
     718                 :           1 :   G_OBJECT_CLASS (g_resource_file_enumerator_parent_class)->finalize (object);
     719                 :           1 : }
     720                 :             : 
     721                 :             : static void
     722                 :           1 : g_resource_file_enumerator_class_init (GResourceFileEnumeratorClass *klass)
     723                 :             : {
     724                 :           1 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     725                 :           1 :   GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
     726                 :             : 
     727                 :           1 :   gobject_class->finalize = g_resource_file_enumerator_finalize;
     728                 :             : 
     729                 :           1 :   enumerator_class->next_file = g_resource_file_enumerator_next_file;
     730                 :           1 :   enumerator_class->close_fn = g_resource_file_enumerator_close;
     731                 :           1 : }
     732                 :             : 
     733                 :             : static void
     734                 :           1 : g_resource_file_enumerator_init (GResourceFileEnumerator *resource)
     735                 :             : {
     736                 :           1 : }
     737                 :             : 
     738                 :             : static GFileEnumerator *
     739                 :           1 : _g_resource_file_enumerator_new (GResourceFile *file,
     740                 :             :                                  const char           *attributes,
     741                 :             :                                  GFileQueryInfoFlags   flags,
     742                 :             :                                  GCancellable         *cancellable,
     743                 :             :                                  GError              **error)
     744                 :             : {
     745                 :             :   GResourceFileEnumerator *resource;
     746                 :             :   char **children;
     747                 :             :   gboolean res;
     748                 :             : 
     749                 :           1 :   children = g_resources_enumerate_children (file->path, 0, NULL);
     750                 :           1 :   if (children == NULL &&
     751                 :           0 :       strcmp ("/", file->path) != 0)
     752                 :             :     {
     753                 :           0 :       res = g_resources_get_info (file->path, 0, NULL, NULL, NULL);
     754                 :           0 :       if (res)
     755                 :           0 :         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
     756                 :             :                      _("The resource at “%s” is not a directory"),
     757                 :             :                      file->path);
     758                 :             :       else
     759                 :           0 :         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
     760                 :             :                      _("The resource at “%s” does not exist"),
     761                 :             :                      file->path);
     762                 :           0 :       return NULL;
     763                 :             :     }
     764                 :             : 
     765                 :           1 :   resource = g_object_new (G_TYPE_RESOURCE_FILE_ENUMERATOR,
     766                 :             :                            "container", file,
     767                 :             :                            NULL);
     768                 :             : 
     769                 :           1 :   resource->children = children;
     770                 :           2 :   resource->path = g_strdup (file->path);
     771                 :           1 :   resource->attributes = g_strdup (attributes);
     772                 :           1 :   resource->flags = flags;
     773                 :             : 
     774                 :           1 :   return G_FILE_ENUMERATOR (resource);
     775                 :             : }
     776                 :             : 
     777                 :             : static GFileInfo *
     778                 :           3 : g_resource_file_enumerator_next_file (GFileEnumerator  *enumerator,
     779                 :             :                                       GCancellable     *cancellable,
     780                 :             :                                       GError          **error)
     781                 :             : {
     782                 :           3 :   GResourceFileEnumerator *resource = G_RESOURCE_FILE_ENUMERATOR (enumerator);
     783                 :             :   char *path;
     784                 :             :   GFileInfo *info;
     785                 :             :   GFile *file;
     786                 :             : 
     787                 :           3 :   if (resource->children == NULL ||
     788                 :           3 :       resource->children[resource->index] == NULL)
     789                 :           1 :     return NULL;
     790                 :             : 
     791                 :           2 :   path = g_build_path ("/", resource->path, resource->children[resource->index++], NULL);
     792                 :           2 :   file = g_resource_file_new_for_path (path);
     793                 :           2 :   g_free (path);
     794                 :             : 
     795                 :           2 :   info = g_file_query_info (file,
     796                 :           2 :                             resource->attributes,
     797                 :             :                             resource->flags,
     798                 :             :                             cancellable,
     799                 :             :                             error);
     800                 :             : 
     801                 :           2 :   g_object_unref (file);
     802                 :             : 
     803                 :           2 :   return info;
     804                 :             : }
     805                 :             : 
     806                 :             : static gboolean
     807                 :           1 : g_resource_file_enumerator_close (GFileEnumerator  *enumerator,
     808                 :             :                                GCancellable     *cancellable,
     809                 :             :                                GError          **error)
     810                 :             : {
     811                 :           1 :   return TRUE;
     812                 :             : }
     813                 :             : 
     814                 :             : 
     815                 :             : struct _GResourceFileInputStream
     816                 :             : {
     817                 :             :   GFileInputStream parent_instance;
     818                 :             :   GInputStream *stream;
     819                 :             :   GFile *file;
     820                 :             : };
     821                 :             : 
     822                 :             : struct _GResourceFileInputStreamClass
     823                 :             : {
     824                 :             :   GFileInputStreamClass parent_class;
     825                 :             : };
     826                 :             : 
     827                 :             : #define g_resource_file_input_stream_get_type _g_resource_file_input_stream_get_type
     828                 :          12 : G_DEFINE_TYPE (GResourceFileInputStream, g_resource_file_input_stream, G_TYPE_FILE_INPUT_STREAM)
     829                 :             : 
     830                 :             : static gssize     g_resource_file_input_stream_read       (GInputStream      *stream,
     831                 :             :                                                            void              *buffer,
     832                 :             :                                                            gsize              count,
     833                 :             :                                                            GCancellable      *cancellable,
     834                 :             :                                                            GError           **error);
     835                 :             : static gssize     g_resource_file_input_stream_skip       (GInputStream      *stream,
     836                 :             :                                                            gsize              count,
     837                 :             :                                                            GCancellable      *cancellable,
     838                 :             :                                                            GError           **error);
     839                 :             : static gboolean   g_resource_file_input_stream_close      (GInputStream      *stream,
     840                 :             :                                                            GCancellable      *cancellable,
     841                 :             :                                                            GError           **error);
     842                 :             : static goffset    g_resource_file_input_stream_tell       (GFileInputStream  *stream);
     843                 :             : static gboolean   g_resource_file_input_stream_can_seek   (GFileInputStream  *stream);
     844                 :             : static gboolean   g_resource_file_input_stream_seek       (GFileInputStream  *stream,
     845                 :             :                                                            goffset            offset,
     846                 :             :                                                            GSeekType          type,
     847                 :             :                                                            GCancellable      *cancellable,
     848                 :             :                                                            GError           **error);
     849                 :             : static GFileInfo *g_resource_file_input_stream_query_info (GFileInputStream  *stream,
     850                 :             :                                                            const char        *attributes,
     851                 :             :                                                            GCancellable      *cancellable,
     852                 :             :                                                            GError           **error);
     853                 :             : 
     854                 :             : static void
     855                 :           1 : g_resource_file_input_stream_finalize (GObject *object)
     856                 :             : {
     857                 :           1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (object);
     858                 :             : 
     859                 :           1 :   g_object_unref (file->stream);
     860                 :           1 :   g_object_unref (file->file);
     861                 :           1 :   G_OBJECT_CLASS (g_resource_file_input_stream_parent_class)->finalize (object);
     862                 :           1 : }
     863                 :             : 
     864                 :             : static void
     865                 :           1 : g_resource_file_input_stream_class_init (GResourceFileInputStreamClass *klass)
     866                 :             : {
     867                 :           1 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     868                 :           1 :   GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
     869                 :           1 :   GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
     870                 :             : 
     871                 :           1 :   gobject_class->finalize = g_resource_file_input_stream_finalize;
     872                 :             : 
     873                 :           1 :   stream_class->read_fn = g_resource_file_input_stream_read;
     874                 :           1 :   stream_class->skip = g_resource_file_input_stream_skip;
     875                 :           1 :   stream_class->close_fn = g_resource_file_input_stream_close;
     876                 :           1 :   file_stream_class->tell = g_resource_file_input_stream_tell;
     877                 :           1 :   file_stream_class->can_seek = g_resource_file_input_stream_can_seek;
     878                 :           1 :   file_stream_class->seek = g_resource_file_input_stream_seek;
     879                 :           1 :   file_stream_class->query_info = g_resource_file_input_stream_query_info;
     880                 :           1 : }
     881                 :             : 
     882                 :             : static void
     883                 :           1 : g_resource_file_input_stream_init (GResourceFileInputStream *info)
     884                 :             : {
     885                 :           1 : }
     886                 :             : 
     887                 :             : static GFileInputStream *
     888                 :           1 : _g_resource_file_input_stream_new (GInputStream *in_stream, GFile *file)
     889                 :             : {
     890                 :             :   GResourceFileInputStream *stream;
     891                 :             : 
     892                 :           1 :   stream = g_object_new (G_TYPE_RESOURCE_FILE_INPUT_STREAM, NULL);
     893                 :           1 :   stream->stream = g_object_ref (in_stream);
     894                 :           1 :   stream->file = g_object_ref (file);
     895                 :             : 
     896                 :           1 :   return G_FILE_INPUT_STREAM (stream);
     897                 :             : }
     898                 :             : 
     899                 :             : static gssize
     900                 :           2 : g_resource_file_input_stream_read (GInputStream  *stream,
     901                 :             :                                    void          *buffer,
     902                 :             :                                    gsize          count,
     903                 :             :                                    GCancellable  *cancellable,
     904                 :             :                                    GError       **error)
     905                 :             : {
     906                 :           2 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     907                 :           2 :   return g_input_stream_read (file->stream,
     908                 :             :                               buffer, count, cancellable, error);
     909                 :             : }
     910                 :             : 
     911                 :             : static gssize
     912                 :           1 : g_resource_file_input_stream_skip (GInputStream  *stream,
     913                 :             :                                    gsize          count,
     914                 :             :                                    GCancellable  *cancellable,
     915                 :             :                                    GError       **error)
     916                 :             : {
     917                 :           1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     918                 :           1 :   return g_input_stream_skip (file->stream,
     919                 :             :                               count, cancellable, error);
     920                 :             : }
     921                 :             : 
     922                 :             : static gboolean
     923                 :           1 : g_resource_file_input_stream_close (GInputStream  *stream,
     924                 :             :                                     GCancellable  *cancellable,
     925                 :             :                                     GError       **error)
     926                 :             : {
     927                 :           1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     928                 :           1 :   return g_input_stream_close (file->stream,
     929                 :             :                                cancellable, error);
     930                 :             : }
     931                 :             : 
     932                 :             : 
     933                 :             : static goffset
     934                 :           1 : g_resource_file_input_stream_tell (GFileInputStream *stream)
     935                 :             : {
     936                 :           1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     937                 :             : 
     938                 :           1 :   if (!G_IS_SEEKABLE (file->stream))
     939                 :           0 :       return 0;
     940                 :             : 
     941                 :           1 :   return g_seekable_tell (G_SEEKABLE (file->stream));
     942                 :             : }
     943                 :             : 
     944                 :             : static gboolean
     945                 :           1 : g_resource_file_input_stream_can_seek (GFileInputStream *stream)
     946                 :             : {
     947                 :           1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     948                 :             : 
     949                 :           1 :   return G_IS_SEEKABLE (file->stream) && g_seekable_can_seek (G_SEEKABLE (file->stream));
     950                 :             : }
     951                 :             : 
     952                 :             : static gboolean
     953                 :           1 : g_resource_file_input_stream_seek (GFileInputStream  *stream,
     954                 :             :                                    goffset            offset,
     955                 :             :                                    GSeekType          type,
     956                 :             :                                    GCancellable      *cancellable,
     957                 :             :                                    GError           **error)
     958                 :             : {
     959                 :           1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     960                 :             : 
     961                 :           1 :   if (!G_IS_SEEKABLE (file->stream))
     962                 :             :     {
     963                 :           0 :       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     964                 :             :                            _("Input stream doesn’t implement seek"));
     965                 :           0 :       return FALSE;
     966                 :             :     }
     967                 :             : 
     968                 :           1 :   return g_seekable_seek (G_SEEKABLE (file->stream),
     969                 :             :                           offset, type, cancellable, error);
     970                 :             : }
     971                 :             : 
     972                 :             : static GFileInfo *
     973                 :           1 : g_resource_file_input_stream_query_info (GFileInputStream  *stream,
     974                 :             :                                          const char        *attributes,
     975                 :             :                                          GCancellable      *cancellable,
     976                 :             :                                          GError           **error)
     977                 :             : {
     978                 :           1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     979                 :             : 
     980                 :           1 :   return g_file_query_info (file->file, attributes, 0, cancellable, error);
     981                 :             : }
        

Generated by: LCOV version 2.0-1