[klibc] [PATCH 2/2] Add a relatively minimal mkstemp(3) implementation.

Thorsten Glaser tg at mirbsd.de
Sat Jan 29 09:31:35 PST 2011


Requires arc4random.  Debian: (Closes: #516774)

Signed-off-by: Thorsten Glaser <tg at mirbsd.de>
---
 usr/include/stdlib.h |    2 +
 usr/klibc/Kbuild     |    2 +-
 usr/klibc/mkstemp.c  |   76 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+), 1 deletions(-)
 create mode 100644 usr/klibc/mkstemp.c

diff --git a/usr/include/stdlib.h b/usr/include/stdlib.h
index 28c7150..74c9bf3 100644
--- a/usr/include/stdlib.h
+++ b/usr/include/stdlib.h
@@ -85,6 +85,8 @@ static __inline__ void srandom(unsigned int __s)
 	srand48(__s);
 }
 
+__extern int mkstemp(char *);
+
 /* Basic PTY functions.  These only work if devpts is mounted! */
 
 __extern int unlockpt(int);
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index 1138e6d..783ed69 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -47,7 +47,7 @@ klib-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \
 	  time.o utime.o llseek.o nice.o getpriority.o \
 	  qsort.o bsearch.o \
 	  lrand48.o jrand48.o mrand48.o nrand48.o srand48.o seed48.o \
-	  arc4random.o \
+	  arc4random.o mkstemp.o \
 	  inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \
 	  inet/inet_ntop.o inet/inet_pton.o inet/bindresvport.o \
 	  send.o recv.o \
diff --git a/usr/klibc/mkstemp.c b/usr/klibc/mkstemp.c
new file mode 100644
index 0000000..ef575da
--- /dev/null
+++ b/usr/klibc/mkstemp.c
@@ -0,0 +1,76 @@
+/*-
+ * Compact mkstemp(3)-only implementation, for klibc
+ *
+ * Copyright (c) 2009, 2011
+ *	Thorsten Glaser <tg at mirbsd.de>
+ *
+ * This file is available under the same terms ("historic
+ * permission clause") as klibc itself or under the terms
+ * of The MirOS Licence (dual licenced).
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+mkstemp(char *template)
+{
+	int i;
+	char *cp, *sp;
+	struct stat sbuf;
+
+	cp = template;
+	while (*cp)
+		++cp;
+
+	sp = cp;
+	/* generate random suffix */
+	while (sp > template && sp[-1] == 'X') {
+		i = arc4random() % (26 + 26);
+		*--sp = i < 26 ? 'A' + i : 'a' + i - 26;
+	}
+	if (sp == cp) {
+		/* zero-length template or no X at its end */
+		errno = EINVAL;
+		return (-1);
+	}
+
+	/* check the target directory */
+	cp = sp;
+	while (cp > template && *cp != '/')
+		--cp;
+	if (cp > template) {
+		*cp = '\0';
+		i = stat(template, &sbuf);
+		*cp = '/';
+
+		if (i != 0)
+			/* stat failed, pass errno */
+			return (-1);
+		if (!S_ISDIR(sbuf.st_mode)) {
+			errno = ENOTDIR;
+			return (-1);
+		}
+	}
+
+	while (1) {
+		if ((i = open(template, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0 ||
+		    errno != EEXIST)
+			break;
+
+		while (*cp == 'Z')
+			if (!*++cp)
+				return (-1);
+		if (*cp == 'z')
+			*cp = 'A';
+		else
+			++*cp;
+	}
+	return (i);
+}
-- 
1.7.2.3



More information about the klibc mailing list