git: 30697383812e - stable/13 - mktemp: add -p/--tmpdir argument
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 13 Nov 2022 05:38:07 UTC
The branch stable/13 has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=30697383812ee71e2e52eedc8e247c9cd670b56c
commit 30697383812ee71e2e52eedc8e247c9cd670b56c
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2022-10-31 03:55:46 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2022-11-13 05:37:29 +0000
mktemp: add -p/--tmpdir argument
This matches other mktemp implementations, including OpenBSD and GNU.
The -p option can be used to provide a tmpdir prefix for specified
templates. Precedence works out like so:
-t flag:
- $TMPDIR
- -p directory
- /tmp
Implied -t flag (no arguments or only -d flag):
- -p directory
- $TMPDIR
- /tmp
Some tests have been added for mktemp(1) in the process.
Reviewed by: imp (earlier version), wosch
Sponsored by: Klara, Inc.
(cherry picked from commit ac6f924e1cd1ebd9832227e906ebc03e3ba5eede)
(cherry picked from commit d22f03636be1c012951f744f414b0d410970808e)
---
etc/mtree/BSD.tests.dist | 2 +
usr.bin/mktemp/Makefile | 5 ++
usr.bin/mktemp/mktemp.1 | 35 ++++++++++-
usr.bin/mktemp/mktemp.c | 52 +++++++++++++---
usr.bin/mktemp/tests/Makefile | 7 +++
usr.bin/mktemp/tests/mktemp_test.sh | 118 ++++++++++++++++++++++++++++++++++++
6 files changed, 209 insertions(+), 10 deletions(-)
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index e902a33ca417..b4050937dfc3 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -1044,6 +1044,8 @@
..
mkimg
..
+ mktemp
+ ..
ncal
..
opensm
diff --git a/usr.bin/mktemp/Makefile b/usr.bin/mktemp/Makefile
index 0e23063431c2..72e3d7306bb8 100644
--- a/usr.bin/mktemp/Makefile
+++ b/usr.bin/mktemp/Makefile
@@ -1,7 +1,12 @@
# $FreeBSD$
+.include <src.opts.mk>
+
PACKAGE= runtime
PROG= mktemp
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
.include <bsd.prog.mk>
diff --git a/usr.bin/mktemp/mktemp.1 b/usr.bin/mktemp/mktemp.1
index 469d4f6097d0..5835cf4b1b3f 100644
--- a/usr.bin/mktemp/mktemp.1
+++ b/usr.bin/mktemp/mktemp.1
@@ -37,12 +37,14 @@
.Sh SYNOPSIS
.Nm
.Op Fl d
+.Op Fl p Ar tmpdir
.Op Fl q
.Op Fl t Ar prefix
.Op Fl u
.Ar template ...
.Nm
.Op Fl d
+.Op Fl p Ar tmpdir
.Op Fl q
.Op Fl u
.Fl t Ar prefix
@@ -91,10 +93,20 @@ will generate a template string based on the
and the
.Ev TMPDIR
environment variable if set.
-The default location if
+If the
+.Fl p
+option is set, then the given
+.Ar tmpdir
+will be used if the
+.Ev TMPDIR
+environment variable is not set.
+Finally,
+.Pa /tmp
+will be used if neither
.Ev TMPDIR
-is not set is
-.Pa /tmp .
+or
+.Fl p
+are set and used.
Care should
be taken to ensure that it is appropriate to use an environment variable
potentially supplied by the user.
@@ -134,6 +146,23 @@ The available options are as follows:
.Bl -tag -width indent
.It Fl d , Fl -directory
Make a directory instead of a file.
+.It Fl p Ar tmpdir , Fl -tmpdir Ns Oo = Ns Ar tmpdir Oc
+Use
+.Ar tmpdir
+for the
+.Fl t
+flag if the
+.Ev TMPDIR
+environment variable is not set.
+Additionally, any provided
+.Ar template
+arguments will be interpreted relative to the path specified as
+.Ar tmpdir .
+If
+.Ar tmpdir
+is either empty or omitted, then the
+.Ev TMPDIR
+environment variable will be used.
.It Fl q , Fl -quiet
Fail silently if an error occurs.
This is useful if
diff --git a/usr.bin/mktemp/mktemp.c b/usr.bin/mktemp/mktemp.c
index dc92de2961d0..77245d2fa0d3 100644
--- a/usr.bin/mktemp/mktemp.c
+++ b/usr.bin/mktemp/mktemp.c
@@ -39,6 +39,7 @@
#include <err.h>
#include <getopt.h>
#include <paths.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -53,6 +54,7 @@ static void usage(void);
static const struct option long_opts[] = {
{"directory", no_argument, NULL, 'd'},
+ {"tmpdir", optional_argument, NULL, 'p'},
{"quiet", no_argument, NULL, 'q'},
{"dry-run", no_argument, NULL, 'u'},
{NULL, no_argument, NULL, 0},
@@ -62,21 +64,35 @@ int
main(int argc, char **argv)
{
int c, fd, ret;
- char *tmpdir;
- const char *prefix;
+ const char *prefix, *tmpdir;
char *name;
int dflag, qflag, tflag, uflag;
+ bool prefer_tmpdir;
ret = dflag = qflag = tflag = uflag = 0;
+ prefer_tmpdir = true;
prefix = "mktemp";
name = NULL;
+ tmpdir = NULL;
- while ((c = getopt_long(argc, argv, "dqt:u", long_opts, NULL)) != -1)
+ while ((c = getopt_long(argc, argv, "dp:qt:u", long_opts, NULL)) != -1)
switch (c) {
case 'd':
dflag++;
break;
+ case 'p':
+ tmpdir = optarg;
+ if (tmpdir == NULL || *tmpdir == '\0')
+ tmpdir = getenv("TMPDIR");
+
+ /*
+ * We've already done the necessary environment
+ * fallback, skip the later one.
+ */
+ prefer_tmpdir = false;
+ break;
+
case 'q':
qflag++;
break;
@@ -100,10 +116,26 @@ main(int argc, char **argv)
if (!tflag && argc < 1) {
tflag = 1;
prefix = "tmp";
+
+ /*
+ * For this implied -t mode, we actually want to swap the usual
+ * order of precedence: -p, then TMPDIR, then /tmp.
+ */
+ prefer_tmpdir = false;
}
if (tflag) {
- tmpdir = getenv("TMPDIR");
+ const char *envtmp;
+
+ envtmp = NULL;
+
+ /*
+ * $TMPDIR preferred over `-p` if specified, for compatibility.
+ */
+ if (prefer_tmpdir || tmpdir == NULL)
+ envtmp = getenv("TMPDIR");
+ if (envtmp != NULL)
+ tmpdir = envtmp;
if (tmpdir == NULL)
asprintf(&name, "%s%s.XXXXXXXX", _PATH_TMP, prefix);
else
@@ -120,7 +152,12 @@ main(int argc, char **argv)
/* generate all requested files */
while (name != NULL || argc > 0) {
if (name == NULL) {
- name = strdup(argv[0]);
+ if (!tflag && tmpdir != NULL)
+ asprintf(&name, "%s/%s", tmpdir, argv[0]);
+ else
+ name = strdup(argv[0]);
+ if (name == NULL)
+ err(1, "%s", argv[0]);
argv++;
argc--;
}
@@ -159,8 +196,9 @@ static void
usage(void)
{
fprintf(stderr,
- "usage: mktemp [-d] [-q] [-t prefix] [-u] template ...\n");
+ "usage: mktemp [-d] [-p tmpdir] [-q] [-t prefix] [-u] template "
+ "...\n");
fprintf(stderr,
- " mktemp [-d] [-q] [-u] -t prefix \n");
+ " mktemp [-d] [-p tmpdir] [-q] [-u] -t prefix \n");
exit (1);
}
diff --git a/usr.bin/mktemp/tests/Makefile b/usr.bin/mktemp/tests/Makefile
new file mode 100644
index 000000000000..5141bf0faade
--- /dev/null
+++ b/usr.bin/mktemp/tests/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PACKAGE= tests
+
+ATF_TESTS_SH+= mktemp_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/mktemp/tests/mktemp_test.sh b/usr.bin/mktemp/tests/mktemp_test.sh
new file mode 100755
index 000000000000..c424030fac4f
--- /dev/null
+++ b/usr.bin/mktemp/tests/mktemp_test.sh
@@ -0,0 +1,118 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+#
+# Copyright (c) 2022 Klara Systems
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+atf_test_case tmpdir_env
+tmpdir_env_body()
+{
+
+ tmpdir="$PWD"
+
+ atf_check -o match:"^$tmpdir/foo\..+$" \
+ env TMPDIR="$tmpdir" mktemp -t foo
+}
+
+atf_test_case tmpdir_pflag
+tmpdir_pflag_body()
+{
+
+ mkdir tmp_p tmp_env
+
+ tmpdir="$PWD/tmp_env"
+ export TMPDIR="$tmpdir"
+
+ pflag="$PWD/tmp_p"
+
+ # Basic usage: just -p specified
+ atf_check -o match:"^$pflag/tmp\..+$" \
+ env -u TMPDIR mktemp -p "$pflag"
+ atf_check -o match:"^$pflag/tmp\..+$" \
+ env TMPDIR="$tmpdir" mktemp -p "$pflag"
+
+ # -p with a list of names
+ atf_check -o ignore env -u TMPDIR mktemp -p "$pflag" x y z
+ atf_check test -f "$pflag/x"
+ atf_check test -f "$pflag/y"
+ atf_check test -f "$pflag/z"
+
+ # Checking --tmpdir usage, which should defer to $TMPDIR followed by
+ # /tmp with no value specified.
+ atf_check -o match:"^/tmp/foo\..+$" \
+ env -u TMPDIR mktemp --tmpdir -t foo
+ atf_check -o match:"^$tmpdir/foo\..+$" \
+ env TMPDIR="$tmpdir" mktemp --tmpdir -t foo
+
+ # Finally, combined -p -t
+ atf_check -o match:"^$pflag/foo\..+$" \
+ env -u TMPDIR mktemp -p "$pflag" -t foo
+ atf_check -o match:"^$pflag/foo\..+$" \
+ env TMPDIR="$tmpdir" mktemp -p "$pflag" -t foo
+}
+
+atf_test_case tmpdir_pflag_dir
+tmpdir_pflag_dir_body()
+{
+
+ tmpdir="$PWD"
+ atf_check -o save:tmpname \
+ env -u TMPDIR mktemp -d -p "$tmpdir" -t foo
+
+ # Better diagnostics when using -o match: + cat rather than grep.
+ atf_check -o match:"^$tmpdir/foo\..+$" cat tmpname
+ cdir=$(cat tmpname)
+
+ atf_check test -d "$cdir"
+
+ atf_check -o match:"^$tmpdir/footmp$" \
+ env -u TMPDIR mktemp -d -p "$tmpdir" footmp
+ atf_check test -d "$tmpdir/footmp"
+}
+
+atf_test_case tmpdir_pflag_noarg
+tmpdir_pflag_noarg_body()
+{
+
+ # Without -t, this time; this introduces $TMPDIR without having to use
+ # it.
+ tmpdir="$PWD"
+ atf_check -o save:tmpname \
+ env TMPDIR="$tmpdir" mktemp --tmpdir foo.XXXXXXXX
+ atf_check -o match:"^$tmpdir/foo\..+$" cat tmpname
+
+ # An empty string gets the same treatment.
+ atf_check -o save:tmpname \
+ env TMPDIR="$tmpdir" mktemp -p '' foo.XXXXXXXX
+ atf_check -o match:"^$tmpdir/foo\..+$" cat tmpname
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case tmpdir_env
+ atf_add_test_case tmpdir_pflag
+ atf_add_test_case tmpdir_pflag_dir
+ atf_add_test_case tmpdir_pflag_noarg
+}