8000 mktemp: incompatibility between coreutils, BSD (file created in current directory) · Issue #4821 · uutils/coreutils · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

mktemp: incompatibility between coreutils, BSD (file created in current directory) #4821

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

Closed
kevinburke opened this issue May 2, 2023 · 5 comments · Fixed by #4832
Closed

Comments

@kevinburke
Copy link
Contributor
kevinburke commented May 2, 2023

If I run mktemp -t foo.XXX , I expect a file to be created in a temporary directory. Instead with Rust coreutils, a file is created in the current directory.

With BSD, mktemp -t foo.XXX creates a file in /var/folders/.../... as I expect it to.

@sylvestre
Copy link
Contributor

On Linux, it is created in pwd:

$ mktemp -t foo.XXX
foo.BXX
$ ls -al foo.BXX
-rw------- 1 sylvestre sylvestre 0 May  3 08:39 foo.BXX

@kevinburke
Copy link
Contributor Author
kevinburke commented May 4, 2023

@sylvestre can you double check or share a little bit more about which version of mktemp you're running? I got hold of a Linux machine and I can't reproduce - this is with GNU coreutils.

# mktemp -t foo.XXX
/tmp/foo.EW8

@kevinburke
Copy link
Contributor Author

I also tried busybox and can't reproduce.

# mktemp -t foo.XXX
mktemp: Invalid argument

@mckern
Copy link
mckern commented May 4, 2023

Respectfully, mktemp -t should always default to /tmp unless -p or $TMPDIR says otherwise. It should never make a temporary file or directory in the current working directory unless explicitly told to.

First, some examples of default behavior

Some context from a plain, fresh Debian 12 pre-release instance

$ docker run -it --rm --workdir /root debian:bookworm /bin/bash
root@ce6df075b698:~# pwd
/root
root@ce6df075b698:~# env | grep TMP
root@ce6df075b698:~# env | grep TEMP
root@ce6df075b698:~# mktemp -t foo.XXX
/tmp/foo.Hgv
root@ce6df075b698:~# command -v mktemp
/usr/bin/mktemp
root@ce6df075b698:~# ls -lha /usr/bin/mktemp
-rwxr-xr-x 1 root root 43K Sep 20  2022 /usr/bin/mktemp

# Debian 12 has a unified /bin and /usr/bin (https://wiki.debian.org/UsrMerge)

root@ce6df075b698:~# dpkg -S /bin/mktemp
coreutils: /bin/mktemp
root@ce6df075b698:~# dpkg -l coreutils
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  coreutils      9.1-1        amd64        GNU core utilities

And a fresh Debian 11.7 instance:

$ docker run -it --rm --workdir /root debian:bullseye /bin/bash
root@586830a958f3:~# cat /etc/debian_version
11.7
root@586830a958f3:~# mktemp -t foo.XXX
/tmp/foo.Muf
root@586830a958f3:~# dpkg -S /bin/mktemp
coreutils: /bin/mktemp
root@586830a958f3:~# dpkg -l coreutils
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  coreutils      8.32-4+b1    amd64        GNU core utilities
root@586830a958f3:~#

A fresh alpine:latest instance; this failure makes sense and aligns with what Kevin reports, since it's a Busybox mktemp and not a coreutils mktemp -- busybox requires more X's to generate a path.

$ docker run -it --rm --workdir /root alpine:latest
~ # which mktemp
/bin/mktemp
~ # mktemp -t foo.XXX
mktemp: (null): Invalid argument
~ # mktemp -h
mktemp: unrecognized option: h
BusyBox v1.35.0 (2022-11-19 10:13:10 UTC) multi-call binary.

Usage: mktemp [-dt] [-p DIR] [TEMPLATE]

Create a temporary file with na
8000
me based on TEMPLATE and print its name.
TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).
Without TEMPLATE, -t tmp.XXXXXX is assumed.

	-d	Make directory, not file
	-q	Fail silently on errors
	-t	Prepend base directory name to TEMPLATE
	-p DIR	Use DIR as a base directory (implies -t)
	-u	Do not create anything; print a name

Base directory is: -p DIR, else $TMPDIR, else /tmp
~ # mktemp -t foo.XXXXXX
/tmp/foo.bLJLOf

OK but why?

mktemp should always respect $TMPDIR, and default to /tmp and the help screens for Busybox, GNU coreutils mktemp agree on this:

Busybox:

# mktemp -h
mktemp: unrecognized option: h
BusyBox v1.35.0 (2022-11-19 10:13:10 UTC) multi-call binary.

Usage: mktemp [-dt] [-p DIR] [TEMPLATE]

Create a temporary file with name based on TEMPLATE and print its name.
TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).
Without TEMPLATE, -t tmp.XXXXXX is assumed.

	-d	Make directory, not file
	-q	Fail silently on errors
	-t	Prepend base directory name to TEMPLATE
	-p DIR	Use DIR as a base directory (implies -t)
	-u	Do not create anything; print a name

Base directory is: -p DIR, else $TMPDIR, else /tmp

GNU Coreutils:

# mktemp --help
Usage: mktemp [OPTION]... [TEMPLATE]
Create a temporary file or directory, safely, and print its name.
TEMPLATE must contain at least 3 consecutive 'X's in last component.
If TEMPLATE is not specified, use tmp.XXXXXXXXXX, and --tmpdir is implied.
Files are created u+rw, and directories u+rwx, minus umask restrictions.

  -d, --directory     create a directory, not a file
  -u, --dry-run       do not create anything; merely print a name (unsafe)
  -q, --quiet         suppress diagnostics about file/dir-creation failure
      --suffix=SUFF   append SUFF to TEMPLATE; SUFF must not contain a slash.
                        This option is implied if TEMPLATE does not end in X
  -p DIR, --tmpdir[=DIR]  interpret TEMPLATE relative to DIR; if DIR is not
                        specified, use $TMPDIR if set, else /tmp.  With
                        this option, TEMPLATE must not be an absolute name;
                        unlike with -t, TEMPLATE may contain slashes, but
                        mktemp creates only the final component
  -t                  interpret TEMPLATE as a single file name component,
                        relative to a directory: $TMPDIR, if set; else the
                        directory specified via -p; else /tmp [deprecated]
      --help     display this help and exit
      --version  output version information and exit

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/mktemp>
or available locally via: info '(coreutils) mktemp invocation'

macOS's BSD-derived mktemp has no helpful --help or -h output but it has a man page, and that man page is also pretty clear about behavior:

If the -t prefix option is given, mktemp will generate a template string
based on the prefix and the _CS_DARWIN_USER_TEMP_DIR configuration
variable if available.  Fallback locations if _CS_DARWIN_USER_TEMP_DIR is
not available are TMPDIR and /tmp.  Care should be taken to ensure that
it is appropriate to use an environment variable potentially supplied by
the user.

If no arguments are passed or if only the -d flag is passed mktemp
behaves as if -t tmp was supplied.

@sylvestre
Copy link
Contributor

Sorry, I am just dumb ... I was using a system relying on the Rust implementation ....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants
0