Imported Upstream version 2.66.6
[platform/upstream/glib.git] / gio / gresource.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2011 Red Hat, Inc
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Authors: Alexander Larsson <alexl@redhat.com>
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include "gresource.h"
26 #include <gvdb/gvdb-reader.h>
27 #include <gi18n-lib.h>
28 #include <gstdio.h>
29 #include <gio/gfile.h>
30 #include <gio/gioerror.h>
31 #include <gio/gmemoryinputstream.h>
32 #include <gio/gzlibdecompressor.h>
33 #include <gio/gconverterinputstream.h>
34
35 #include "glib-private.h"
36
37 struct _GResource
38 {
39   int ref_count;
40
41   GvdbTable *table;
42 };
43
44 static void register_lazy_static_resources (void);
45
46 G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
47
48 /**
49  * SECTION:gresource
50  * @short_description: Resource framework
51  * @include: gio/gio.h
52  *
53  * Applications and libraries often contain binary or textual data that is
54  * really part of the application, rather than user data. For instance
55  * #GtkBuilder .ui files, splashscreen images, GMenu markup XML, CSS files,
56  * icons, etc. These are often shipped as files in `$datadir/appname`, or
57  * manually included as literal strings in the code.
58  *
59  * The #GResource API and the [glib-compile-resources][glib-compile-resources] program
60  * provide a convenient and efficient alternative to this which has some nice properties. You
61  * maintain the files as normal files, so its easy to edit them, but during the build the files
62  * are combined into a binary bundle that is linked into the executable. This means that loading
63  * the resource files are efficient (as they are already in memory, shared with other instances) and
64  * simple (no need to check for things like I/O errors or locate the files in the filesystem). It
65  * also makes it easier to create relocatable applications.
66  *
67  * Resource files can also be marked as compressed. Such files will be included in the resource bundle
68  * in a compressed form, but will be automatically uncompressed when the resource is used. This
69  * is very useful e.g. for larger text files that are parsed once (or rarely) and then thrown away.
70  *
71  * Resource files can also be marked to be preprocessed, by setting the value of the
72  * `preprocess` attribute to a comma-separated list of preprocessing options.
73  * The only options currently supported are:
74  *
75  * `xml-stripblanks` which will use the xmllint command
76  * to strip ignorable whitespace from the XML file. For this to work,
77  * the `XMLLINT` environment variable must be set to the full path to
78  * the xmllint executable, or xmllint must be in the `PATH`; otherwise
79  * the preprocessing step is skipped.
80  *
81  * `to-pixdata` which will use the gdk-pixbuf-pixdata command to convert
82  * images to the GdkPixdata format, which allows you to create pixbufs directly using the data inside
83  * the resource file, rather than an (uncompressed) copy of it. For this, the gdk-pixbuf-pixdata
84  * program must be in the PATH, or the `GDK_PIXBUF_PIXDATA` environment variable must be
85  * set to the full path to the gdk-pixbuf-pixdata executable; otherwise the resource compiler will
86  * abort.
87  *
88  * `json-stripblanks` which will use the `json-glib-format` command to strip
89  * ignorable whitespace from the JSON file. For this to work, the
90  * `JSON_GLIB_FORMAT` environment variable must be set to the full path to the
91  * `json-glib-format` executable, or it must be in the `PATH`;
92  * otherwise the preprocessing step is skipped. In addition, at least version
93  * 1.6 of `json-glib-format` is required.
94  *
95  * Resource files will be exported in the GResource namespace using the
96  * combination of the given `prefix` and the filename from the `file` element.
97  * The `alias` attribute can be used to alter the filename to expose them at a
98  * different location in the resource namespace. Typically, this is used to
99  * include files from a different source directory without exposing the source
100  * directory in the resource namespace, as in the example below.
101  *
102  * Resource bundles are created by the [glib-compile-resources][glib-compile-resources] program
103  * which takes an XML file that describes the bundle, and a set of files that the XML references. These
104  * are combined into a binary resource bundle.
105  *
106  * An example resource description:
107  * |[
108  * <?xml version="1.0" encoding="UTF-8"?>
109  * <gresources>
110  *   <gresource prefix="/org/gtk/Example">
111  *     <file>data/splashscreen.png</file>
112  *     <file compressed="true">dialog.ui</file>
113  *     <file preprocess="xml-stripblanks">menumarkup.xml</file>
114  *     <file alias="example.css">data/example.css</file>
115  *   </gresource>
116  * </gresources>
117  * ]|
118  *
119  * This will create a resource bundle with the following files:
120  * |[
121  * /org/gtk/Example/data/splashscreen.png
122  * /org/gtk/Example/dialog.ui
123  * /org/gtk/Example/menumarkup.xml
124  * /org/gtk/Example/example.css
125  * ]|
126  *
127  * Note that all resources in the process share the same namespace, so use Java-style
128  * path prefixes (like in the above example) to avoid conflicts.
129  *
130  * You can then use [glib-compile-resources][glib-compile-resources] to compile the XML to a
131  * binary bundle that you can load with g_resource_load(). However, its more common to use the --generate-source and
132  * --generate-header arguments to create a source file and header to link directly into your application.
133  * This will generate `get_resource()`, `register_resource()` and
134  * `unregister_resource()` functions, prefixed by the `--c-name` argument passed
135  * to [glib-compile-resources][glib-compile-resources]. `get_resource()` returns
136  * the generated #GResource object. The register and unregister functions
137  * register the resource so its files can be accessed using
138  * g_resources_lookup_data().
139  *
140  * Once a #GResource has been created and registered all the data in it can be accessed globally in the process by
141  * using API calls like g_resources_open_stream() to stream the data or g_resources_lookup_data() to get a direct pointer
142  * to the data. You can also use URIs like "resource:///org/gtk/Example/data/splashscreen.png" with #GFile to access
143  * the resource data.
144  *
145  * Some higher-level APIs, such as #GtkApplication, will automatically load
146  * resources from certain well-known paths in the resource namespace as a
147  * convenience. See the documentation for those APIs for details.
148  *
149  * There are two forms of the generated source, the default version uses the compiler support for constructor
150  * and destructor functions (where available) to automatically create and register the #GResource on startup
151  * or library load time. If you pass `--manual-register`, two functions to register/unregister the resource are created
152  * instead. This requires an explicit initialization call in your application/library, but it works on all platforms,
153  * even on the minor ones where constructors are not supported. (Constructor support is available for at least Win32, Mac OS and Linux.)
154  *
155  * Note that resource data can point directly into the data segment of e.g. a library, so if you are unloading libraries
156  * during runtime you need to be very careful with keeping around pointers to data from a resource, as this goes away
157  * when the library is unloaded. However, in practice this is not generally a problem, since most resource accesses
158  * are for your own resources, and resource data is often used once, during parsing, and then released.
159  *
160  * When debugging a program or testing a change to an installed version, it is often useful to be able to
161  * replace resources in the program or library, without recompiling, for debugging or quick hacking and testing
162  * purposes. Since GLib 2.50, it is possible to use the `G_RESOURCE_OVERLAYS` environment variable to selectively overlay
163  * resources with replacements from the filesystem.  It is a %G_SEARCHPATH_SEPARATOR-separated list of substitutions to perform
164  * during resource lookups. It is ignored when running in a setuid process.
165  *
166  * A substitution has the form
167  *
168  * |[
169  *    /org/gtk/libgtk=/home/desrt/gtk-overlay
170  * ]|
171  *
172  * The part before the `=` is the resource subpath for which the overlay applies.  The part after is a
173  * filesystem path which contains files and subdirectories as you would like to be loaded as resources with the
174  * equivalent names.
175  *
176  * In the example above, if an application tried to load a resource with the resource path
177  * `/org/gtk/libgtk/ui/gtkdialog.ui` then GResource would check the filesystem path
178  * `/home/desrt/gtk-overlay/ui/gtkdialog.ui`.  If a file was found there, it would be used instead.  This is an
179  * overlay, not an outright replacement, which means that if a file is not found at that path, the built-in
180  * version will be used instead.  Whiteouts are not currently supported.
181  *
182  * Substitutions must start with a slash, and must not contain a trailing slash before the '='.  The path after
183  * the slash should ideally be absolute, but this is not strictly required.  It is possible to overlay the
184  * location of a single resource with an individual file.
185  *
186  * Since: 2.32
187  */
188
189 /**
190  * GStaticResource:
191  *
192  * #GStaticResource is an opaque data structure and can only be accessed
193  * using the following functions.
194  **/
195 typedef gboolean (* CheckCandidate) (const gchar *candidate, gpointer user_data);
196
197 static gboolean
198 open_overlay_stream (const gchar *candidate,
199                      gpointer     user_data)
200 {
201   GInputStream **res = (GInputStream **) user_data;
202   GError *error = NULL;
203   GFile *file;
204
205   file = g_file_new_for_path (candidate);
206   *res = (GInputStream *) g_file_read (file, NULL, &error);
207
208   if (*res)
209     {
210       g_message ("Opened file '%s' as a resource overlay", candidate);
211     }
212   else
213     {
214       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
215         g_warning ("Can't open overlay file '%s': %s", candidate, error->message);
216       g_error_free (error);
217     }
218
219   g_object_unref (file);
220
221   return *res != NULL;
222 }
223
224 static gboolean
225 get_overlay_bytes (const gchar *candidate,
226                    gpointer     user_data)
227 {
228   GBytes **res = (GBytes **) user_data;
229   GMappedFile *mapped_file;
230   GError *error = NULL;
231
232   mapped_file = g_mapped_file_new (candidate, FALSE, &error);
233
234   if (mapped_file)
235     {
236       g_message ("Mapped file '%s' as a resource overlay", candidate);
237       *res = g_mapped_file_get_bytes (mapped_file);
238       g_mapped_file_unref (mapped_file);
239     }
240   else
241     {
242       if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
243         g_warning ("Can't mmap overlay file '%s': %s", candidate, error->message);
244       g_error_free (error);
245     }
246
247   return *res != NULL;
248 }
249
250 static gboolean
251 enumerate_overlay_dir (const gchar *candidate,
252                        gpointer     user_data)
253 {
254   GHashTable **hash = (GHashTable **) user_data;
255   GError *error = NULL;
256   GDir *dir;
257   const gchar *name;
258
259   dir = g_dir_open (candidate, 0, &error);
260   if (dir)
261     {
262       if (*hash == NULL)
263         /* note: keep in sync with same line below */
264         *hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
265
266       g_message ("Enumerating directory '%s' as resource overlay", candidate);
267
268       while ((name = g_dir_read_name (dir)))
269         {
270           gchar *fullname = g_build_filename (candidate, name, NULL);
271
272           /* match gvdb behaviour by suffixing "/" on dirs */
273           if (g_file_test (fullname, G_FILE_TEST_IS_DIR))
274             g_hash_table_add (*hash, g_strconcat (name, "/", NULL));
275           else
276             g_hash_table_add (*hash, g_strdup (name));
277
278           g_free (fullname);
279         }
280
281       g_dir_close (dir);
282     }
283   else
284     {
285       if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
286         g_warning ("Can't enumerate overlay directory '%s': %s", candidate, error->message);
287       g_error_free (error);
288       return FALSE;
289     }
290
291   /* We may want to enumerate results from more than one overlay
292    * directory.
293    */
294   return FALSE;
295 }
296
297 typedef struct {
298   gsize size;
299   guint32 flags;
300 } InfoData;
301
302 static gboolean
303 get_overlay_info (const gchar *candidate,
304                   gpointer     user_data)
305 {
306   InfoData *info = user_data;
307   GStatBuf buf;
308
309   if (g_stat (candidate, &buf) < 0)
310     return FALSE;
311
312   info->size = buf.st_size;
313   info->flags = G_RESOURCE_FLAGS_NONE;
314
315   return TRUE;
316 }
317
318 static gboolean
319 g_resource_find_overlay (const gchar    *path,
320                          CheckCandidate  check,
321                          gpointer        user_data)
322 {
323   /* This is a null-terminated array of replacement strings (with '=' inside) */
324   static const gchar * const *overlay_dirs;
325   gboolean res = FALSE;
326   gint path_len = -1;
327   gint i;
328
329   /* We try to be very fast in case there are no overlays.  Otherwise,
330    * we can take a bit more time...
331    */
332
333   if (g_once_init_enter (&overlay_dirs))
334     {
335       gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
336       const gchar * const *result;
337       const gchar *envvar;
338
339       /* Don’t load overlays if setuid, as they could allow reading privileged
340        * files. */
341       envvar = !is_setuid ? g_getenv ("G_RESOURCE_OVERLAYS") : NULL;
342       if (envvar != NULL)
343         {
344           gchar **parts;
345           gint i, j;
346
347           parts = g_strsplit (envvar, G_SEARCHPATH_SEPARATOR_S, 0);
348
349           /* Sanity check the parts, dropping those that are invalid.
350            * 'i' may grow faster than 'j'.
351            */
352           for (i = j = 0; parts[i]; i++)
353             {
354               gchar *part = parts[i];
355               gchar *eq;
356
357               eq = strchr (part, '=');
358               if (eq == NULL)
359                 {
360                   g_critical ("G_RESOURCE_OVERLAYS segment '%s' lacks '='.  Ignoring.", part);
361                   g_free (part);
362                   continue;
363                 }
364
365               if (eq == part)
366                 {
367                   g_critical ("G_RESOURCE_OVERLAYS segment '%s' lacks path before '='.  Ignoring.", part);
368                   g_free (part);
369                   continue;
370                 }
371
372               if (eq[1] == '\0')
373                 {
374                   g_critical ("G_RESOURCE_OVERLAYS segment '%s' lacks path after '='.  Ignoring", part);
375                   g_free (part);
376                   continue;
377                 }
378
379               if (part[0] != '/')
380                 {
381                   g_critical ("G_RESOURCE_OVERLAYS segment '%s' lacks leading '/'.  Ignoring.", part);
382                   g_free (part);
383                   continue;
384                 }
385
386               if (eq[-1] == '/')
387                 {
388                   g_critical ("G_RESOURCE_OVERLAYS segment '%s' has trailing '/' before '='.  Ignoring", part);
389                   g_free (part);
390                   continue;
391                 }
392
393               if (!g_path_is_absolute (eq + 1))
394                 {
395                   g_critical ("G_RESOURCE_OVERLAYS segment '%s' does not have an absolute path after '='.  Ignoring", part);
396                   g_free (part);
397                   continue;
398                 }
399
400               g_message ("Adding GResources overlay '%s'", part);
401               parts[j++] = part;
402             }
403
404           parts[j] = NULL;
405
406           result = (const gchar **) parts;
407         }
408       else
409         {
410           /* We go out of the way to avoid malloc() in the normal case
411            * where the environment variable is not set.
412            */
413           static const gchar * const empty_strv[0 + 1];
414           result = empty_strv;
415         }
416
417       g_once_init_leave (&overlay_dirs, result);
418     }
419
420   for (i = 0; overlay_dirs[i]; i++)
421     {
422       const gchar *src;
423       gint src_len;
424       const gchar *dst;
425       gint dst_len;
426       gchar *candidate;
427
428       {
429         gchar *eq;
430
431         /* split the overlay into src/dst */
432         src = overlay_dirs[i];
433         eq = strchr (src, '=');
434         g_assert (eq); /* we checked this already */
435         src_len = eq - src;
436         dst = eq + 1;
437         /* hold off on dst_len because we will probably fail the checks below */
438       }
439
440       if (path_len == -1)
441         path_len = strlen (path);
442
443       /* The entire path is too short to match the source */
444       if (path_len < src_len)
445         continue;
446
447       /* It doesn't match the source */
448       if (memcmp (path, src, src_len) != 0)
449         continue;
450
451       /* The prefix matches, but it's not a complete path component */
452       if (path[src_len] && path[src_len] != '/')
453         continue;
454
455       /* OK.  Now we need this. */
456       dst_len = strlen (dst);
457
458       /* The candidate will be composed of:
459        *
460        *    dst + remaining_path + nul
461        */
462       candidate = g_malloc (dst_len + (path_len - src_len) + 1);
463       memcpy (candidate, dst, dst_len);
464       memcpy (candidate + dst_len, path + src_len, path_len - src_len);
465       candidate[dst_len + (path_len - src_len)] = '\0';
466
467       /* No matter what, 'r' is what we need, including the case where
468        * we are trying to enumerate a directory.
469        */
470       res = (* check) (candidate, user_data);
471       g_free (candidate);
472
473       if (res)
474         break;
475     }
476
477   return res;
478 }
479
480 /**
481  * g_resource_error_quark:
482  *
483  * Gets the #GResource Error Quark.
484  *
485  * Returns: a #GQuark
486  *
487  * Since: 2.32
488  */
489 G_DEFINE_QUARK (g-resource-error-quark, g_resource_error)
490
491 /**
492  * g_resource_ref:
493  * @resource: A #GResource
494  *
495  * Atomically increments the reference count of @resource by one. This
496  * function is MT-safe and may be called from any thread.
497  *
498  * Returns: The passed in #GResource
499  *
500  * Since: 2.32
501  **/
502 GResource *
503 g_resource_ref (GResource *resource)
504 {
505   g_atomic_int_inc (&resource->ref_count);
506   return resource;
507 }
508
509 /**
510  * g_resource_unref:
511  * @resource: A #GResource
512  *
513  * Atomically decrements the reference count of @resource by one. If the
514  * reference count drops to 0, all memory allocated by the resource is
515  * released. This function is MT-safe and may be called from any
516  * thread.
517  *
518  * Since: 2.32
519  **/
520 void
521 g_resource_unref (GResource *resource)
522 {
523   if (g_atomic_int_dec_and_test (&resource->ref_count))
524     {
525       gvdb_table_free (resource->table);
526       g_free (resource);
527     }
528 }
529
530 /*< internal >
531  * g_resource_new_from_table:
532  * @table: (transfer full): a GvdbTable
533  *
534  * Returns: (transfer full): a new #GResource for @table
535  */
536 static GResource *
537 g_resource_new_from_table (GvdbTable *table)
538 {
539   GResource *resource;
540
541   resource = g_new (GResource, 1);
542   resource->ref_count = 1;
543   resource->table = table;
544
545   return resource;
546 }
547
548 static void
549 g_resource_error_from_gvdb_table_error (GError **g_resource_error,
550                                         GError  *gvdb_table_error  /* (transfer full) */)
551 {
552   if (g_error_matches (gvdb_table_error, G_FILE_ERROR, G_FILE_ERROR_INVAL))
553     g_set_error_literal (g_resource_error,
554                          G_RESOURCE_ERROR, G_RESOURCE_ERROR_INTERNAL,
555                          gvdb_table_error->message);
556   else
557     g_propagate_error (g_resource_error, g_steal_pointer (&gvdb_table_error));
558   g_clear_error (&gvdb_table_error);
559 }
560
561 /**
562  * g_resource_new_from_data:
563  * @data: A #GBytes
564  * @error: return location for a #GError, or %NULL
565  *
566  * Creates a GResource from a reference to the binary resource bundle.
567  * This will keep a reference to @data while the resource lives, so
568  * the data should not be modified or freed.
569  *
570  * If you want to use this resource in the global resource namespace you need
571  * to register it with g_resources_register().
572  *
573  * Note: @data must be backed by memory that is at least pointer aligned.
574  * Otherwise this function will internally create a copy of the memory since
575  * GLib 2.56, or in older versions fail and exit the process.
576  *
577  * If @data is empty or corrupt, %G_RESOURCE_ERROR_INTERNAL will be returned.
578  *
579  * Returns: (transfer full): a new #GResource, or %NULL on error
580  *
581  * Since: 2.32
582  **/
583 GResource *
584 g_resource_new_from_data (GBytes  *data,
585                           GError **error)
586 {
587   GvdbTable *table;
588   gboolean unref_data = FALSE;
589   GError *local_error = NULL;
590
591   if (((guintptr) g_bytes_get_data (data, NULL)) % sizeof (gpointer) != 0)
592     {
593       data = g_bytes_new (g_bytes_get_data (data, NULL),
594                           g_bytes_get_size (data));
595       unref_data = TRUE;
596     }
597
598   table = gvdb_table_new_from_bytes (data, TRUE, &local_error);
599
600   if (unref_data)
601     g_bytes_unref (data);
602
603   if (table == NULL)
604     {
605       g_resource_error_from_gvdb_table_error (error, g_steal_pointer (&local_error));
606       return NULL;
607     }
608
609   return g_resource_new_from_table (table);
610 }
611
612 /**
613  * g_resource_load:
614  * @filename: (type filename): the path of a filename to load, in the GLib filename encoding
615  * @error: return location for a #GError, or %NULL
616  *
617  * Loads a binary resource bundle and creates a #GResource representation of it, allowing
618  * you to query it for data.
619  *
620  * If you want to use this resource in the global resource namespace you need
621  * to register it with g_resources_register().
622  *
623  * If @filename is empty or the data in it is corrupt,
624  * %G_RESOURCE_ERROR_INTERNAL will be returned. If @filename doesn’t exist, or
625  * there is an error in reading it, an error from g_mapped_file_new() will be
626  * returned.
627  *
628  * Returns: (transfer full): a new #GResource, or %NULL on error
629  *
630  * Since: 2.32
631  **/
632 GResource *
633 g_resource_load (const gchar  *filename,
634                  GError      **error)
635 {
636   GvdbTable *table;
637   GError *local_error = NULL;
638
639   table = gvdb_table_new (filename, FALSE, &local_error);
640   if (table == NULL)
641     {
642       g_resource_error_from_gvdb_table_error (error, g_steal_pointer (&local_error));
643       return NULL;
644     }
645
646   return g_resource_new_from_table (table);
647 }
648
649 static gboolean
650 do_lookup (GResource             *resource,
651            const gchar           *path,
652            GResourceLookupFlags   lookup_flags,
653            gsize                 *size,
654            guint32               *flags,
655            const void           **data,
656            gsize                 *data_size,
657            GError               **error)
658 {
659   char *free_path = NULL;
660   gsize path_len;
661   gboolean res = FALSE;
662   GVariant *value;
663
664   /* Drop any trailing slash. */
665   path_len = strlen (path);
666   if (path_len >= 1 && path[path_len-1] == '/')
667     {
668       path = free_path = g_strdup (path);
669       free_path[path_len-1] = 0;
670     }
671
672   value = gvdb_table_get_raw_value (resource->table, path);
673
674   if (value == NULL)
675     {
676       g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND,
677                    _("The resource at “%s” does not exist"),
678                    path);
679     }
680   else
681     {
682       guint32 _size, _flags;
683       GVariant *array;
684
685       g_variant_get (value, "(uu@ay)",
686                      &_size,
687                      &_flags,
688                      &array);
689
690       _size = GUINT32_FROM_LE (_size);
691       _flags = GUINT32_FROM_LE (_flags);
692
693       if (size)
694         *size = _size;
695       if (flags)
696         *flags = _flags;
697       if (data)
698         *data = g_variant_get_data (array);
699       if (data_size)
700         {
701           /* Don't report trailing newline that non-compressed files has */
702           if (_flags & G_RESOURCE_FLAGS_COMPRESSED)
703             *data_size = g_variant_get_size (array);
704           else
705             *data_size = g_variant_get_size (array) - 1;
706         }
707       g_variant_unref (array);
708       g_variant_unref (value);
709
710       res = TRUE;
711     }
712
713   g_free (free_path);
714   return res;
715 }
716
717 /**
718  * g_resource_open_stream:
719  * @resource: A #GResource
720  * @path: A pathname inside the resource
721  * @lookup_flags: A #GResourceLookupFlags
722  * @error: return location for a #GError, or %NULL
723  *
724  * Looks for a file at the specified @path in the resource and
725  * returns a #GInputStream that lets you read the data.
726  *
727  * @lookup_flags controls the behaviour of the lookup.
728  *
729  * Returns: (transfer full): #GInputStream or %NULL on error.
730  *     Free the returned object with g_object_unref()
731  *
732  * Since: 2.32
733  **/
734 GInputStream *
735 g_resource_open_stream (GResource             *resource,
736                         const gchar           *path,
737                         GResourceLookupFlags   lookup_flags,
738                         GError               **error)
739 {
740   const void *data;
741   gsize data_size;
742   guint32 flags;
743   GInputStream *stream, *stream2;
744
745   if (!do_lookup (resource, path, lookup_flags, NULL, &flags, &data, &data_size, error))
746     return NULL;
747
748   stream = g_memory_input_stream_new_from_data (data, data_size, NULL);
749   g_object_set_data_full (G_OBJECT (stream), "g-resource",
750                           g_resource_ref (resource),
751                           (GDestroyNotify)g_resource_unref);
752
753   if (flags & G_RESOURCE_FLAGS_COMPRESSED)
754     {
755       GZlibDecompressor *decompressor =
756         g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_ZLIB);
757
758       stream2 = g_converter_input_stream_new (stream, G_CONVERTER (decompressor));
759       g_object_unref (decompressor);
760       g_object_unref (stream);
761       stream = stream2;
762     }
763
764   return stream;
765 }
766
767 /**
768  * g_resource_lookup_data:
769  * @resource: A #GResource
770  * @path: A pathname inside the resource
771  * @lookup_flags: A #GResourceLookupFlags
772  * @error: return location for a #GError, or %NULL
773  *
774  * Looks for a file at the specified @path in the resource and
775  * returns a #GBytes that lets you directly access the data in
776  * memory.
777  *
778  * The data is always followed by a zero byte, so you
779  * can safely use the data as a C string. However, that byte
780  * is not included in the size of the GBytes.
781  *
782  * For uncompressed resource files this is a pointer directly into
783  * the resource bundle, which is typically in some readonly data section
784  * in the program binary. For compressed files we allocate memory on
785  * the heap and automatically uncompress the data.
786  *
787  * @lookup_flags controls the behaviour of the lookup.
788  *
789  * Returns: (transfer full): #GBytes or %NULL on error.
790  *     Free the returned object with g_bytes_unref()
791  *
792  * Since: 2.32
793  **/
794 GBytes *
795 g_resource_lookup_data (GResource             *resource,
796                         const gchar           *path,
797                         GResourceLookupFlags   lookup_flags,
798                         GError               **error)
799 {
800   const void *data;
801   guint32 flags;
802   gsize data_size;
803   gsize size;
804
805   if (!do_lookup (resource, path, lookup_flags, &size, &flags, &data, &data_size, error))
806     return NULL;
807
808   if (flags & G_RESOURCE_FLAGS_COMPRESSED)
809     {
810       char *uncompressed, *d;
811       const char *s;
812       GConverterResult res;
813       gsize d_size, s_size;
814       gsize bytes_read, bytes_written;
815
816
817       GZlibDecompressor *decompressor =
818         g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_ZLIB);
819
820       uncompressed = g_malloc (size + 1);
821
822       s = data;
823       s_size = data_size;
824       d = uncompressed;
825       d_size = size;
826
827       do
828         {
829           res = g_converter_convert (G_CONVERTER (decompressor),
830                                      s, s_size,
831                                      d, d_size,
832                                      G_CONVERTER_INPUT_AT_END,
833                                      &bytes_read,
834                                      &bytes_written,
835                                      NULL);
836           if (res == G_CONVERTER_ERROR)
837             {
838               g_free (uncompressed);
839               g_object_unref (decompressor);
840
841               g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_INTERNAL,
842                            _("The resource at “%s” failed to decompress"),
843                            path);
844               return NULL;
845
846             }
847           s += bytes_read;
848           s_size -= bytes_read;
849           d += bytes_written;
850           d_size -= bytes_written;
851         }
852       while (res != G_CONVERTER_FINISHED);
853
854       uncompressed[size] = 0; /* Zero terminate */
855
856       g_object_unref (decompressor);
857
858       return g_bytes_new_take (uncompressed, size);
859     }
860   else
861     return g_bytes_new_with_free_func (data, data_size, (GDestroyNotify)g_resource_unref, g_resource_ref (resource));
862 }
863
864 /**
865  * g_resource_get_info:
866  * @resource: A #GResource
867  * @path: A pathname inside the resource
868  * @lookup_flags: A #GResourceLookupFlags
869  * @size:  (out) (optional): a location to place the length of the contents of the file,
870  *    or %NULL if the length is not needed
871  * @flags:  (out) (optional): a location to place the flags about the file,
872  *    or %NULL if the length is not needed
873  * @error: return location for a #GError, or %NULL
874  *
875  * Looks for a file at the specified @path in the resource and
876  * if found returns information about it.
877  *
878  * @lookup_flags controls the behaviour of the lookup.
879  *
880  * Returns: %TRUE if the file was found. %FALSE if there were errors
881  *
882  * Since: 2.32
883  **/
884 gboolean
885 g_resource_get_info (GResource             *resource,
886                      const gchar           *path,
887                      GResourceLookupFlags   lookup_flags,
888                      gsize                 *size,
889                      guint32               *flags,
890                      GError               **error)
891 {
892   return do_lookup (resource, path, lookup_flags, size, flags, NULL, NULL, error);
893 }
894
895 /**
896  * g_resource_enumerate_children:
897  * @resource: A #GResource
898  * @path: A pathname inside the resource
899  * @lookup_flags: A #GResourceLookupFlags
900  * @error: return location for a #GError, or %NULL
901  *
902  * Returns all the names of children at the specified @path in the resource.
903  * The return result is a %NULL terminated list of strings which should
904  * be released with g_strfreev().
905  *
906  * If @path is invalid or does not exist in the #GResource,
907  * %G_RESOURCE_ERROR_NOT_FOUND will be returned.
908  *
909  * @lookup_flags controls the behaviour of the lookup.
910  *
911  * Returns: (array zero-terminated=1) (transfer full): an array of constant strings
912  *
913  * Since: 2.32
914  **/
915 gchar **
916 g_resource_enumerate_children (GResource             *resource,
917                                const gchar           *path,
918                                GResourceLookupFlags   lookup_flags,
919                                GError               **error)
920 {
921   gchar local_str[256];
922   const gchar *path_with_slash;
923   gchar **children;
924   gchar *free_path = NULL;
925   gsize path_len;
926
927   /*
928    * Size of 256 is arbitrarily chosen based on being large enough
929    * for pretty much everything we come across, but not cumbersome
930    * on the stack. It also matches common cacheline sizes.
931    */
932
933   if (*path == 0)
934     {
935       g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND,
936                    _("The resource at “%s” does not exist"),
937                    path);
938       return NULL;
939     }
940
941   path_len = strlen (path);
942
943   if G_UNLIKELY (path[path_len-1] != '/')
944     {
945       if (path_len < sizeof (local_str) - 2)
946         {
947           /*
948            * We got a path that does not have a trailing /. It is not the
949            * ideal use of this API as we require trailing / for our lookup
950            * into gvdb. Some degenerate application configurations can hit
951            * this code path quite a bit, so we try to avoid using the
952            * g_strconcat()/g_free().
953            */
954           memcpy (local_str, path, path_len);
955           local_str[path_len] = '/';
956           local_str[path_len+1] = 0;
957           path_with_slash = local_str;
958         }
959       else
960         {
961           path_with_slash = free_path = g_strconcat (path, "/", NULL);
962         }
963     }
964   else
965     {
966       path_with_slash = path;
967     }
968
969   children = gvdb_table_list (resource->table, path_with_slash);
970   g_free (free_path);
971
972   if (children == NULL)
973     {
974       g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND,
975                    _("The resource at “%s” does not exist"),
976                    path);
977       return NULL;
978     }
979
980   return children;
981 }
982
983 static GRWLock resources_lock;
984 static GList *registered_resources;
985
986 /* This is updated atomically, so we can append to it and check for NULL outside the
987    lock, but all other accesses are done under the write lock */
988 static GStaticResource *lazy_register_resources;
989
990 static void
991 g_resources_register_unlocked (GResource *resource)
992 {
993   registered_resources = g_list_prepend (registered_resources, g_resource_ref (resource));
994 }
995
996 static void
997 g_resources_unregister_unlocked (GResource *resource)
998 {
999   if (g_list_find (registered_resources, resource) == NULL)
1000     {
1001       g_warning ("Tried to remove not registered resource");
1002     }
1003   else
1004     {
1005       registered_resources = g_list_remove (registered_resources, resource);
1006       g_resource_unref (resource);
1007     }
1008 }
1009
1010 /**
1011  * g_resources_register:
1012  * @resource: A #GResource
1013  *
1014  * Registers the resource with the process-global set of resources.
1015  * Once a resource is registered the files in it can be accessed
1016  * with the global resource lookup functions like g_resources_lookup_data().
1017  *
1018  * Since: 2.32
1019  **/
1020 void
1021 g_resources_register (GResource *resource)
1022 {
1023   g_rw_lock_writer_lock (&resources_lock);
1024   g_resources_register_unlocked (resource);
1025   g_rw_lock_writer_unlock (&resources_lock);
1026 }
1027
1028 /**
1029  * g_resources_unregister:
1030  * @resource: A #GResource
1031  *
1032  * Unregisters the resource from the process-global set of resources.
1033  *
1034  * Since: 2.32
1035  **/
1036 void
1037 g_resources_unregister (GResource *resource)
1038 {
1039   g_rw_lock_writer_lock (&resources_lock);
1040   g_resources_unregister_unlocked (resource);
1041   g_rw_lock_writer_unlock (&resources_lock);
1042 }
1043
1044 /**
1045  * g_resources_open_stream:
1046  * @path: A pathname inside the resource
1047  * @lookup_flags: A #GResourceLookupFlags
1048  * @error: return location for a #GError, or %NULL
1049  *
1050  * Looks for a file at the specified @path in the set of
1051  * globally registered resources and returns a #GInputStream
1052  * that lets you read the data.
1053  *
1054  * @lookup_flags controls the behaviour of the lookup.
1055  *
1056  * Returns: (transfer full): #GInputStream or %NULL on error.
1057  *     Free the returned object with g_object_unref()
1058  *
1059  * Since: 2.32
1060  **/
1061 GInputStream *
1062 g_resources_open_stream (const gchar           *path,
1063                          GResourceLookupFlags   lookup_flags,
1064                          GError               **error)
1065 {
1066   GInputStream *res = NULL;
1067   GList *l;
1068   GInputStream *stream;
1069
1070   if (g_resource_find_overlay (path, open_overlay_stream, &res))
1071     return res;
1072
1073   register_lazy_static_resources ();
1074
1075   g_rw_lock_reader_lock (&resources_lock);
1076
1077   for (l = registered_resources; l != NULL; l = l->next)
1078     {
1079       GResource *r = l->data;
1080       GError *my_error = NULL;
1081
1082       stream = g_resource_open_stream (r, path, lookup_flags, &my_error);
1083       if (stream == NULL &&
1084           g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
1085         {
1086           g_clear_error (&my_error);
1087         }
1088       else
1089         {
1090           if (stream == NULL)
1091             g_propagate_error (error, my_error);
1092           res = stream;
1093           break;
1094         }
1095     }
1096
1097   if (l == NULL)
1098     g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND,
1099                  _("The resource at “%s” does not exist"),
1100                  path);
1101
1102   g_rw_lock_reader_unlock (&resources_lock);
1103
1104   return res;
1105 }
1106
1107 /**
1108  * g_resources_lookup_data:
1109  * @path: A pathname inside the resource
1110  * @lookup_flags: A #GResourceLookupFlags
1111  * @error: return location for a #GError, or %NULL
1112  *
1113  * Looks for a file at the specified @path in the set of
1114  * globally registered resources and returns a #GBytes that
1115  * lets you directly access the data in memory.
1116  *
1117  * The data is always followed by a zero byte, so you
1118  * can safely use the data as a C string. However, that byte
1119  * is not included in the size of the GBytes.
1120  *
1121  * For uncompressed resource files this is a pointer directly into
1122  * the resource bundle, which is typically in some readonly data section
1123  * in the program binary. For compressed files we allocate memory on
1124  * the heap and automatically uncompress the data.
1125  *
1126  * @lookup_flags controls the behaviour of the lookup.
1127  *
1128  * Returns: (transfer full): #GBytes or %NULL on error.
1129  *     Free the returned object with g_bytes_unref()
1130  *
1131  * Since: 2.32
1132  **/
1133 GBytes *
1134 g_resources_lookup_data (const gchar           *path,
1135                          GResourceLookupFlags   lookup_flags,
1136                          GError               **error)
1137 {
1138   GBytes *res = NULL;
1139   GList *l;
1140   GBytes *data;
1141
1142   if (g_resource_find_overlay (path, get_overlay_bytes, &res))
1143     return res;
1144
1145   register_lazy_static_resources ();
1146
1147   g_rw_lock_reader_lock (&resources_lock);
1148
1149   for (l = registered_resources; l != NULL; l = l->next)
1150     {
1151       GResource *r = l->data;
1152       GError *my_error = NULL;
1153
1154       data = g_resource_lookup_data (r, path, lookup_flags, &my_error);
1155       if (data == NULL &&
1156           g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
1157         {
1158           g_clear_error (&my_error);
1159         }
1160       else
1161         {
1162           if (data == NULL)
1163             g_propagate_error (error, my_error);
1164           res = data;
1165           break;
1166         }
1167     }
1168
1169   if (l == NULL)
1170     g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND,
1171                  _("The resource at “%s” does not exist"),
1172                  path);
1173
1174   g_rw_lock_reader_unlock (&resources_lock);
1175
1176   return res;
1177 }
1178
1179 /**
1180  * g_resources_enumerate_children:
1181  * @path: A pathname inside the resource
1182  * @lookup_flags: A #GResourceLookupFlags
1183  * @error: return location for a #GError, or %NULL
1184  *
1185  * Returns all the names of children at the specified @path in the set of
1186  * globally registered resources.
1187  * The return result is a %NULL terminated list of strings which should
1188  * be released with g_strfreev().
1189  *
1190  * @lookup_flags controls the behaviour of the lookup.
1191  *
1192  * Returns: (array zero-terminated=1) (transfer full): an array of constant strings
1193  *
1194  * Since: 2.32
1195  **/
1196 gchar **
1197 g_resources_enumerate_children (const gchar           *path,
1198                                 GResourceLookupFlags   lookup_flags,
1199                                 GError               **error)
1200 {
1201   GHashTable *hash = NULL;
1202   GList *l;
1203   char **children;
1204   int i;
1205
1206   /* This will enumerate actual files found in overlay directories but
1207    * will not enumerate the overlays themselves.  For example, if we
1208    * have an overlay "/org/gtk=/path/to/files" and we enumerate "/org"
1209    * then we will not see "gtk" in the result set unless it is provided
1210    * by another resource file.
1211    *
1212    * This is probably not going to be a problem since if we are doing
1213    * such an overlay, we probably will already have that path.
1214    */
1215   g_resource_find_overlay (path, enumerate_overlay_dir, &hash);
1216
1217   register_lazy_static_resources ();
1218
1219   g_rw_lock_reader_lock (&resources_lock);
1220
1221   for (l = registered_resources; l != NULL; l = l->next)
1222     {
1223       GResource *r = l->data;
1224
1225       children = g_resource_enumerate_children (r, path, 0, NULL);
1226
1227       if (children != NULL)
1228         {
1229           if (hash == NULL)
1230             /* note: keep in sync with same line above */
1231             hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1232
1233           for (i = 0; children[i] != NULL; i++)
1234             g_hash_table_add (hash, children[i]);
1235           g_free (children);
1236         }
1237     }
1238
1239   g_rw_lock_reader_unlock (&resources_lock);
1240
1241   if (hash == NULL)
1242     {
1243       g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND,
1244                    _("The resource at “%s” does not exist"),
1245                    path);
1246       return NULL;
1247     }
1248   else
1249     {
1250       children = (gchar **) g_hash_table_get_keys_as_array (hash, NULL);
1251       g_hash_table_steal_all (hash);
1252       g_hash_table_destroy (hash);
1253
1254       return children;
1255     }
1256 }
1257
1258 /**
1259  * g_resources_get_info:
1260  * @path: A pathname inside the resource
1261  * @lookup_flags: A #GResourceLookupFlags
1262  * @size:  (out) (optional): a location to place the length of the contents of the file,
1263  *    or %NULL if the length is not needed
1264  * @flags:  (out) (optional): a location to place the #GResourceFlags about the file,
1265  *    or %NULL if the flags are not needed
1266  * @error: return location for a #GError, or %NULL
1267  *
1268  * Looks for a file at the specified @path in the set of
1269  * globally registered resources and if found returns information about it.
1270  *
1271  * @lookup_flags controls the behaviour of the lookup.
1272  *
1273  * Returns: %TRUE if the file was found. %FALSE if there were errors
1274  *
1275  * Since: 2.32
1276  **/
1277 gboolean
1278 g_resources_get_info (const gchar           *path,
1279                       GResourceLookupFlags   lookup_flags,
1280                       gsize                 *size,
1281                       guint32               *flags,
1282                       GError               **error)
1283 {
1284   gboolean res = FALSE;
1285   GList *l;
1286   gboolean r_res;
1287   InfoData info;
1288
1289   if (g_resource_find_overlay (path, get_overlay_info, &info))
1290     {
1291       if (size)
1292         *size = info.size;
1293       if (flags)
1294         *flags = info.flags;
1295
1296       return TRUE;
1297     }
1298
1299   register_lazy_static_resources ();
1300
1301   g_rw_lock_reader_lock (&resources_lock);
1302
1303   for (l = registered_resources; l != NULL; l = l->next)
1304     {
1305       GResource *r = l->data;
1306       GError *my_error = NULL;
1307
1308       r_res = g_resource_get_info (r, path, lookup_flags, size, flags, &my_error);
1309       if (!r_res &&
1310           g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
1311         {
1312           g_clear_error (&my_error);
1313         }
1314       else
1315         {
1316           if (!r_res)
1317             g_propagate_error (error, my_error);
1318           res = r_res;
1319           break;
1320         }
1321     }
1322
1323   if (l == NULL)
1324     g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND,
1325                  _("The resource at “%s” does not exist"),
1326                  path);
1327
1328   g_rw_lock_reader_unlock (&resources_lock);
1329
1330   return res;
1331 }
1332
1333 /* This code is to handle registration of resources very early, from a constructor.
1334  * At that point we'd like to do minimal work, to avoid ordering issues. For instance,
1335  * we're not allowed to use g_malloc, as the user need to be able to call g_mem_set_vtable
1336  * before the first call to g_malloc.
1337  *
1338  * So, what we do at construction time is that we just register a static structure on
1339  * a list of resources that need to be initialized, and then later, when doing any lookups
1340  * in the global list of registered resources, or when getting a reference to the
1341  * lazily initialized resource we lazily create and register all the GResources on
1342  * the lazy list.
1343  *
1344  * To avoid having to use locks in the constructor, and having to grab the writer lock
1345  * when checking the lazy registering list we update lazy_register_resources in
1346  * a lock-less fashion (atomic prepend-only, atomic replace with NULL). However, all
1347  * operations except:
1348  *  * check if there are any resources to lazily initialize
1349  *  * Add a static resource to the lazy init list
1350  * Do use the full writer lock for protection.
1351  */
1352
1353 static void
1354 register_lazy_static_resources_unlocked (void)
1355 {
1356   GStaticResource *list;
1357
1358   do
1359     list = lazy_register_resources;
1360   while (!g_atomic_pointer_compare_and_exchange (&lazy_register_resources, list, NULL));
1361
1362   while (list != NULL)
1363     {
1364       GBytes *bytes = g_bytes_new_static (list->data, list->data_len);
1365       GResource *resource = g_resource_new_from_data (bytes, NULL);
1366       if (resource)
1367         {
1368           g_resources_register_unlocked (resource);
1369           g_atomic_pointer_set (&list->resource, resource);
1370         }
1371       g_bytes_unref (bytes);
1372
1373       list = list->next;
1374     }
1375 }
1376
1377 static void
1378 register_lazy_static_resources (void)
1379 {
1380   if (g_atomic_pointer_get (&lazy_register_resources) == NULL)
1381     return;
1382
1383   g_rw_lock_writer_lock (&resources_lock);
1384   register_lazy_static_resources_unlocked ();
1385   g_rw_lock_writer_unlock (&resources_lock);
1386 }
1387
1388 /**
1389  * g_static_resource_init:
1390  * @static_resource: pointer to a static #GStaticResource
1391  *
1392  * Initializes a GResource from static data using a
1393  * GStaticResource.
1394  *
1395  * This is normally used by code generated by
1396  * [glib-compile-resources][glib-compile-resources]
1397  * and is not typically used by other code.
1398  *
1399  * Since: 2.32
1400  **/
1401 void
1402 g_static_resource_init (GStaticResource *static_resource)
1403 {
1404   gpointer next;
1405
1406   do
1407     {
1408       next = lazy_register_resources;
1409       static_resource->next = next;
1410     }
1411   while (!g_atomic_pointer_compare_and_exchange (&lazy_register_resources, next, static_resource));
1412 }
1413
1414 /**
1415  * g_static_resource_fini:
1416  * @static_resource: pointer to a static #GStaticResource
1417  *
1418  * Finalized a GResource initialized by g_static_resource_init().
1419  *
1420  * This is normally used by code generated by
1421  * [glib-compile-resources][glib-compile-resources]
1422  * and is not typically used by other code.
1423  *
1424  * Since: 2.32
1425  **/
1426 void
1427 g_static_resource_fini (GStaticResource *static_resource)
1428 {
1429   GResource *resource;
1430
1431   g_rw_lock_writer_lock (&resources_lock);
1432
1433   register_lazy_static_resources_unlocked ();
1434
1435   resource = g_atomic_pointer_get (&static_resource->resource);
1436   if (resource)
1437     {
1438       g_atomic_pointer_set (&static_resource->resource, NULL);
1439       g_resources_unregister_unlocked (resource);
1440       g_resource_unref (resource);
1441     }
1442
1443   g_rw_lock_writer_unlock (&resources_lock);
1444 }
1445
1446 /**
1447  * g_static_resource_get_resource:
1448  * @static_resource: pointer to a static #GStaticResource
1449  *
1450  * Gets the GResource that was registered by a call to g_static_resource_init().
1451  *
1452  * This is normally used by code generated by
1453  * [glib-compile-resources][glib-compile-resources]
1454  * and is not typically used by other code.
1455  *
1456  * Returns:  (transfer none): a #GResource
1457  *
1458  * Since: 2.32
1459  **/
1460 GResource *
1461 g_static_resource_get_resource (GStaticResource *static_resource)
1462 {
1463   register_lazy_static_resources ();
1464
1465   return g_atomic_pointer_get (&static_resource->resource);
1466 }