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