mktemp.c.patch   [plain text]


--- mktemp.c.orig	Tue Mar 30 22:56:07 2004
+++ mktemp.c	Tue Mar 30 23:39:22 2004
@@ -40,6 +40,7 @@
 #include "namespace.h"
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/syslimits.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <stdio.h>
@@ -106,13 +107,14 @@
 	int domkdir;
 	int slen;
 {
-	char *start, *trv, *suffp;
+	char *start, *trv, *suffp, *carryp;
 	char *pad;
 	struct stat sbuf;
 	int rval;
 	uint32_t rand;
+	char carrybuf[NAME_MAX];
 
-	if (doopen != NULL && domkdir) {
+	if ((doopen != NULL && domkdir) || slen < 0) {
 		errno = EINVAL;
 		return (0);
 	}
@@ -122,7 +124,7 @@
 	trv -= slen;
 	suffp = trv;
 	--trv;
-	if (trv < path) {
+	if (trv < path || NULL != strchr(suffp, '/')) {
 		errno = EINVAL;
 		return (0);
 	}
@@ -134,6 +136,9 @@
 	}
 	start = trv + 1;
 
+	/* save first combination of random characters */
+	memcpy(carrybuf, start, suffp - start);
+
 	/*
 	 * check the target directory.
 	 */
@@ -170,14 +175,25 @@
 			return (errno == ENOENT);
 
 		/* If we have a collision, cycle through the space of filenames */
-		for (trv = start;;) {
-			if (*trv == '\0' || trv == suffp)
-				return (0);
+		for (trv = start, carryp = carrybuf;;) {
+			/* have we tried all possible permutations? */
+			if (trv == suffp)
+				return (0); /* yes - exit with EEXIST */
 			pad = strchr(padchar, *trv);
-			if (pad == NULL || *++pad == '\0')
-				*trv++ = padchar[0];
-			else {
-				*trv++ = *pad;
+			if (pad == NULL) {
+				/* this should never happen */
+				errno = EIO;
+				return (0);
+			}
+			/* increment character */
+			*trv = (*++pad == '\0') ? padchar[0] : *pad;
+			/* carry to next position? */
+			if (*trv == *carryp) {
+				/* increment position and loop */
+				++trv;
+				++carryp;
+			} else {
+				/* try with new name */
 				break;
 			}
 		}