Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/freebsd/freebsd-src.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2022-10-31 06:55:46 +0300
committerKyle Evans <kevans@FreeBSD.org>2022-10-31 06:55:46 +0300
commitac6f924e1cd1ebd9832227e906ebc03e3ba5eede (patch)
tree0dff84188c50a77bba0b605f6b1f9e5bb3871233 /usr.bin
parentcfc57d7dbe5bff175ef6d508fecd6779c0a0d656 (diff)
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. Differential Revision: https://reviews.freebsd.org/D37121
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/mktemp/Makefile5
-rw-r--r--usr.bin/mktemp/mktemp.135
-rw-r--r--usr.bin/mktemp/mktemp.c46
-rw-r--r--usr.bin/mktemp/tests/Makefile7
-rwxr-xr-xusr.bin/mktemp/tests/mktemp_test.sh118
5 files changed, 201 insertions, 10 deletions
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 9240197e9129..a15e0d776c40 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,29 @@ 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");
+ break;
+
case 'q':
qflag++;
break;
@@ -100,10 +110,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.XXXXXXXXXX", _PATH_TMP, prefix);
else
@@ -120,7 +146,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 +190,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..1138c46ec1d0
--- /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:"^$tmpdir/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
+}