[glib] g_get_user_runtime_dir(): ensure directory exists



commit 7c6141a546b80866e26a12cee8b6a9f1be5b9fc6
Author: Allison Ryan Lortie <desrt desrt ca>
Date:   Tue Mar 8 15:34:26 2016 -0500

    g_get_user_runtime_dir(): ensure directory exists
    
    If the XDG_RUNTIME_DIR environment variable is set, we are being told by
    the OS that this directory exists and is appropriately configured
    already.  In the fallback case of ~/.cache/, however, the directory may
    not yet exist.
    
    Rework the logic of this function a little so that we only check for the
    environment variable once.  If it is not set, we will fall back to the
    cache directory, and mkdir() it to make sure that it exists.
    
    Meanwhile, remove a statement from the reference documentation that
    promises a warning in this case (which has never been true) and replace
    it with a statement that applications can rely on the directory
    existing.
    
    This change prevents each user of this API from having to check for the
    directory for themselves; an example of that can be seen in bug 763274.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=763344

 glib/gutils.c |   44 ++++++++++++++++++++++++++++++--------------
 1 files changed, 30 insertions(+), 14 deletions(-)
---
diff --git a/glib/gutils.c b/glib/gutils.c
index ee465d9..43a2776 100644
--- a/glib/gutils.c
+++ b/glib/gutils.c
@@ -1314,8 +1314,8 @@ g_get_user_cache_dir (void)
  * [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
  * This is the directory
  * specified in the `XDG_RUNTIME_DIR` environment variable.
- * In the case that this variable is not set, GLib will issue a warning
- * message to stderr and return the value of g_get_user_cache_dir().
+ * In the case that this variable is not set, we return the value of
+ * g_get_user_cache_dir(), after verifying that it exists.
  *
  * On Windows this is the folder to use for local (as opposed to
  * roaming) application data. See documentation for
@@ -1331,24 +1331,40 @@ g_get_user_runtime_dir (void)
 {
 #ifndef G_OS_WIN32
   static const gchar *runtime_dir;
-  static gsize initialised;
 
-  if (g_once_init_enter (&initialised))
+  if (g_once_init_enter (&runtime_dir))
     {
-      runtime_dir = g_strdup (getenv ("XDG_RUNTIME_DIR"));
-      
-      g_once_init_leave (&initialised, 1);
-    }
+      const gchar *dir;
 
-  if (runtime_dir)
-    return runtime_dir;
+      dir = g_strdup (getenv ("XDG_RUNTIME_DIR"));
 
-  /* Both fallback for UNIX and the default
-   * in Windows: use the user cache directory.
-   */
-#endif
+      if (dir == NULL)
+        {
+          /* No need to strdup this one since it is valid forever. */
+          dir = g_get_user_cache_dir ();
+
+          /* The user should be able to rely on the directory existing
+           * when the function returns.  Probably it already does, but
+           * let's make sure.  Just do mkdir() directly since it will be
+           * no more expensive than a stat() in the case that the
+           * directory already exists and is a lot easier.
+           *
+           * $XDG_CACHE_HOME is probably ~/.cache/ so as long as $HOME
+           * exists this will work.  If the user changed $XDG_CACHE_HOME
+           * then they can make sure that it exists...
+           */
+          (void) mkdir (dir, 0700);
+        }
+
+      g_assert (dir != NULL);
 
+      g_once_init_leave (&runtime_dir, dir);
+    }
+
+  return runtime_dir;
+#else /* Windows */
   return g_get_user_cache_dir ();
+#endif
 }
 
 #ifdef HAVE_CARBON


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]