[libglnx: 1/3] glnx-fdio: try $TMPDIR if /var/tmp doesn't exist




commit 1ea9158c24ab0c775c23403e853cc27bb0155d27
Author: Rebecca Turner <rbt sent as>
Date:   Wed Sep 23 13:33:43 2020 -0400

    glnx-fdio: try $TMPDIR if /var/tmp doesn't exist
    
    `glnx_open_anonymous_tmpfile` attempts to create an fd in `/var/tmp`
    regardless of the value of `$TMPDIR`.
    
    This is _usually_ okay, but can fail in some contexts, such as in the
    [NixOS][1] build environment, which doesn't have `/var` mapped at all.
    
    To avoid failing in this case, if the inner call to
    `glnx_open_anonymous_tmpfile_full` fails, we retrieve the value of
    `$TMPDIR` and try calling `glnx_open_anonymous_tmpfile_full` again with
    that directory instead.
    
    In the fast path (i.e. where `/var/tmp` exists), functionality is
    unchanged.
    
    [1]: https://nixos.org/

 glnx-fdio.c | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)
---
diff --git a/glnx-fdio.c b/glnx-fdio.c
index e537a9b..9cf595e 100644
--- a/glnx-fdio.c
+++ b/glnx-fdio.c
@@ -303,8 +303,8 @@ glnx_open_anonymous_tmpfile_full (int          flags,
 }
 
 /* A variant of `glnx_open_tmpfile_linkable_at()` which doesn't support linking.
- * Useful for true temporary storage. The fd will be allocated in /var/tmp to
- * ensure maximum storage space.
+ * Useful for true temporary storage. The fd will be allocated in `/var/tmp`
+ * (or `$TMPDIR` if `/var/tmp` doesn't exist) to ensure maximum storage space.
  *
  * If you need the file on a specific filesystem use glnx_open_anonymous_tmpfile_full()
  * which lets you pass a directory.
@@ -314,7 +314,37 @@ glnx_open_anonymous_tmpfile (int          flags,
                              GLnxTmpfile *out_tmpf,
                              GError     **error)
 {
-  return glnx_open_anonymous_tmpfile_full (flags, "/var/tmp", out_tmpf, error);
+  if (glnx_open_anonymous_tmpfile_full (flags, "/var/tmp", out_tmpf, error))
+    return TRUE;
+  else if ((*error)->code == G_IO_ERROR_NOT_FOUND)
+    {
+      /* If /var/tmp doesn't exist, such as in a NixOS build or
+       * other constrained systems, this will fail.
+       *
+       * Therefore, we try again using the directory in $TMPDIR if possible.
+       */
+      const char *tmpdir = getenv("TMPDIR");
+      if (tmpdir == NULL)
+        return FALSE;
+
+      GError *tmp_error;
+      tmp_error = NULL;
+      if (!glnx_open_anonymous_tmpfile_full (flags, tmpdir,
+                                             out_tmpf, &tmp_error))
+        {
+          g_propagate_error (error, tmp_error);
+          return FALSE;
+        }
+      else
+        {
+          // Don't leave the error from the first call to
+          // glnx_open_anonymous_tmpfile_full in `error`.
+          g_clear_error(error);
+          return TRUE;
+        }
+    }
+  else
+    return FALSE;
 }
 
 /* Use this after calling glnx_open_tmpfile_linkable_at() to give


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