mktemp(1) in /tmp or $PWD?

Garrett Cooper yanefbsd at gmail.com
Fri Feb 26 05:00:46 UTC 2010


On Thu, Feb 25, 2010 at 6:50 PM, Garrett Cooper <yanefbsd at gmail.com> wrote:
> Hi Hackers,
>    Really basic question (because I'm relatively new to the Unix
> scene -- only been using it for the last 10 years, so I don't know if
> this was done for backwards compatibility with SysV) -- is mktemp(1)
> without -t supposed to default to $PWD instead of /tmp if a template
> is specified, e.g.
>
> [root at left4dead /usr/home/garrcoop]# mktemp fooXXXXXX
> foovE3FLt
> [root at left4dead /usr/home/garrcoop]# ls foovE3FLt
> foovE3FLt
>
>    I ask because GNU coreutils' copy of mktemp (I know... I know...)
> defaults to /tmp if $TMPDIR isn't specified.

And this is the reason why I asked...

I was getting annoyed when I ran out of space in /usr today
iteratively trying to generate mfsroots because I expected the default
temp directory to be /tmp. Turns out it wasn't, and the reason why is
that $PWD is the assumed $TMPDIR iff an argument with -t isn't
specified.

So what I did was I wrote up a patch to be *I know... here it comes*
more like GNU coreutils' copy of mktemp.

Three behavioral changes I'm proposing are:

1. If mktemp is called without a prefix or template, it will
automatically generate one file (or directory) instead of erroring
out. That way if someone wants to call mktemp, they will automatically
get a file instead of having to produce a template or prefix.
2. $TMPDIR (or /tmp if not specified) will automatically get tacked
onto each file, instead of it being implicitly $PWD; that way a bunch
of temporary files will be generated _in_ /tmp (and subsequently wiped
on each reboot if the sysadmin sets it up that way) instead of having
a boatload of temporary files spread across a machine, which the user
must clean up based on the current working directory for their
applications.
3. All files will be prefixed with `tmp' by default instead of
`mktemp' (for consistency with GNU coreutils, and also because it
allows folks to increase the size of the random string in the files).

If folks like it, I'll create a PR with this change and also update
the manpage to reflect the change.

Thanks,
-Garrett

Index: mktemp.c
===================================================================
--- mktemp.c	(revision 204344)
+++ mktemp.c	(working copy)
@@ -48,6 +48,12 @@

 static void usage(void);

+#define MK_TEMPLATE(template) \
+	asprintf(&name, "%s%s%s", \
+			(tmpdir == NULL ? _PATH_TMP : tmpdir), \
+			(tmpdir == NULL ? "" : "/" ), \
+			template)
+
 int
 main(int argc, char **argv)
 {
@@ -55,13 +61,13 @@
 	char *tmpdir;
 	const char *prefix;
 	char *name;
-	int dflag, qflag, tflag, uflag;
+	int dflag, qflag, uflag;

-	ret = dflag = qflag = tflag = uflag = 0;
-	prefix = "mktemp";
+	ret = dflag = qflag = uflag = 0;
+	prefix = NULL;
 	name = NULL;

-	while ((c = getopt(argc, argv, "dqt:u")) != -1)
+	while ((c = getopt(argc, argv, "dqt:u")) != -1) {
 		switch (c) {
 		case 'd':
 			dflag++;
@@ -73,7 +79,6 @@

 		case 't':
 			prefix = optarg;
-			tflag++;
 			break;

 		case 'u':
@@ -83,16 +88,29 @@
 		default:
 			usage();
 		}
+	}

 	argc -= optind;
 	argv += optind;

-	if (tflag) {
-		tmpdir = getenv("TMPDIR");
-		if (tmpdir == NULL)
-			asprintf(&name, "%s%s.XXXXXXXX", _PATH_TMP, prefix);
-		else
-			asprintf(&name, "%s/%s.XXXXXXXX", tmpdir, prefix);
+	tmpdir = getenv("TMPDIR");
+
+	/*
+	 * User didn't specify anything; let's default to a file prefixed by
+	 * tmp*
+	 */
+	if (prefix == NULL && argc == 0) {
+		prefix = "tmp.XXXXXX";
+	}
+
+	/*
+	 * Make sure that the user specified an option with -t (or nothing
+	 * at all -- which equates to a file in tmp prefixed file).
+	 */
+	if (prefix != NULL) {
+
+		MK_TEMPLATE(prefix);
+
 		/* if this fails, the program is in big trouble already */
 		if (name == NULL) {
 			if (qflag)
@@ -100,44 +118,58 @@
 			else
 				errx(1, "cannot generate template");
 		}
-	} else if (argc < 1) {
-		usage();
+
 	}
-		
+
 	/* generate all requested files */
 	while (name != NULL || argc > 0) {
+
 		if (name == NULL) {
-			name = strdup(argv[0]);
+			MK_TEMPLATE(argv[0]);
 			argv++;
 			argc--;
 		}

-		if (dflag) {
-			if (mkdtemp(name) == NULL) {
-				ret = 1;
-				if (!qflag)
-					warn("mkdtemp failed on %s", name);
+		/* Just in case asprintf(3) ala MK_TEMPLATE fails. */
+		if (name != NULL) {
+
+			if (dflag) {
+
+				if (mkdtemp(name) == NULL) {
+					ret = 1;
+					if (!qflag) {
+						warn("mkdtemp failed on %s",
+						     name);
+					}
+				} else {
+					printf("%s\n", name);
+					if (uflag)
+						rmdir(name);
+				}
 			} else {
-				printf("%s\n", name);
-				if (uflag)
-					rmdir(name);
+
+				fd = mkstemp(name);
+				if (fd < 0) {
+					ret = 1;
+					if (!qflag) {
+						warn("mkstemp failed on %s",
+						     name);
+					}
+				} else {
+					close(fd);
+					if (uflag)
+						unlink(name);
+					printf("%s\n", name);
+				}
+
 			}
-		} else {
-			fd = mkstemp(name);
-			if (fd < 0) {
-				ret = 1;
-				if (!qflag)
-					warn("mkstemp failed on %s", name);
-			} else {
-				close(fd);
-				if (uflag)
-					unlink(name);
-				printf("%s\n", name);
-			}
+
+			free(name);
+
 		}
-		if (name)
-			free(name);
+
 		name = NULL;
+
 	}
 	return (ret);
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: more-gnuish-mktemp.diff
Type: application/octet-stream
Size: 3068 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20100226/e0018ae2/more-gnuish-mktemp.obj


More information about the freebsd-hackers mailing list