summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Reiter <creiter@src.gnome.org>2016-12-13 20:43:10 +0100
committerChristoph Reiter <creiter@src.gnome.org>2018-04-24 12:34:08 +0200
commit6ef31828dd5f58491fb7a20e5258cb0c3f42b170 (patch)
tree890f1fa0643c5ab1e9d7d4b761bf1dea44e98475
parent12aa6f9264514c62781124a7287c2e997d3ea482 (diff)
downloadgdk-pixbuf-6ef31828dd5f58491fb7a20e5258cb0c3f42b170.tar.gz
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
-rw-r--r--gdk-pixbuf/gdk-pixbuf-io.c43
-rw-r--r--gdk-pixbuf/queryloaders.c79
2 files changed, 82 insertions, 40 deletions
diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c
index 021b4c702..75fa26ae4 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 2b025b88c..7728caf4b 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;