LCOV - code coverage report
Current view: top level - glib/gio - gresourcefile.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 303 348 87.1 %
Date: 2024-03-26 05:16:46 Functions: 57 65 87.7 %
Branches: 88 142 62.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                 :            :   int 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                 :            :   char **children;
     459                 :            :   gboolean is_dir;
     460                 :            :   char *base;
     461                 :            : 
     462                 :          4 :   is_dir = FALSE;
     463                 :          4 :   children = g_resources_enumerate_children (resource->path, 0, NULL);
     464         [ -  + ]:          4 :   if (children != NULL)
     465                 :            :     {
     466                 :          0 :       g_strfreev (children);
     467                 :          0 :       is_dir = TRUE;
     468                 :            :     }
     469                 :            : 
     470                 :            :   /* root is always there */
     471         [ -  + ]:          4 :   if (strcmp ("/", resource->path) == 0)
     472                 :          0 :     is_dir = TRUE;
     473                 :            : 
     474         [ +  - ]:          4 :   if (!is_dir)
     475                 :            :     {
     476                 :          4 :       res = g_resources_get_info (resource->path, 0, &size, &resource_flags, &my_error);
     477         [ -  + ]:          4 :       if (!res)
     478                 :            :         {
     479         [ #  # ]:          0 :           if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
     480                 :            :             {
     481                 :          0 :               g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
     482                 :            :                            _("The resource at “%s” does not exist"),
     483                 :            :                            resource->path);
     484                 :            :             }
     485                 :            :           else
     486                 :          0 :             g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
     487                 :          0 :                                  my_error->message);
     488                 :          0 :           g_clear_error (&my_error);
     489                 :          0 :           return FALSE;
     490                 :            :         }
     491                 :            :     }
     492                 :            : 
     493                 :          4 :   matcher = g_file_attribute_matcher_new (attributes);
     494                 :            : 
     495                 :          4 :   info = g_file_info_new ();
     496                 :          4 :   base = g_resource_file_get_basename (file);
     497                 :          4 :   g_file_info_set_name (info, base);
     498                 :          4 :   g_file_info_set_display_name (info, base);
     499                 :            : 
     500                 :          4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ, TRUE);
     501                 :          4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE, FALSE);
     502                 :          4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE, FALSE);
     503                 :          4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME, FALSE);
     504                 :          4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE, FALSE);
     505                 :          4 :   _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH, FALSE);
     506                 :            : 
     507         [ -  + ]:          4 :   if (is_dir)
     508                 :            :     {
     509                 :          0 :       g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
     510                 :            :     }
     511                 :            :   else
     512                 :            :     {
     513                 :            :       GBytes *bytes;
     514                 :            :       char *content_type;
     515                 :            : 
     516                 :          4 :       g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
     517                 :          4 :       g_file_info_set_size (info, size);
     518                 :            : 
     519         [ +  + ]:          4 :       if ((_g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE) ||
     520   [ +  -  -  + ]:          6 :            ((~resource_flags & G_RESOURCE_FLAGS_COMPRESSED) && 
     521         [ +  - ]:          4 :             _g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE))) &&
     522                 :          1 :           (bytes = g_resources_lookup_data (resource->path, 0, NULL)))
     523                 :          1 :         {
     524                 :            :           const guchar *data;
     525                 :            :           gsize data_size;
     526                 :            : 
     527                 :          1 :           data = g_bytes_get_data (bytes, &data_size);
     528                 :          1 :           content_type = g_content_type_guess (base, data, data_size, NULL);
     529                 :            : 
     530                 :          1 :           g_bytes_unref (bytes);
     531                 :            :         }
     532                 :            :       else
     533                 :          3 :         content_type = NULL;
     534                 :            : 
     535         [ +  + ]:          4 :       if (content_type)
     536                 :            :         {
     537                 :          1 :           _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE, content_type);
     538                 :          1 :           _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE, content_type);
     539                 :            : 
     540                 :          1 :           g_free (content_type);
     541                 :            :         }
     542                 :            :     }
     543                 :            : 
     544                 :          4 :   g_free (base);
     545                 :          4 :   g_file_attribute_matcher_unref (matcher);
     546                 :            : 
     547                 :          4 :   return info;
     548                 :            : }
     549                 :            : 
     550                 :            : static GFileInfo *
     551                 :          1 : g_resource_file_query_filesystem_info (GFile         *file,
     552                 :            :                                        const char    *attributes,
     553                 :            :                                        GCancellable  *cancellable,
     554                 :            :                                        GError       **error)
     555                 :            : {
     556                 :            :   GFileInfo *info;
     557                 :            :   GFileAttributeMatcher *matcher;
     558                 :            : 
     559                 :          1 :   info = g_file_info_new ();
     560                 :            : 
     561                 :          1 :   matcher = g_file_attribute_matcher_new (attributes);
     562         [ +  - ]:          1 :   if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE))
     563                 :          1 :     g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "resource");
     564                 :            : 
     565         [ +  - ]:          1 :   if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY))
     566                 :          1 :     g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
     567                 :            : 
     568                 :          1 :   g_file_attribute_matcher_unref (matcher);
     569                 :            : 
     570                 :          1 :   return info;
     571                 :            : }
     572                 :            : 
     573                 :            : static GFileAttributeInfoList *
     574                 :          1 : g_resource_file_query_settable_attributes (GFile         *file,
     575                 :            :                                            GCancellable  *cancellable,
     576                 :            :                                            GError       **error)
     577                 :            : {
     578                 :          1 :   return g_file_attribute_info_list_ref (resource_writable_attributes);
     579                 :            : }
     580                 :            : 
     581                 :            : static GFileAttributeInfoList *
     582                 :          1 : g_resource_file_query_writable_namespaces (GFile         *file,
     583                 :            :                                            GCancellable  *cancellable,
     584                 :            :                                            GError       **error)
     585                 :            : {
     586                 :          1 :   return g_file_attribute_info_list_ref (resource_writable_namespaces);
     587                 :            : }
     588                 :            : 
     589                 :            : static GFileInputStream *
     590                 :          1 : g_resource_file_read (GFile         *file,
     591                 :            :                       GCancellable  *cancellable,
     592                 :            :                       GError       **error)
     593                 :            : {
     594                 :          1 :   GResourceFile *resource = G_RESOURCE_FILE (file);
     595                 :          1 :   GError *my_error = NULL;
     596                 :            :   GInputStream *stream;
     597                 :            :   GFileInputStream *res;
     598                 :            : 
     599                 :          1 :   stream = g_resources_open_stream (resource->path, 0, &my_error);
     600                 :            : 
     601         [ -  + ]:          1 :   if (stream == NULL)
     602                 :            :     {
     603         [ #  # ]:          0 :       if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
     604                 :            :         {
     605                 :          0 :           g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
     606                 :            :                        _("The resource at “%s” does not exist"),
     607                 :            :                        resource->path);
     608                 :            :         }
     609                 :            :       else
     610                 :          0 :         g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
     611                 :          0 :                              my_error->message);
     612                 :          0 :       g_clear_error (&my_error);
     613                 :          0 :       return NULL;
     614                 :            :     }
     615                 :            : 
     616                 :          1 :   res = _g_resource_file_input_stream_new (stream, file);
     617                 :          1 :   g_object_unref (stream);
     618                 :          1 :   return res;
     619                 :            : }
     620                 :            : 
     621                 :            : typedef GFileMonitor GResourceFileMonitor;
     622                 :            : typedef GFileMonitorClass GResourceFileMonitorClass;
     623                 :            : 
     624                 :            : GType g_resource_file_monitor_get_type (void);
     625                 :            : 
     626   [ #  #  #  #  :          0 : G_DEFINE_TYPE (GResourceFileMonitor, g_resource_file_monitor, G_TYPE_FILE_MONITOR)
                   #  # ]
     627                 :            : 
     628                 :            : static gboolean
     629                 :          0 : g_resource_file_monitor_cancel (GFileMonitor *monitor)
     630                 :            : {
     631                 :          0 :   return TRUE;
     632                 :            : }
     633                 :            : 
     634                 :            : static void
     635                 :          0 : g_resource_file_monitor_init (GResourceFileMonitor *monitor)
     636                 :            : {
     637                 :          0 : }
     638                 :            : 
     639                 :            : static void
     640                 :          0 : g_resource_file_monitor_class_init (GResourceFileMonitorClass *class)
     641                 :            : {
     642                 :          0 :   class->cancel = g_resource_file_monitor_cancel;
     643                 :          0 : }
     644                 :            : 
     645                 :            : static GFileMonitor *
     646                 :          0 : g_resource_file_monitor_file (GFile              *file,
     647                 :            :                               GFileMonitorFlags   flags,
     648                 :            :                               GCancellable       *cancellable,
     649                 :            :                               GError            **error)
     650                 :            : {
     651                 :          0 :   return g_object_new (g_resource_file_monitor_get_type (), NULL);
     652                 :            : }
     653                 :            : 
     654                 :            : static GFile *
     655                 :          0 : g_resource_file_set_display_name (GFile         *file,
     656                 :            :                                   const char    *display_name,
     657                 :            :                                   GCancellable  *cancellable,
     658                 :            :                                   GError       **error)
     659                 :            : {
     660                 :          0 :   g_set_error_literal (error,
     661                 :            :                        G_IO_ERROR,
     662                 :            :                        G_IO_ERROR_NOT_SUPPORTED,
     663                 :            :                        _("Resource files cannot be renamed"));
     664                 :          0 :   return NULL;
     665                 :            : }
     666                 :            : 
     667                 :            : static void
     668                 :          1 : g_resource_file_file_iface_init (GFileIface *iface)
     669                 :            : {
     670                 :          1 :   iface->dup = g_resource_file_dup;
     671                 :          1 :   iface->hash = g_resource_file_hash;
     672                 :          1 :   iface->equal = g_resource_file_equal;
     673                 :          1 :   iface->is_native = g_resource_file_is_native;
     674                 :          1 :   iface->has_uri_scheme = g_resource_file_has_uri_scheme;
     675                 :          1 :   iface->get_uri_scheme = g_resource_file_get_uri_scheme;
     676                 :          1 :   iface->get_basename = g_resource_file_get_basename;
     677                 :          1 :   iface->get_path = g_resource_file_get_path;
     678                 :          1 :   iface->get_uri = g_resource_file_get_uri;
     679                 :          1 :   iface->get_parse_name = g_resource_file_get_parse_name;
     680                 :          1 :   iface->get_parent = g_resource_file_get_parent;
     681                 :          1 :   iface->prefix_matches = g_resource_file_prefix_matches;
     682                 :          1 :   iface->get_relative_path = g_resource_file_get_relative_path;
     683                 :          1 :   iface->resolve_relative_path = g_resource_file_resolve_relative_path;
     684                 :          1 :   iface->get_child_for_display_name = g_resource_file_get_child_for_display_name;
     685                 :          1 :   iface->set_display_name = g_resource_file_set_display_name;
     686                 :          1 :   iface->enumerate_children = g_resource_file_enumerate_children;
     687                 :          1 :   iface->query_info = g_resource_file_query_info;
     688                 :          1 :   iface->query_filesystem_info = g_resource_file_query_filesystem_info;
     689                 :          1 :   iface->query_settable_attributes = g_resource_file_query_settable_attributes;
     690                 :          1 :   iface->query_writable_namespaces = g_resource_file_query_writable_namespaces;
     691                 :          1 :   iface->read_fn = g_resource_file_read;
     692                 :          1 :   iface->monitor_file = g_resource_file_monitor_file;
     693                 :            : 
     694                 :          1 :   iface->supports_thread_contexts = TRUE;
     695                 :          1 : }
     696                 :            : 
     697                 :            : static GFileInfo *g_resource_file_enumerator_next_file (GFileEnumerator  *enumerator,
     698                 :            :                                                         GCancellable     *cancellable,
     699                 :            :                                                         GError          **error);
     700                 :            : static gboolean   g_resource_file_enumerator_close     (GFileEnumerator  *enumerator,
     701                 :            :                                                         GCancellable     *cancellable,
     702                 :            :                                                         GError          **error);
     703                 :            : 
     704                 :            : static void
     705                 :          1 : g_resource_file_enumerator_finalize (GObject *object)
     706                 :            : {
     707                 :            :   GResourceFileEnumerator *resource;
     708                 :            : 
     709                 :          1 :   resource = G_RESOURCE_FILE_ENUMERATOR (object);
     710                 :            : 
     711                 :          1 :   g_strfreev (resource->children);
     712                 :          1 :   g_free (resource->path);
     713                 :          1 :   g_free (resource->attributes);
     714                 :            : 
     715                 :          1 :   G_OBJECT_CLASS (g_resource_file_enumerator_parent_class)->finalize (object);
     716                 :          1 : }
     717                 :            : 
     718                 :            : static void
     719                 :          1 : g_resource_file_enumerator_class_init (GResourceFileEnumeratorClass *klass)
     720                 :            : {
     721                 :          1 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     722                 :          1 :   GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
     723                 :            : 
     724                 :          1 :   gobject_class->finalize = g_resource_file_enumerator_finalize;
     725                 :            : 
     726                 :          1 :   enumerator_class->next_file = g_resource_file_enumerator_next_file;
     727                 :          1 :   enumerator_class->close_fn = g_resource_file_enumerator_close;
     728                 :          1 : }
     729                 :            : 
     730                 :            : static void
     731                 :          1 : g_resource_file_enumerator_init (GResourceFileEnumerator *resource)
     732                 :            : {
     733                 :          1 : }
     734                 :            : 
     735                 :            : static GFileEnumerator *
     736                 :          1 : _g_resource_file_enumerator_new (GResourceFile *file,
     737                 :            :                                  const char           *attributes,
     738                 :            :                                  GFileQueryInfoFlags   flags,
     739                 :            :                                  GCancellable         *cancellable,
     740                 :            :                                  GError              **error)
     741                 :            : {
     742                 :            :   GResourceFileEnumerator *resource;
     743                 :            :   char **children;
     744                 :            :   gboolean res;
     745                 :            : 
     746                 :          1 :   children = g_resources_enumerate_children (file->path, 0, NULL);
     747         [ -  + ]:          1 :   if (children == NULL &&
     748         [ #  # ]:          0 :       strcmp ("/", file->path) != 0)
     749                 :            :     {
     750                 :          0 :       res = g_resources_get_info (file->path, 0, NULL, NULL, NULL);
     751         [ #  # ]:          0 :       if (res)
     752                 :          0 :         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
     753                 :            :                      _("The resource at “%s” is not a directory"),
     754                 :            :                      file->path);
     755                 :            :       else
     756                 :          0 :         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
     757                 :            :                      _("The resource at “%s” does not exist"),
     758                 :            :                      file->path);
     759                 :          0 :       return NULL;
     760                 :            :     }
     761                 :            : 
     762                 :          1 :   resource = g_object_new (G_TYPE_RESOURCE_FILE_ENUMERATOR,
     763                 :            :                            "container", file,
     764                 :            :                            NULL);
     765                 :            : 
     766                 :          1 :   resource->children = children;
     767                 :          2 :   resource->path = g_strdup (file->path);
     768                 :          1 :   resource->attributes = g_strdup (attributes);
     769                 :          1 :   resource->flags = flags;
     770                 :            : 
     771                 :          1 :   return G_FILE_ENUMERATOR (resource);
     772                 :            : }
     773                 :            : 
     774                 :            : static GFileInfo *
     775                 :          3 : g_resource_file_enumerator_next_file (GFileEnumerator  *enumerator,
     776                 :            :                                       GCancellable     *cancellable,
     777                 :            :                                       GError          **error)
     778                 :            : {
     779                 :          3 :   GResourceFileEnumerator *resource = G_RESOURCE_FILE_ENUMERATOR (enumerator);
     780                 :            :   char *path;
     781                 :            :   GFileInfo *info;
     782                 :            :   GFile *file;
     783                 :            : 
     784         [ +  - ]:          3 :   if (resource->children == NULL ||
     785         [ +  + ]:          3 :       resource->children[resource->index] == NULL)
     786                 :          1 :     return NULL;
     787                 :            : 
     788                 :          2 :   path = g_build_path ("/", resource->path, resource->children[resource->index++], NULL);
     789                 :          2 :   file = g_resource_file_new_for_path (path);
     790                 :          2 :   g_free (path);
     791                 :            : 
     792                 :          2 :   info = g_file_query_info (file,
     793                 :          2 :                             resource->attributes,
     794                 :            :                             resource->flags,
     795                 :            :                             cancellable,
     796                 :            :                             error);
     797                 :            : 
     798                 :          2 :   g_object_unref (file);
     799                 :            : 
     800                 :          2 :   return info;
     801                 :            : }
     802                 :            : 
     803                 :            : static gboolean
     804                 :          1 : g_resource_file_enumerator_close (GFileEnumerator  *enumerator,
     805                 :            :                                GCancellable     *cancellable,
     806                 :            :                                GError          **error)
     807                 :            : {
     808                 :          1 :   return TRUE;
     809                 :            : }
     810                 :            : 
     811                 :            : 
     812                 :            : struct _GResourceFileInputStream
     813                 :            : {
     814                 :            :   GFileInputStream parent_instance;
     815                 :            :   GInputStream *stream;
     816                 :            :   GFile *file;
     817                 :            : };
     818                 :            : 
     819                 :            : struct _GResourceFileInputStreamClass
     820                 :            : {
     821                 :            :   GFileInputStreamClass parent_class;
     822                 :            : };
     823                 :            : 
     824                 :            : #define g_resource_file_input_stream_get_type _g_resource_file_input_stream_get_type
     825   [ +  +  +  -  :         12 : G_DEFINE_TYPE (GResourceFileInputStream, g_resource_file_input_stream, G_TYPE_FILE_INPUT_STREAM)
                   +  + ]
     826                 :            : 
     827                 :            : static gssize     g_resource_file_input_stream_read       (GInputStream      *stream,
     828                 :            :                                                            void              *buffer,
     829                 :            :                                                            gsize              count,
     830                 :            :                                                            GCancellable      *cancellable,
     831                 :            :                                                            GError           **error);
     832                 :            : static gssize     g_resource_file_input_stream_skip       (GInputStream      *stream,
     833                 :            :                                                            gsize              count,
     834                 :            :                                                            GCancellable      *cancellable,
     835                 :            :                                                            GError           **error);
     836                 :            : static gboolean   g_resource_file_input_stream_close      (GInputStream      *stream,
     837                 :            :                                                            GCancellable      *cancellable,
     838                 :            :                                                            GError           **error);
     839                 :            : static goffset    g_resource_file_input_stream_tell       (GFileInputStream  *stream);
     840                 :            : static gboolean   g_resource_file_input_stream_can_seek   (GFileInputStream  *stream);
     841                 :            : static gboolean   g_resource_file_input_stream_seek       (GFileInputStream  *stream,
     842                 :            :                                                            goffset            offset,
     843                 :            :                                                            GSeekType          type,
     844                 :            :                                                            GCancellable      *cancellable,
     845                 :            :                                                            GError           **error);
     846                 :            : static GFileInfo *g_resource_file_input_stream_query_info (GFileInputStream  *stream,
     847                 :            :                                                            const char        *attributes,
     848                 :            :                                                            GCancellable      *cancellable,
     849                 :            :                                                            GError           **error);
     850                 :            : 
     851                 :            : static void
     852                 :          1 : g_resource_file_input_stream_finalize (GObject *object)
     853                 :            : {
     854                 :          1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (object);
     855                 :            : 
     856                 :          1 :   g_object_unref (file->stream);
     857                 :          1 :   g_object_unref (file->file);
     858                 :          1 :   G_OBJECT_CLASS (g_resource_file_input_stream_parent_class)->finalize (object);
     859                 :          1 : }
     860                 :            : 
     861                 :            : static void
     862                 :          1 : g_resource_file_input_stream_class_init (GResourceFileInputStreamClass *klass)
     863                 :            : {
     864                 :          1 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     865                 :          1 :   GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
     866                 :          1 :   GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
     867                 :            : 
     868                 :          1 :   gobject_class->finalize = g_resource_file_input_stream_finalize;
     869                 :            : 
     870                 :          1 :   stream_class->read_fn = g_resource_file_input_stream_read;
     871                 :          1 :   stream_class->skip = g_resource_file_input_stream_skip;
     872                 :          1 :   stream_class->close_fn = g_resource_file_input_stream_close;
     873                 :          1 :   file_stream_class->tell = g_resource_file_input_stream_tell;
     874                 :          1 :   file_stream_class->can_seek = g_resource_file_input_stream_can_seek;
     875                 :          1 :   file_stream_class->seek = g_resource_file_input_stream_seek;
     876                 :          1 :   file_stream_class->query_info = g_resource_file_input_stream_query_info;
     877                 :          1 : }
     878                 :            : 
     879                 :            : static void
     880                 :          1 : g_resource_file_input_stream_init (GResourceFileInputStream *info)
     881                 :            : {
     882                 :          1 : }
     883                 :            : 
     884                 :            : static GFileInputStream *
     885                 :          1 : _g_resource_file_input_stream_new (GInputStream *in_stream, GFile *file)
     886                 :            : {
     887                 :            :   GResourceFileInputStream *stream;
     888                 :            : 
     889                 :          1 :   stream = g_object_new (G_TYPE_RESOURCE_FILE_INPUT_STREAM, NULL);
     890                 :          1 :   stream->stream = g_object_ref (in_stream);
     891                 :          1 :   stream->file = g_object_ref (file);
     892                 :            : 
     893                 :          1 :   return G_FILE_INPUT_STREAM (stream);
     894                 :            : }
     895                 :            : 
     896                 :            : static gssize
     897                 :          2 : g_resource_file_input_stream_read (GInputStream  *stream,
     898                 :            :                                    void          *buffer,
     899                 :            :                                    gsize          count,
     900                 :            :                                    GCancellable  *cancellable,
     901                 :            :                                    GError       **error)
     902                 :            : {
     903                 :          2 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     904                 :          2 :   return g_input_stream_read (file->stream,
     905                 :            :                               buffer, count, cancellable, error);
     906                 :            : }
     907                 :            : 
     908                 :            : static gssize
     909                 :          1 : g_resource_file_input_stream_skip (GInputStream  *stream,
     910                 :            :                                    gsize          count,
     911                 :            :                                    GCancellable  *cancellable,
     912                 :            :                                    GError       **error)
     913                 :            : {
     914                 :          1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     915                 :          1 :   return g_input_stream_skip (file->stream,
     916                 :            :                               count, cancellable, error);
     917                 :            : }
     918                 :            : 
     919                 :            : static gboolean
     920                 :          1 : g_resource_file_input_stream_close (GInputStream  *stream,
     921                 :            :                                     GCancellable  *cancellable,
     922                 :            :                                     GError       **error)
     923                 :            : {
     924                 :          1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     925                 :          1 :   return g_input_stream_close (file->stream,
     926                 :            :                                cancellable, error);
     927                 :            : }
     928                 :            : 
     929                 :            : 
     930                 :            : static goffset
     931                 :          1 : g_resource_file_input_stream_tell (GFileInputStream *stream)
     932                 :            : {
     933                 :          1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     934                 :            : 
     935   [ -  +  +  -  :          1 :   if (!G_IS_SEEKABLE (file->stream))
             -  +  -  + ]
     936                 :          0 :       return 0;
     937                 :            : 
     938                 :          1 :   return g_seekable_tell (G_SEEKABLE (file->stream));
     939                 :            : }
     940                 :            : 
     941                 :            : static gboolean
     942                 :          1 : g_resource_file_input_stream_can_seek (GFileInputStream *stream)
     943                 :            : {
     944                 :          1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     945                 :            : 
     946   [ -  +  +  -  :          1 :   return G_IS_SEEKABLE (file->stream) && g_seekable_can_seek (G_SEEKABLE (file->stream));
          -  +  +  -  +  
                      - ]
     947                 :            : }
     948                 :            : 
     949                 :            : static gboolean
     950                 :          1 : g_resource_file_input_stream_seek (GFileInputStream  *stream,
     951                 :            :                                    goffset            offset,
     952                 :            :                                    GSeekType          type,
     953                 :            :                                    GCancellable      *cancellable,
     954                 :            :                                    GError           **error)
     955                 :            : {
     956                 :          1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     957                 :            : 
     958   [ -  +  +  -  :          1 :   if (!G_IS_SEEKABLE (file->stream))
             -  +  -  + ]
     959                 :            :     {
     960                 :          0 :       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     961                 :            :                            _("Input stream doesn’t implement seek"));
     962                 :          0 :       return FALSE;
     963                 :            :     }
     964                 :            : 
     965                 :          1 :   return g_seekable_seek (G_SEEKABLE (file->stream),
     966                 :            :                           offset, type, cancellable, error);
     967                 :            : }
     968                 :            : 
     969                 :            : static GFileInfo *
     970                 :          1 : g_resource_file_input_stream_query_info (GFileInputStream  *stream,
     971                 :            :                                          const char        *attributes,
     972                 :            :                                          GCancellable      *cancellable,
     973                 :            :                                          GError           **error)
     974                 :            : {
     975                 :          1 :   GResourceFileInputStream *file = G_RESOURCE_FILE_INPUT_STREAM (stream);
     976                 :            : 
     977                 :          1 :   return g_file_query_info (file->file, attributes, 0, cancellable, error);
     978                 :            : }

Generated by: LCOV version 1.14