Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mktemp: respect TMPDIR environment variable #3552

Merged
merged 1 commit into from
Sep 14, 2022

Conversation

jfinkels
Copy link
Collaborator

Change mktemp so that it respects the value of the TMPDIR
environment variable, if no directory is otherwise specified in its
arguments. For example, before this commit

$ TMPDIR=. mktemp
/tmp/tmp.WDJ66MaS1T

After this commit,

$ TMPDIR=. mktemp
./tmp.h96VZBhv8P

This matches the behavior of GNU mktemp.

@sylvestre
Copy link
Contributor

On windows:

---- test_mktemp::test_tmpdir_env_var stdout ----
current_directory_resolved: 
mkdir: C:\Users\RUNNER~1\AppData\Local\Temp\.tmpykaxwA\d
run: D:\a\coreutils\coreutils\target\debug\coreutils.exe mktemp
thread 'test_mktemp::test_tmpdir_env_var' panicked at '"C:\Users\RUNNER~1\AppData\Local\Temp\.tmpykaxwA\d/tmp.XXXXXXXXXX" != "tmp.rpDSCJMWz7"', D:\a\coreutils\coreutils\tests\by-util\test_mktemp.rs:548:5

@jfinkels jfinkels force-pushed the mktemp-tmpdir-env-var branch from ff3cae3 to 60ef369 Compare May 22, 2022 15:40
@jfinkels
Copy link
Collaborator Author

Thanks, I hope that is fixed now.

@jfinkels
Copy link
Collaborator Author

Nope, I still have an issue on Windows. I'll look into it later.

@jfinkels jfinkels force-pushed the mktemp-tmpdir-env-var branch 2 times, most recently from 224facf to 27d57db Compare May 26, 2022 23:23
@jfinkels
Copy link
Collaborator Author

Something strange is happening with the TMPDIR environment variable in the GNU tests on this pull request and I cannot figure it out. I am running bash util/run-gnu-test.sh tests/misc/mktemp.pl. Before this change, most of the test cases in tests/misc/mktemp.pl are passing. After this change, most of them are failing, because the output of mktemp has /tmp/ at the beginning of the temporary file path. For example, in test case "1f", the error message looks like this:

1f...
mktemp.pl: test 1f: stdout mismatch, comparing 1f.1 (expected) and 1f.O (actual)
*** 1f.1        Thu May 26 19:29:05 2022
--- 1f.O        Thu May 26 19:29:05 2022
***************
*** 1 ****
! bar.ZZZZ
--- 1 ----
! /tmp/bar.ZZZZ

However, when I run the command myself, it seems to work as expected:

$ ./target/release/mktemp bar.XXXX
bar.xXFS

For some reason, the GNU test suite incorrectly thinks that the environment variable TMPDIR is set to /tmp.

@tertsdiepraam
Copy link
Member

Correct me if I'm wrong, but I think it has something to do with the default value of the tmpdir. It seems like you're using the current directory as a fallback for when TMPDIR is missing, but the GNU docs state:

Treat template relative to the directory dir. If dir is not specified (only possible with the long option --tmpdir) or is the empty string, use the value of TMPDIR if available, otherwise use /tmp.

@jfinkels
Copy link
Collaborator Author

That quote seems to be from the description of the --tmpdir option, which is not involved in the issue I was describing above. The issue I'm seeing is that when running bash util/run-gnu-test.sh tests/misc/mktemp.pl, the TMPDIR environment variable is somehow being set to /tmp, but I don't know why or how that's happening.

@tertsdiepraam
Copy link
Member

I see, it mentioned somewhere that a value of /tmp is the default, but I guess that's only true if there's also no template given. The mystery remains unsolved then :)

@jfinkels
Copy link
Collaborator Author

jfinkels commented May 30, 2022

I created this file named printtmpdir.sh in the gnu/tests/misc/ directory:

#!/bin/sh
. "${srcdir=.}/tests/init.sh";
echo TMPDIR=$TMPDIR
Exit 1

and then I ran it with

bash util/run-gnu-test.sh tests/misc/printtmpdir.sh

and I got the following output

FAIL: tests/misc/printtmpdir
============================

TMPDIR=/tmp
FAIL tests/misc/printtmpdir.sh (exit status: 1)

But printing the same environment variable as its own command gives

$ echo TMPDIR=$TMPDIR
TMPDIR=

This is more evidence that the TMPDIR environment variable is unexpectedly set to /tmp when I run the GNU test suite. I'll revert this pull request to a draft and create a new issue for this. Edit: unless TMPDIR is supposed to be set to /tmp and then it is supposed to be unset before running the tests/misc/mktemp.pl test script?

@tertsdiepraam
Copy link
Member

tertsdiepraam commented May 30, 2022

unless TMPDIR is supposed to be set to /tmp and then it is supposed to be unset before running the tests/misc/mktemp.pl test script?

Not sure about being unset, but they seem to set it explicitly in the Makefile (from line 7439):

# Note that the first lines are statements.  They ensure that environment
# variables that can perturb tests are unset or set to expected values.
# The rest are envvar settings that propagate build-related Makefile
# variables to test scripts.
TESTS_ENVIRONMENT = \
  . $(srcdir)/tests/lang-default;       \
  tmp__=$${TMPDIR-/tmp};            \
  test -d "$$tmp__" && test -w "$$tmp__" || tmp__=.;    \
 . $(srcdir)/tests/envvar-check;       \
 TMPDIR=$$tmp__; export TMPDIR;        \

@jfinkels
Copy link
Collaborator Author

