From a85e5286fd2064bfd684e85f3536626bcc2973cb Mon Sep 17 00:00:00 2001 From: Jehan Date: Mon, 6 Apr 2026 16:09:09 +0200 Subject: [PATCH] Issue #14681: Permission denied opening image - /tmp/gimp/3.0/ cannot be shared. Let's create the folder returned by gimp_temp_directory() ourselves, the first time this function is called, using a randomized name. This will ensure that we won't conflict with another user running GIMP on the same machine if using the base /tmp/ (which is usually the case on Linux). Furthermore, since we create the temp folder at this level, we will also delete it when quitting (but only if it's empty, as it should). Also I use a single-level folder above the generic temporary directory, this way, it's easier to track and we don't have to delete 2 levels of directories anymore. When the environment variable GIMP3_TEMPDIR is set though, we do not create the folder, nor do we try and delete it. --- app/main.c | 2 ++ libgimp/gimp.c | 4 +++ libgimpbase/gimpbase.def | 1 + libgimpbase/gimpenv-private.h | 3 +- libgimpbase/gimpenv.c | 53 ++++++++++++++++++++++++++--------- 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/app/main.c b/app/main.c index 4fc373eeaa..c71c102c57 100644 --- a/app/main.c +++ b/app/main.c @@ -909,6 +909,8 @@ main (int argc, pdb_compat_mode, backtrace_file); + gimp_env_exit (FALSE); + g_free (backtrace_file); g_clear_object (&system_gimprc_file); diff --git a/libgimp/gimp.c b/libgimp/gimp.c index cefd101492..74b2e3d23a 100644 --- a/libgimp/gimp.c +++ b/libgimp/gimp.c @@ -576,6 +576,7 @@ gimp_main (GType plug_in_type, _gimp_plug_in_query (PLUG_IN); gimp_close (); + gimp_env_exit (TRUE); return EXIT_SUCCESS; } @@ -588,6 +589,7 @@ gimp_main (GType plug_in_type, _gimp_plug_in_init (PLUG_IN); gimp_close (); + gimp_env_exit (TRUE); return EXIT_SUCCESS; } @@ -605,6 +607,8 @@ gimp_main (GType plug_in_type, g_clear_object (&_check_custom_color1); g_clear_object (&_check_custom_color2); + gimp_env_exit (TRUE); + return EXIT_SUCCESS; } diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def index 454de44291..26f0c50e77 100644 --- a/libgimpbase/gimpbase.def +++ b/libgimpbase/gimpbase.def @@ -58,6 +58,7 @@ EXPORTS gimp_enum_value_get_abbrev gimp_enum_value_get_desc gimp_enum_value_get_help + gimp_env_exit gimp_env_init gimp_escape_uline gimp_export_capabilities_get_type diff --git a/libgimpbase/gimpenv-private.h b/libgimpbase/gimpenv-private.h index fae7a86f4a..f85de504de 100644 --- a/libgimpbase/gimpenv-private.h +++ b/libgimpbase/gimpenv-private.h @@ -26,7 +26,8 @@ G_BEGIN_DECLS /* For information look into the C source or the html documentation */ -void gimp_env_init (gboolean plug_in); +void gimp_env_init (gboolean plug_in); +void gimp_env_exit (gboolean plug_in); G_END_DECLS diff --git a/libgimpbase/gimpenv.c b/libgimpbase/gimpenv.c index 0ccfa3d721..5b47b24604 100644 --- a/libgimpbase/gimpenv.c +++ b/libgimpbase/gimpenv.c @@ -98,6 +98,9 @@ static gchar * gimp_env_get_dir (const gchar *gimp_env_name, const gchar *relative_subdir); +static gchar *gimp_temp_dir = NULL; +static gboolean gimp_temp_dir_generated = FALSE; + const guint gimp_major_version = GIMP_MAJOR_VERSION; const guint gimp_minor_version = GIMP_MINOR_VERSION; const guint gimp_micro_version = GIMP_MICRO_VERSION; @@ -171,6 +174,19 @@ gimp_env_init (gboolean plug_in) } } +void +gimp_env_exit (gboolean plug_in) +{ + if (gimp_temp_dir_generated) + { + if (g_rmdir (gimp_temp_dir) == -1) + g_printerr ("%s: failed to delete the temporary folder `%s`: %s\n", + G_STRFUNC, gimp_temp_dir, g_strerror (errno)); + } + + g_clear_pointer (&gimp_temp_dir, g_free); +} + #ifdef G_OS_WIN32 static char * @@ -755,9 +771,9 @@ gimp_cache_directory (void) * gimp_temp_directory: * * Returns the default top directory for GIMP temporary files. If the - * environment variable GIMP3_TEMPDIR exists, that is used. It - * should be an absolute pathname. Otherwise, a subdirectory of the - * directory returned by g_get_tmp_dir() is used. + * environment variable `GIMP3_TEMPDIR` exists, that is used. It + * should be an absolute pathname. Otherwise, a subdirectory of the + * directory returned by [func@GLib.get_tmp_dir] is used. * * In config files such as gimprc, the string ${gimp_temp_dir} expands * to this directory. @@ -767,8 +783,10 @@ gimp_cache_directory (void) * * The returned string is owned by GIMP and must not be modified or * freed. The returned string is in the encoding used for filenames by - * GLib, which isn't necessarily UTF-8. (On Windows it always is - * UTF-8.). + * GLib, which isn't necessarily UTF-8 (On Windows it always is UTF-8.). + * + * The returned directory path might already exists, or it might not. It + * is your responsibility to make sure it does before using it. * * Since: 2.10.10 * @@ -777,17 +795,24 @@ gimp_cache_directory (void) const gchar * gimp_temp_directory (void) { - static gchar *gimp_temp_dir = NULL; - if (! gimp_temp_dir) { - gchar *tmp = g_build_filename (g_get_tmp_dir (), - GIMP_PACKAGE, - GIMP_USER_VERSION, - NULL); + GError *error = NULL; - gimp_temp_dir = gimp_env_get_dir ("GIMP3_TEMPDIR", NULL, tmp); - g_free (tmp); + gimp_temp_dir = gimp_env_get_dir ("GIMP3_TEMPDIR", NULL, NULL); + if (gimp_temp_dir) + return gimp_temp_dir; + + gimp_temp_dir = g_dir_make_tmp (GIMP_PACKAGE "-" GIMP_USER_VERSION "-XXXXXXX", &error); + gimp_temp_dir_generated = TRUE; + if (gimp_temp_dir == NULL) + { + g_critical ("%s: failed to create temporary directory: %s\n", + G_STRFUNC, error->message); + g_clear_error (&error); + + gimp_temp_dir_generated = FALSE; + } } return gimp_temp_dir; @@ -1286,7 +1311,7 @@ gimp_env_get_dir (const gchar *gimp_env_name, return retval; } - else if (! g_path_is_absolute (relative_subdir)) + else if (relative_subdir && ! g_path_is_absolute (relative_subdir)) { return g_build_filename (gimp_installation_directory (), relative_subdir,