Hi,

Attached is a patch to fix an issue (#1830) affecting
create-temporary-{file,directory} in cases where the environment
variables they use to determine the directory where temporary
files/directories are created get changed.

Please see the commit message and https://bugs.call-cc.org/ticket/1830
for more details.

The patch also contains some updates to the documentation and a couple
of simple tests.  The tests will be called by "make check" on Windows,
but I haven't run them there as I don't have a Windows system.

All the best.
Mario
-- 
http://parenteses.org/mario
>From b2f56ee7a2bc98bfebe8e8674dab2aa7c9e70bdc Mon Sep 17 00:00:00 2001
From: Mario Domenech Goulart <[email protected]>
Date: Mon, 1 Jan 2024 21:07:36 +0100
Subject: [PATCH] Drop memoization of envvars used by
 create-temporary-{file,directory}

Once cached, the directory used by create-temporary-file and
create-temporary-directory remains unchanged regardless of changes to
the environment variables they are supposed to respect (TMPDIR, TMP
and TEMP).

Example:

Without this patch:

  #;1> (create-temporary-file)
  "/tmp/tempcd92.182728.tmp"
  #;2> (set-environment-variable! "TMPDIR" "/home/mario")
  #;3> (create-temporary-file)
  "/tmp/tempc6c.182728.tmp"

With this patch:

  #;1> (create-temporary-file)
  "/tmp/temp6bf0.186696.tmp"
  #;2> (set-environment-variable! "TMPDIR" "/home/mario")
  #;3> (create-temporary-file)
  "/home/mario/temp639b.186696.tmp"

Fixes #1830
---
 NEWS                                 |  2 ++
 file.scm                             | 15 +++++--------
 manual/Module (chicken file)         | 32 +++++++++++++++++++--------
 tests/runtests.bat                   |  4 ++++
 tests/runtests.sh                    |  3 +++
 tests/test-create-temporary-file.scm | 33 ++++++++++++++++++++++++++++
 6 files changed, 70 insertions(+), 19 deletions(-)
 create mode 100644 tests/test-create-temporary-file.scm

diff --git a/NEWS b/NEWS
index cb565620..3fcbbdd4 100644
--- a/NEWS
+++ b/NEWS
@@ -31,6 +31,8 @@
     using it from there is deprecated.
   - Added "export/rename" to (chicken module) for renaming identifiers on
     export.
+  - The values of the TMPDIR, TMP and TEMP environment variables are no
+    longer memoized (fixes #1830).
 
 - Tools
   - The -R option for csi and csc now accepts list-notation like
diff --git a/file.scm b/file.scm
index 11b1bcc0..78d68a41 100644
--- a/file.scm
+++ b/file.scm
@@ -304,18 +304,13 @@ EOF
 (define create-temporary-file)
 (define create-temporary-directory)
 
-(let ((temp #f)
-      (temp-prefix "temp")
+(let ((temp-prefix "temp")
       (string-append string-append))
   (define (tempdir)
-    (or temp
-	(let ((tmp
-	       (or (get-environment-variable "TMPDIR")
-		   (get-environment-variable "TEMP")
-		   (get-environment-variable "TMP")
-		   "/tmp")))
-	  (set! temp tmp)
-	  tmp)))
+    (or (get-environment-variable "TMPDIR")
+        (get-environment-variable "TEMP")
+        (get-environment-variable "TMP")
+        "/tmp"))
   (set! create-temporary-file
     (lambda (#!optional (ext "tmp"))
       (##sys#check-string ext 'create-temporary-file)
diff --git a/manual/Module (chicken file) b/manual/Module (chicken file)
index e78fb91b..4dd96d08 100644
--- a/manual/Module (chicken file)	
+++ b/manual/Module (chicken file)	
@@ -129,22 +129,36 @@ write or execute permissions on the file named {{FILENAME}}.
 <procedure>(create-temporary-file [EXTENSION])</procedure>
 
 Creates an empty temporary file and returns its pathname. If
-{{EXTENSION}} is not given, then {{.tmp}} is used. If the
-environment variable {{TMPDIR, TEMP}} or {{TMP}} is set,
-then the pathname names a file in that directory. If none of
-the environment variables is given the location of the
-temporary file defaults to {{/tmp}} if it exists or the 
-current-directory
+{{EXTENSION}} is not given, then {{.tmp}} is used. If the environment
+variable {{TMPDIR}}, {{TEMP}} or {{TMP}} is set, then the pathname
+names a file in that directory. If none of the environment variables
+is given, the location of the temporary file defaults to {{/tmp}}.
 
+Note that {{TMPDIR}}, {{TEMP}} and {{TMP}} are checked in this order.
+It means that, for example, if both {{TMPDIR}} and {{TEMP}} are set,
+the value of {{TMPDIR}} will be used.
+
+Changed in CHICKEN 5.4.0: the values of the {{TMPDIR}}, {{TEMP}} and
+{{TMP}} environment variables are no longer memoized (see
+[[#1830|https://bugs.call-cc.org/ticket/1830]]).
 
 ==== create-temporary-directory
 
 <procedure>(create-temporary-directory)</procedure>
 
 Creates an empty temporary directory and returns its pathname. If the
-environment variable {{TMPDIR, TEMP}} or {{TMP}} is set, then the
-temporary directory is created at that location.
-
+environment variable {{TMPDIR}}, {{TEMP}} or {{TMP}} is set, then the
+temporary directory is created at that location. If none of the
+environment variables is given, the location of the temporary
+directory defaults to {{/tmp}}.
+
+Note that {{TMPDIR}}, {{TEMP}} and {{TMP}} are checked in this order.
+It means that, for example, if both {{TMPDIR}} and {{TEMP}} are set,
+the value of {{TMPDIR}} will be used.
+
+Changed in CHICKEN 5.4.0: the values of the {{TMPDIR}}, {{TEMP}} and
+{{TMP}} environment variables are no longer memoized (see
+[[#1830|https://bugs.call-cc.org/ticket/1830]]).
 
 === Finding files
 
diff --git a/tests/runtests.bat b/tests/runtests.bat
index ab0bcc45..24977eee 100644
--- a/tests/runtests.bat
+++ b/tests/runtests.bat
@@ -586,6 +586,10 @@ echo ======================================== find-files tests ...
 %interpret% -bnq test-find-files.scm
 if errorlevel 1 exit /b 1
 
+echo ======================================== create-temporary-file tests ...
+%interpret% -bnq test-create-temporary-file.scm
+if errorlevel 1 exit /b 1
+
 echo "======================================== record-renaming tests ..."
 %interpret% -bnq record-rename-test.scm
 if errorlevel 1 exit /b 1
diff --git a/tests/runtests.sh b/tests/runtests.sh
index 4fba44b5..185db284 100755
--- a/tests/runtests.sh
+++ b/tests/runtests.sh
@@ -433,6 +433,9 @@ fi
 echo "======================================== find-files tests ..."
 $interpret -bnq test-find-files.scm
 
+echo "======================================== create-temporary-file tests ..."
+$interpret -bnq test-create-temporary-file.scm
+
 echo "======================================== record-renaming tests ..."
 $interpret -bnq record-rename-test.scm
 
diff --git a/tests/test-create-temporary-file.scm b/tests/test-create-temporary-file.scm
new file mode 100644
index 00000000..67e664c3
--- /dev/null
+++ b/tests/test-create-temporary-file.scm
@@ -0,0 +1,33 @@
+(import (chicken file)
+        (chicken pathname)
+        (chicken process-context))
+
+(define (with-environment-variable var val thunk)
+  (let ((old-val (get-environment-variable var)))
+    (set-environment-variable! var val)
+     (thunk)
+     (if old-val
+         (set-environment-variable! var old-val)
+         (unset-environment-variable! var))))
+
+(let ((tmp (create-temporary-file)))
+  (delete-file tmp)
+  (assert (pathname-directory tmp)))
+
+;; Assert that changes to the environment variables used by
+;; create-temporary-file and create-temporary-directory get used (see
+;; https://bugs.call-cc.org/ticket/1830).
+;;
+;; Here the use of "" as value of TMPDIR is because
+;; (pathname-directory (make-pathname "" filename)) => #f
+(with-environment-variable "TMPDIR" ""
+  (lambda ()
+    (let ((tmp (create-temporary-file)))
+      (delete-file tmp)
+      (assert (not (pathname-directory tmp))))))
+
+(with-environment-variable "TMPDIR" ""
+  (lambda ()
+    (let ((tmp (create-temporary-directory)))
+      (delete-directory tmp)
+      (assert (not (pathname-directory tmp))))))
-- 
2.39.2

Reply via email to