[gdk-pixbuf] windows: rework loaders cache relocation support
- From: Christoph Reiter <creiter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdk-pixbuf] windows: rework loaders cache relocation support
- Date: Tue, 24 Apr 2018 10:35:34 +0000 (UTC)
commit 6ef31828dd5f58491fb7a20e5258cb0c3f42b170
Author: Christoph Reiter <creiter src gnome org>
Date: Tue Dec 13 20:43:10 2016 +0100
windows: rework loaders cache relocation support
Relocation works by recognizing paths in the loaders cache
which start with the built time prefix and extract the relative
path from that.
This leads to the following problem when updating the cache:
In case the package is build on another machine one has to
either match the build directory layout or adjust the
cache by hand for the resulting cache to stay relocatable.
This commonly occurs with msys2 where mostly pre-build packages
are used which are built on another machine and the cache gets
generated at install time. Another case is updating the cache
in a separate deployment environment.
This patch takes the package installation directory as a base
and writes relative paths into the cache when relocation
is enabled. When loading the cache a relative path is made
absolute by prepending the package base again.
https://bugzilla.gnome.org/show_bug.cgi?id=776081
gdk-pixbuf/gdk-pixbuf-io.c | 43 ++++++++---------------
gdk-pixbuf/queryloaders.c | 79 +++++++++++++++++++++++++++++++++++++-------
2 files changed, 82 insertions(+), 40 deletions(-)
---
diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c
index 021b4c7..75fa26a 100644
--- a/gdk-pixbuf/gdk-pixbuf-io.c
+++ b/gdk-pixbuf/gdk-pixbuf-io.c
@@ -347,34 +347,24 @@ get_libdir (void)
#undef GDK_PIXBUF_LIBDIR
#define GDK_PIXBUF_LIBDIR get_libdir()
-static void
-correct_prefix (gchar **path)
+#endif /* GDK_PIXBUF_RELOCATABLE */
+
+/* In case we have a relative module path in the loaders cache
+ * prepend the toplevel dir */
+static gchar *
+build_module_path (const gchar *path)
{
- if (strncmp (*path, GDK_PIXBUF_PREFIX "/", strlen (GDK_PIXBUF_PREFIX "/")) == 0 ||
- strncmp (*path, GDK_PIXBUF_PREFIX "\\", strlen (GDK_PIXBUF_PREFIX "\\")) == 0)
- {
- gchar *tem = NULL;
- if (g_str_has_suffix (*path, ".libs"))
- {
- /* We are being run from inside the build tree, and shouldn't mess about. */
- return;
+#ifdef GDK_PIXBUF_RELOCATABLE
+ if (g_path_is_absolute (path)) {
+ return g_strdup (path);
+ } else {
+ return g_build_filename (gdk_pixbuf_get_toplevel (), path, NULL);
}
-
- /* This is an entry put there by gdk-pixbuf-query-loaders on the
- * packager's system. On Windows a prebuilt gdk-pixbuf package can be
- * installed in a random location. The loaders.cache file
- * distributed in such a package contains paths from the package
- * builder's machine. Replace the build-time prefix with the
- * installation prefix on this machine.
- */
- tem = *path;
- *path = g_strconcat (gdk_pixbuf_get_toplevel (), tem + strlen (GDK_PIXBUF_PREFIX), NULL);
- g_free (tem);
- }
+#else
+ return g_strdup (path);
+#endif
}
-#endif /* GDK_PIXBUF_RELOCATABLE */
-
static gchar *
gdk_pixbuf_get_module_file (void)
{
@@ -512,9 +502,6 @@ gdk_pixbuf_io_init (void)
/* Blank line marking the end of a module
*/
if (module && *p != '#') {
-#ifdef GDK_PIXBUF_RELOCATABLE
- correct_prefix (&module->module_path);
-#endif
file_formats = g_slist_prepend (file_formats, module);
module = NULL;
}
@@ -536,7 +523,7 @@ gdk_pixbuf_io_init (void)
filename, line_buf);
have_error = TRUE;
}
- module->module_path = g_strdup (tmp_buf->str);
+ module->module_path = build_module_path (tmp_buf->str);
}
else if (!module->module_name) {
module->info = g_new0 (GdkPixbufFormat, 1);
diff --git a/gdk-pixbuf/queryloaders.c b/gdk-pixbuf/queryloaders.c
index 2b025b8..7728caf 100644
--- a/gdk-pixbuf/queryloaders.c
+++ b/gdk-pixbuf/queryloaders.c
@@ -116,14 +116,80 @@ loader_sanity_check (const char *path, GdkPixbufFormat *info, GdkPixbufModule *v
return 0;
}
+#ifdef GDK_PIXBUF_RELOCATABLE
+
+/* Based on gdk_pixbuf_get_toplevel () */
+static gchar *
+get_toplevel (void)
+{
+ static gchar *toplevel = NULL;
+
+ if (toplevel == NULL) {
+#if defined (G_OS_WIN32)
+ toplevel = g_win32_get_package_installation_directory_of_module (NULL);
+#elif defined(OS_DARWIN)
+ char pathbuf[PATH_MAX + 1];
+ uint32_t bufsize = sizeof (pathbuf);
+ gchar *bin_dir;
+
+ _NSGetExecutablePath (pathbuf, &bufsize);
+ bin_dir = g_dirname (pathbuf);
+ toplevel = g_build_path (G_DIR_SEPARATOR_S, bin_dir, "..", NULL);
+ g_free (bin_dir);
+#elif defined (OS_LINUX) || defined (__MINGW32__)
+ gchar *exe_path, *bin_dir;
+
+ exe_path = g_file_read_link ("/proc/self/exe", NULL);
+ bin_dir = g_dirname (exe_path);
+ toplevel = g_build_path (G_DIR_SEPARATOR_S, bin_dir, "..", NULL);
+ g_free (exe_path);
+ g_free (bin_dir);
+#else
+#error "Relocations not supported for this platform"
+#endif
+ }
+ return toplevel;
+}
+
+/* Returns the relative path or NULL; transfer full */
+static gchar *
+get_relative_path (const gchar *parent, const gchar *descendant)
+{
+ GFile *parent_file, *descendant_file;
+ char *relative_path;
+
+ parent_file = g_file_new_for_path (parent);
+ descendant_file = g_file_new_for_path (descendant);
+ relative_path = g_file_get_relative_path (parent_file, descendant_file);
+ g_object_unref (parent_file);
+ g_object_unref (descendant_file);
+
+ return relative_path;
+}
+
+#endif /* GDK_PIXBUF_RELOCATABLE */
+
static void
write_loader_info (GString *contents, const char *path, GdkPixbufFormat *info)
{
const GdkPixbufModulePattern *pattern;
char **mime;
char **ext;
+ gchar *module_path = NULL, *escaped_path;
+
+#ifdef GDK_PIXBUF_RELOCATABLE
+ module_path = get_relative_path (get_toplevel (), path);
+#endif
+
+ if (module_path == NULL) {
+ module_path = g_strdup (path);
+ }
+
+ escaped_path = g_strescape (module_path, "");
+ g_string_append_printf (contents, "\"%s\"\n", escaped_path);
+ g_free (module_path);
+ g_free (escaped_path);
- g_string_append_printf (contents, "\"%s\"\n", path);
g_string_append_printf (contents, "\"%s\" %u \"%s\" \"%s\" \"%s\"\n",
info->name,
info->flags,
@@ -213,17 +279,6 @@ query_module (GString *contents, const char *dir, const char *file)
#ifdef G_OS_WIN32
static char *
-get_toplevel (void)
-{
- static char *toplevel = NULL;
-
- if (toplevel == NULL)
- toplevel = g_win32_get_package_installation_directory_of_module (NULL);
-
- return toplevel;
-}
-
-static char *
get_libdir (void)
{
static char *libdir = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]