Hm, but the test cases in tests/misc/mktemp.pl all expect that TMPDIR is not set (except the ones that set TMPDIR explicitly).

@tertsdiepraam
Copy link
Member

tertsdiepraam commented Jun 1, 2022

Okay, I did some more tests. First, I checked any other places where TMPDIR could be changed and found nothing. Then, I made mktemp.pl fail with the value of TMPDIR and it is indeed set to /tmp, confirming that it is not just the bash tests, but also the perl tests that have that variable set. So then I tried the 1f test case with and without TMPDIR set:

(cargo commands are this PR)

echo $TMPDIR

❯ cargo run --quiet -- bar.XXXX
bar.NVKh
❯ mktemp bar.XXXX
bar.lfXc
❯ TMPDIR=/tmp cargo run --quiet -- bar.XXXX
/tmp/bar.HCS6
❯ TMPDIR=/tmp mktemp bar.XXXX
bar.sgDY

So, the test case actually doesn't care whether TMPDIR is set because it shouldn't use it when a template is given and --tmpdir is not used.

@jfinkels
Copy link
Collaborator Author

jfinkels commented Jun 1, 2022

Okay, so I think the unit test that I wrote is incorrect, and I misunderstood how the environment variable interacts with the arguments. It's confusing!

The documentation states "If TEMPLATE is not specified, use tmp.XXXXXXXXXX, and --tmpdir is implied." So in other words, TMPDIR should be respected unless a template argument is present and
--tmpdir is not present:

$ mkdir d
$ TMPDIR=d mktemp
d/tmp.dhHS99qWsq

$ TMPDIR=d mktemp --tmpdir
d/tmp.KaKXYFfaUK

$ TMPDIR=d mktemp XXX
bAw

$ TMPDIR=d mktemp --tmpdir XXX
d/DSC

I'll adjust the code on this branch to reflect that.

@jfinkels jfinkels force-pushed the mktemp-tmpdir-env-var branch from 27d57db to 6cb3e6a Compare June 1, 2022 22:16
@jfinkels jfinkels force-pushed the mktemp-tmpdir-env-var branch from 6cb3e6a to 9ff62e3 Compare June 6, 2022 23:44
@jfinkels
Copy link
Collaborator Author

jfinkels commented Jun 7, 2022

I've updated this pull request with a new implementation and some new unit tests to match the intended behavior. However, now I'm facing a failure on Windows that I'm not able to diagnose:

---- test_mktemp::test_tmpdir_env_var stdout ----
current_directory_resolved: 
run: D:\a\coreutils\coreutils\target\debug\coreutils.exe mktemp
thread 'test_mktemp::test_tmpdir_env_var' panicked at '".\tmp.XXXXXXXXXX" != "C:\Users\RUNNER~1\AppData\Local\Temp\.tmp20FPpM\tmp.6swQq3pq5e"', D:\a\coreutils\coreutils\tests\by-util\test_mktemp.rs:631:5

@jfinkels jfinkels force-pushed the mktemp-tmpdir-env-var branch from c5aa9f5 to e736754 Compare June 8, 2022 01:10
@niyaznigmatullin
Copy link
Contributor

niyaznigmatullin commented Aug 11, 2022

I've looked into it, so it seems env::temp_dir().display().to_string() prints absolute path to the current dir, when echo %TMP% prints ..

The function env::temp_dir() calls GetTempPath2W (https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2w), for which the documentation says that

The GetTempPath2 function returns the properly formatted string that specifies the fully qualified path based on the environment variable search order as previously specified.

So I guess we need to say that in Windows it prints an absolute path. I didn't find a good way to learn if the variable that this path was taken from contains absolute path or relative path.

Copy link
Contributor

@sylvestre sylvestre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows fails with:


---- test_mktemp::test_tmpdir_env_var stdout ----
current_directory_resolved: 
run: D:\a\coreutils\coreutils\target\i686-pc-windows-msvc\debug\coreutils.exe mktemp
thread 'test_mktemp::test_tmpdir_env_var' panicked at '".\tmp.XXXXXXXXXX" != "C:\Users\RUNNER~1\AppData\Local\Temp\.tmpZJDV1L\tmp.knQR5r5wmV"', D:\a\coreutils\coreutils\tests\by-util\test_mktemp.rs:653:5

@jfinkels jfinkels force-pushed the mktemp-tmpdir-env-var branch from 44729f2 to 7e41b0e Compare September 6, 2022 04:18
@jfinkels jfinkels force-pushed the mktemp-tmpdir-env-var branch from fb82c02 to 6b4a211 Compare September 7, 2022 00:50
@jfinkels
Copy link
Collaborator Author

jfinkels commented Sep 7, 2022

Okay, I got the tests to pass on Windows by relaxing the assertion so that it just checks that the filename printed to stdout ends with the template.

@jfinkels jfinkels requested a review from sylvestre September 8, 2022 00:08
Change `mktemp` so that it respects the value of the `TMPDIR`
environment variable if no directory is otherwise specified in its
arguments. For example, before this commit

    $ TMPDIR=. mktemp
    /tmp/tmp.WDJ66MaS1T

After this commit,

    $ TMPDIR=. mktemp
    ./tmp.h96VZBhv8P

This matches the behavior of GNU `mktemp`.
@jfinkels jfinkels force-pushed the mktemp-tmpdir-env-var branch from 6b4a211 to 61345cb Compare September 13, 2022 23:38
@sylvestre sylvestre merged commit f83e7d3 into uutils:main Sep 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants